Building Adventure Game Puzzles is fun. This is a very complete breakdown of creating a bathroom scene with its puzzle in under 2 days! (Spoiler alert!)

This a pretty massive post, that contains the complete workflow for this scene, ranging from prompting the images to building the puzzles and creating the VFX & SFX. Usually I would split a post like this into a few parts, but this puzzle and location came so quick and I wanted to write the whole thing while it was fresh on my mind!

The bathroom scene puzzle breakdown

For the bathroom, I needed a scene with a washing machine. As this was the core of the puzzle. Apart from that the scene needed an entry point from the side.

Prompting

I started on this location in April. Prompting some variations of a simple bathroom I could use.

Building Adventure Game Puzzles, location variations
cyberpunk dirty apartent apartment bathroom interior with door to different room, morning, wide angle, hdr masterpiece adventure game –ar 16:9

I landed on this version of the location. I had to run the upscale again on it to access the vary region tool.

Selected location starting point
cyberpunk dirty apartent apartment bathroom interior with door to different room, morning, wide angle, hdr masterpiece adventure game –ar 16:9

As usual, the new upscale changed things quite a but for the better for the most part.

Reupscaled location starting point
cyberpunk dirty apartent apartment bathroom interior with door to different room, morning, wide angle, hdr masterpiece adventure game –ar 16:9

Now that I had re-scaled the image, I had access to the Vary Region tool and could start to edit the scene.

Edits / overpaints

Midjourney vary (region)

Building Adventure Game Puzzles, location editing to match requirements
Vary (region) editor on Discord

I used the Vary (region) tool to replace the door with a shower unit. It was not important for the story, but I wanted the player to enter from scene right, as it matched the apartment floor plan better, because I needed to stay mindful of how the outside windows would line up with the rest of the apartment.

Building Adventure Game Puzzles, midjourney location final stage
A shower added. Also zoomed out 1.5x.

After the vary, I added a 1.5x zoom out to add more floor real estate.

After a bit of tinkering I found out that Midjourney would not add a door on the scene right for me no matter what. So I had to turn to Adobe Photoshop generative fill for that.

Midjourney location finished up in adobe photoshop
Final image from Photoshop

I also mixed in the washing machine from the very first, original Midjourney generation as I liked it better and it had this electrical box I could use as a puzzle element. I used generative fill to remove the box cover and add some wiring inside.

I also created a shadow pass version of the scene at this point.

Shadow version of the bathoom scene
Bathroom scene shadow pass

Now the scene was ready for modeling!

3D

This scene was a bit problematic. fSpy wanted to flip the scene upside down no matter what I did. This is the first time I ran into this kind of issue. I fixed it by flipping the scene in Blender, but I would have appreciated flp Z-axis functionality directly in fSpy.

fSpy perspective plotting for the finished midjourney bathroom location
Perspective plotting in fSpy

The Bender portion of this scene was a little bit different than before too. This scene would have some animating doors and I did not want to unpack the FBX prefab, so I built all the hinges and hierarchies already in Blender, so I could animate the elements in Unity without changing anything.

Building Adventure Game Puzzles, simple 3D geometry for the midjourney bathroom location created in blender
Scene in Blender with pre-set up hierarchies

The doors to the electrical box and the washing machine turned out all wonky, as the shapes were distorted in the Ai generated image. I did not worry about this too much. I wanted to see them in-game before I decided if they needed to be fixed or not.

Unity

Building Adventure Game Puzzles, the location geometry in Unity
The scene layout in Unity

The bathroom scene is connected to the back room of the kitchen, so I imported the mesh for that room into the bathroom scene. I wanted the back wall of that room to be visible from within the bathroom.

Building Adventure Game Puzzles, hotspots and navigation in Unity
The scene setup in unity.

In the final game view, the open doorway ties the room to the kitchen area.

Building Adventure Game Puzzles, fiished scene screenshot in-game
What happened here? The scene seen from the game camera.

Scene animations

The scene had some simple animations. Opening hatches and spinning laundry. For the hatches, these animations were super simple. The electrical box door was animated to open and close with keyframes so I could have the door swing and bounce properly, this door could be opened multiple times so I wanted it to be nice.

The washing machine door only had closed and open states, I did not animate it, the door simply transitions between 2 keyframes with animation transition. This is only opened and closed once, so it does not matter that much.

Midjourney spy blender washing machine insides trick

When the machine is on, laundry can be seen tumbling in it. For this, I simply created a cylinder and applied the scene image to it as a material. When it is spinning behind the glass, no one can really say what it is they are looking at!

Building Adventure Game Puzzles

This room had a bit of a complicated scripting set-up, as I needed the main puzzle of the room to have a couple of stages.

The rest of the text contains game spoilers! I am not shying away from explaining this puzzle, as it is the very first puzzle of the game and made especially easy! But spoiler alert!

Planning

I have to admit, I did not plan this puzzle too much. I added the bathroom to the apartment on a whim. Originally, you were not supposed to have misplaced your maglev ticket. I always figured you would simply find it from your apartment. But the apartment felt like it had a good spot for the bathroom.

I had been thinking of adding a bathroom earlier, but I was just spitballing locations back then.

I remembered those bathrooms and figured what if the player has forgotten his maglev ticket into his pocket and his clothes are in the washer? That could be a good puzzle, how to get the ticket from the washer?

One of the locations I had generated had a washer in it, so that seemed like it could work. The image also had this weird maintenance hatch on top of the washer. At this point I had no idea what you needed to do in order to stop the washer from running. Maybe you needed to unplug it, hit it with something, pry open the door?

But as I looked at the electricity box, I decided that the player needs to manipulate this box somehow. Initially I just had an “interesting item” that you found from the yard and it would stop the washer when combined with the electricity box. But Lauri Konttori (the story consultant) just told me to put pliers into the game and have that be the item. I was overthinking it.

Once the pliers were in, I knew I wanted to do something extra for the stopping of the machine. I wanted to add an explosion.

But as you see, this puzzle was not pre-planned. I simply added a location to the apartment and looked at the AI generated image and tried to think what sort of puzzle could happen in this location? This seemed to be a perfectly valid way of making a puzzle into the game!

Changing the use interaction

The puzzle in this room is that you need to access the washing machine. In order to do that, you need to make the washing cycle stop. naturally the machine can not be stopped. So you need to figure out a way to force it to stop.

Building Adventure Game Puzzles, adventure creator action list
The action list that runs when you try to plan the washing machine door

Spoiler: you need to cut off the power to the machine by unplugging it’s wiring, but you need a tool to do that.

The washing machine hotspot is set up with multiple use interactions. The one enabled at the beginning takes you to the fail state shown above. Once the electricity is cut, the fail state is disabled and the interaction with success state is enabled.

Building Adventure Game Puzzles, adventure creator action list
Building Adventure Game Puzzles, adventure creator action list
Changing the interaction of the washing machine door in Adventure creator

There are multiple ways of changing the use interaction result. But I find this is the cleanest way.

For the changes to be permanent, you need to add Remember Hotspot -component to the washing machine door, so that the changed use state persists after china changes and is stored in the save file.

Moving the player

Adventure creator’s built in tools for moving game objects did not work for me. They were not unable to move players, for whatever reason. I bet there is a way to make them work, but I was too lazy to figure it out and I ended up making a custom solution instead.

Building Adventure Game Puzzles, adventure creator custom action
Custom action to move a game object in the scene
Action_MoveTowards.cs
/*
 *
 *	Adventure Creator
 *	by Chris Burton, 2013-2023
 *	
 *	"ActionTemplate.cs"
 * 
 *	This is a blank action template.
 * 
 */

using UnityEngine;
using System.Collections.Generic;


#if UNITY_EDITOR
using UnityEditor;
#endif

namespace AC
{

	[System.Serializable]
	public class Action_MoveTowards : Action
	{
		
		// Declare properties here
		public override ActionCategory Category { get { return ActionCategory.Object; }}
		public override string Title { get { return "Movetowards"; }}
		public override string Description { get { return "move a gameobject to a world position"; }}


		// Declare variables here
		public Transform _target;
		public Transform _puppet;
		public Transform _ObjectToMove;
		public float _speed = 1.0f;
		public bool isPlayer;
		public int playerID = -1;
		public int parameterID = -1;
		public int constantID = 0;
		public GameObject linkedProp;

		public override void AssignValues(List<ActionParameter> parameters)
		{
			if (isPlayer)
			{
				Player player = AssignPlayer(playerID, parameters, parameterID);
				_ObjectToMove = (player != null) ? player.Transform : null;
			}
			else
			{
				_ObjectToMove = _puppet;
			}
		}

		public override float Run()
		{
			/* 
			 * This function is called when the action is performed.
			 * 
			 * The float to return is the time that the game
			 * should wait before moving on to the next action.
			 * Return 0f to make the action instantenous.
			 * 
			 * For actions that take longer than one frame,
			 * you can return "defaultPauseTime" to make the game
			 * re-run this function a short time later. You can
			 * use the isRunning boolean to check if the action is
			 * being run for the first time, eg: 
			 */
			if (_target != null)
			{
				isRunning = true;

				// Check if the position of the object to move and the target are approximately equal.
				if (Vector3.Distance(_ObjectToMove.position, _target.position) < 0.001f)
				{
					isRunning = false;
					return 0f;
				}
				else
				{
					// Move our position a step closer to the target.
					var step = _speed * Time.deltaTime; // calculate distance to move
					_ObjectToMove.position = Vector3.MoveTowards(_ObjectToMove.position, _target.position, step);

					return defaultPauseTime;
				}
			}
			else
			{
				isRunning = false;
				return 0f;
			}
		}

		public override void Skip ()
		{
			/*
			 * This function is called when the Action is skipped, as a
			 * result of the player invoking the "EndCutscene" input.
			 * 
			 * It should perform the instructions of the Action instantly -
			 * regardless of whether or not the Action itself has been run
			 * normally yet.  If this method is left blank, then skipping
			 * the Action will have no effect.  If this method is removed,
			 * or if the Run() method call is left below, then skipping the
			 * Action will cause it to run itself as normal.
			 */

			 Run ();
		}


#if UNITY_EDITOR

		public override void ShowGUI(List<ActionParameter> parameters)
		{
			// Action-specific Inspector GUI code here
			isPlayer = EditorGUILayout.Toggle("Move Player?", isPlayer);
			if (isPlayer)
			{
				if (KickStarter.settingsManager != null && KickStarter.settingsManager.playerSwitching == PlayerSwitching.Allow)
				{
					parameterID = ChooseParameterGUI("Player ID:", parameters, parameterID, ParameterType.Integer);
					if (parameterID < 0)
						playerID = ChoosePlayerGUI(playerID, true);
				}
			}
			else
			{
				_puppet = (Transform)EditorGUILayout.ObjectField("Gameobject to move:", _puppet, typeof(Transform), true);
			}

			_target = (Transform)EditorGUILayout.ObjectField("Gameobject to reach:", _target, typeof(Transform), true);
			_speed = EditorGUILayout.FloatField("Speed:", _speed);

		}

		/**public override bool ReferencesPlayer(int _playerID = -1)
		{
			if (!isPlayer) return false;
			if (_playerID < 0) return true;
			if (playerID < 0 && parameterID < 0) return true;
			return (parameterID < 0 && playerID == _playerID);
		}*/

		public override string SetLabel ()
		{
			// (Optional) Return a string used to describe the specific action's job.
			
			return string.Empty;
		}

#endif

	}

}

This script takes the player, or a game object in the scene, and moves it towards another game object at certain speed. The current iteration of the script does not have tweening. I will add it in later once it is required.

In the actionlist, as the character begins to move, I trigger an animation of him flying backwards. This animation is downloaded from Mixamo.

Unity animator setup
Animator setup for the backwards tumble

The fall back and get up animations are separate clips, stitched together and blended to minimise seams.

Using Items

To make the washing machine stop, you need to use the pliers on the electrical wiring. You can access the electrical wiring at any time, but in order to advance, you need to use the pliers on the wiring. In theory this should cut the electricity to the machine.

Prompting

I prompted the pliers graphic with Midjourney.

creating items in midjourney
Bunch of different pliers variations.

I chose the first image as the Icon for the item. I also used the same graphic in the game screen to visualise the pliers in-game.

Removing the white background

To remove the white background, I used a feature built in OS X. It is an AI feature, so it fits within the theme!

osx remove background
Remove Background in OS X

So, there is this feature buil-in to Mac OS X that allows you to isolate the main subject from an image. You can access it by right clicking in the image, going to “Quick Actions” and from there to “Remove Background”.

This feature is also built in iOS and iPad OS. You can simply hold on a subject on an image to generate the mask and get a version with alpha. it works surprisingly well!

OSX remove background before and after
Original and edited version

For these inventory icons, this quick OS X trick works just perfect.

Scripting

Adventure Creator makes my life so easy! There are built in tools for achieving almost any result. Adding item interactions is very easy, just select the inventory item you want the interaction to work with and add the interaction action list.

Building Adventure Game Puzzles, adventure creator inventory interaction for hotspot
Hotspot + item interaction in Adventure Creator

The action lists for these interactions quickly grow quite unruly. So they are hard to visualise. For this case, I did want the player to be able to perform the action multiple times, as it was so much fun to see the result. So this list has a different result if you do it for the first time, or the second time onwards.

Building Adventure Game Puzzles, adventure creator action list
Pliers + Electric witting interaction action list

For all the doors in the scene, I use IK to drive the hand to the door. I have set up these IK targets for everything intractable so that the arm goes to the right location. Often times simply the IK targeting is enough without any actual interaction animations. I use this for many pickup events and door open / close events.

Usually the flow goes: hand IK on -> trigger door open animation -> wait ~0.7 seconds -> hand IK off.

Explosion setup

I was already using Zibra Effects for a lot of smoke and steam, so I though it was time to add some fire to the mix!

SDF colliders

Building Adventure Game Puzzles, zibra fluid simulation collider setup
SDF collision meshes

I had to add quite a bit of colliders in to the scene. The more I followed the shapes of the room and added details, the better the smoke interaction with the surroundings got.

Colliders with Zibra are very fast and cheap, as they are using their proprietary AI accelerated SDF data. This also makes it possible to use very performant skinned mesh colliders.

Forces

In addition to the colliders, I needed some forces. I had 2 emitters in the scene, one for the fireball and one for the residual smoke. For the fireball, I added quite bit of outwards momentum, but not so much for the smoke.

To add motion to the smoke and not have it look tubular as it squeezes out of the box, I added a random force field right at the opening. This serves to mix the gases as they appear so it breaks up the shape and makes the smoke and fire. look generally more interesting.

To trigger these smoke effects on cue, I had built a custom action that I can plug into Adventure Creator.

Building Adventure Game Puzzles, zibra fluid simulation adventure creator setup
The Explosion action list

I spiced up the explosion with some camera shake and some electricity VFX.

Electricity Particle Effects

The explosion also needed electricity. I wanted to move quick, so I went to Unity Asset Store to see if I could find a pre-made set of electricity VFX that was URP compatible to use as a starting point.

Sure enough I found one pretty quick. It was not the most amazing set, but it did not need to be. The only thing I was after was some pre-made textures and particle systems. For 20 bucks, I figured it was worth the time saved.

I combined multiple effects from the pack to form the effect that I was an after and also added an animated lens flare to the mix. I also wrote a very quick destroy myself script that would delete the effect prefab with a bit of a delay from the scene after it was spawed.

Electrical Explosion SFX

To get the sound effect I was after, I downloaded and explosion and electrical buzz sounds from Pixbay.com. I uses Adobe Audition to combine these into a single sound.

Combining sounds in Adobe audition
Electrical Exploion multi-track project in Adobe Audition

The sound is then triggered with all the other explosion effects. It is using the washing machine sound object as a source. The washing machine audio source is in spatial mode, but I have tweaked the falloff curve to make sure the sound is beefier.

This turned out to be a massive update, containing everything from the prompting of a scene to building the final puzzle. This whole scene took me about 12 hours to create, starting from prompting to final product. I am very pleased with that speed. Even with my limited time available for this project, I should be able to craft a substantial amount of gameplay and locations for this project!

In the future I plan to keep these updates shorter…

Leave a Reply

Your email address will not be published. Required fields are marked *

Recent Posts


Archive


Social Links