XML – The Dialog System’s Bread and Butter

I knew that we needed to write our dialogs outside of Unity, because it would be way to much text, and editing and keeping track of text within Unity is a pain. I knew from previous experience that XML is used a lot in Unity and AAA games but I only had very basic insights on how to use it. I researched on my own for a while and had a few different approaches based on tutorials from the Unity wiki or some other sites.

what other two words start with F and Y ?
Very first test, just to see whether I could get Unity to read my file
xml with conditions and nodes
Attempt at a variable system, when we hadn’t decided on the InventoryItem system we are using now

For the first few tests I was using the Unity XmlSerializer and I noticed that it had quite a few flaws that would make my work more annoying. For once I had to write three scripts just to read the file properly. I also found out that the serializer only goes to a certain depth of tags, which meant that I would have to create a different XML file for each character, so we would end up with quite a few files.

too many files
One script contains the Class “DialogString” another script is used to store multiple DialogStrings and the third script actually reads the XML-file

So eventually I decided to ask Markus, my programming professor, for help. I was quite happy to hear that my approach wasn’t absolutely terrible, but he recommended reading the XML file “directly” instead of using unity’s serializer. He gave me an example Unity Project which explained the method very well, so I could quickly implement it. Now I needed only one script to read the file, and I could put all dialogs in one single XML file too! I had already revised the XML file after our decision on the InventoryItem approach so I only had to tweak that a little bit.

Template and Example of a PlayerTopic (aka DialogItem aka InventoryItem)
The structure of the final XML file, the different tags refer to different methods that will be called by the reader

I then wrote a prototype Scene for it, using a few buttons and textfields to test whether it was all working as intended.

I know it's pretty disgusting
Lots of beautiful, beautiful, debug text

Finally, this is the core method for reading the XML-file.

GiveNpcItem
Go through the XML file and search for the NPC name, then for the item name, and then do something for each element in that item. Also features a default answer of the item is not found

Now we only had to implement this in the main project. That’ll be a whole other post though.

Skinning Test on coolguy – Game Arts

Today I started with Skinning a model that Pierre made, the coolguy_prisoner (was there a character like that?). I’m happy I get to apply the skills I learned from Fridi during our Profil² Woche!

Oh there he is
Oh there he is

After shortly struggling to find the mesh in the file that Pierre provided I got to work. I hadn’t done anything in maya for a few months now but it was surprisingly fast for me to get back into the controls! I quickly created a few joints along the spine and the left arm just to test whether I still knew how to do this at all!

Frontal with bones
Frontal view with bones

I tried to let Maya do the skin weights for me but apparently I can’t be that lazy…

Not how you raise your hand...
Not how you raise your hand…

So I got to painting the skin weights myself. I wasn’t sure where to start, so I had to try around a bit, but eventually I just flooded the first child of the Arm, the Clavicle with all of the weight for the arm and then went from there. I did pretty much the same for the Spine too.

The model had a pretty complicated structure, with a few hollow areas like the jacket on the arm, which resulted in some weird glitches.

Better?
Err…

I’ll keep in close contact with Pierre (I’m talking to him right now) in order to optimize our workflow! Eventually I managed to get nice weighting, and it actually looked pretty good for the short amount of time!

Hands in his pocket
Cool dudes keep their hands in their pockets.

As a final test for my rig I made a short animation. Thanks for reading 🙂

Dialog and Inventory System – Game Design

Our game is a detective game, we want the player to think while playing, and be able to solve the mysteries themselves instead of being presented the solution at the end of the game. We want investigative dialog and freedom of choice in what they want to ask.

How does the dialog work?

Instead of a set of dialog options for every character, we decided that you should be able to talk to every character about anything that might be relevant. So for example you could talk to a character about another character you met, or maybe about where to get alcohol to fill a bottle of booze. We drew some inspiration from Ace Attorney here where, in similar fashion, you can present an item to the court in order to highlight a discrepancy of a witness’s testimony.

Ace Attorney Objection!
Ace Attorney Objection!

In the beginning we thought about how to limit the amount of things you can talk about. In Ace Attorney, you can highlight any part of a witness’s testimony and try to find a mistake in it. However we knew that we couldn’t allow the player to talk about absolutely everything, because that would require us to write ridiculous amounts of dialog!

We were all agreed on an Items Category, which would contain the different physical objects the player may have with them. We also knew that we had to include persons and locations. For a while I also tried to bring in a sort of “abstract” category, which would contain ideas like money or alcohol or power, and phrases like “the don said I would get a free refill”.

Categories draft
First draft of how the categories could look

However in the end we found out that we could make that much more intuitive by combining items, like “empty booze bottle” + “the Don” + “Barkeep” to tell the character about getting a refill from the barkeep.

So after 2 meetings and lots of discussion about abstracts and physicals and topics, we came up with three final categories of InventoryItems:

Items, physical objects the player has, like an empty booze bottle.
Persons, the characters you can talk to, like the Don.
Locations, the unique places of the noir world like the bar.

How does the inventory work?

The inventory is closely related to the dialog, so you’ll already have an idea of it, but we still had to find a way to design it visually!

What was important to us was, like the environment, make it feel good in VR. We liked how the interaction with the environment felt, so we wanted to see how we could do that for the inventory too. The solution was to make the inventory behave pretty much the same like the interactable objects in the world. The InventoryItems would spawn when you opened the Inventory, and you could grab them and move them around and -to be implemented- have them float around you in zero gravity. To give the Item/s to an NPC in oder to talk about them, we would need some kind of container to collect them in, and then give the container to the NPC.

Inventory Visual Draft
First visual draft for the inventory

For the first draft we came up with a ring around the player that displayed the different items. It looked very sci-fi so we moved on from that soon. As of writing this (June 21st) we are still not 100% set on the visual look of the inventory, as we got some negative feedback from the intermediate presentation, but intend to make it fit the noir style!

Programming Session June 3rd&4th with Felix Schade

On June 3rd Felix Schade and I sat together to get started on the VR controls for our Game. Although it’s not absolutely necessary for our game per se; we wanted to allow the player to interact with most of the items in their environment, because that’s what players will attempt to do when they first enter a VR game. I had thought of different approaches beforehand, but eventually we decided on the simple childing method for loose items. For hinged objects (like doors or levers) we didn’t do any controls, because we don’t plan on having anything of that sort in the game.

The Controls-system went through a long iteration process. We used the standard Unity SteamVR Plugin from the Assetstore and followed this tutorial for starters. However since the endresult from those tutorials still have a few shortcomings, we still had lots of work to do.

The Object Hierarchy of our CameraRig
The Object Hierarchy of our CameraRig

This is the resulting GameObject Hierarchy for our CameraRig. As you can see there are two Controllers (left&right) childed to the CameraRig GameObject. The way we wrote the code is that each of the controllers works independently from the other, so you could theoretically play with just one controller.

 The Components of each of the Controllers
The Components of each of the Controllers

Each of the Controllers has these Scripts on it: WandController, InputManager, InteractWithWorld and Teleporter (not implemented yet). They also have a child GameObject which has a Spherecollider (trigger) and the GrabSphereCollDetection Script on it. There is also a ModeManager Script attached to the Camera(eye) GameObject which deals with changing between the noir and the real-world look. All Grabbable items must have the InteractableObj Script, and the “Interactable” tag on them, as well as a rigidbody and a collider.

So how do you grab something?

The position of the controllers are tracked by the Plugin, we didn’t have to write that ourselves. So; you move the controllers to the item in virtual space. The Spheretrigger enters the collider of the interactable object, and the object is saved for this sphere (controller).

GrabSphere OnTriggerStay
GrabSphere OnTriggerStay Method

Now you press the GripButton. The GripButton is the button labled as 8 in this image. There is a GripButton on both sides of the controller, but they behave as one Button.

Vive Controller Buttons
Vive Controller Buttons

The WandController Script checks for that Input (and others) in the Update function, and then makes it available to other Scripts as public bool variables.

WandController CheckInput
WandController Update Function, Checking for Player Input

Now the InteractWithWorld Script takes action. This script is the main script dealing with grabbing objects.

InteractWithWorld GrabStuff
InteractWithWorld GrabStuff method

In the Update function it checks for Input on the GripButton. If the GripButton is pressed, and there is an item in the grabsphere, and the controller is not already holding an object, the object will be grabbed. Also, if the object is already held by the other controller, the other controller will lose connection with the object (DeleteFromHand). The following steps are necessary to grab the object: the rigidbody is set to a velocity of zero and it stops using gravity. Additionally the object is parented to the grabSphere, which is parented to the controller, so now the object directly follows the position and rotation of the controller.

If the GripButton is released while holding an Object, or if the Object leaves the collider of the sphere (outOfSphere), the Object shall be dropped.DropStuff DeleteStuffFromHand and ThrowReleasedObject Methods

When the Object is dropped, it’s parent will be reset to its initial value (just null at the moment), gravity will be enabled again, and all references of the object will be removed from the wand controller (DeleteStuffFromHand). However before the references are deleted, the object will take on the velocity/angular velocity of the wandcontroller, so you can actually throw objects. After trying several of our own approaches on throwing, and none of them working as intended, we eventually found this method from thestonefox and used that. Now you can pick up an Object, move it around, and throw it away. We also made it so that objects cannot go through other objects, so when you move your hands through a virtual wall, the object will get stuck on it, and eventually fall from your hands. Furthermore we made it so that when you switch between real-world and noir mode, you drop those objects in your hands that do not exist in the other mode.

Check out the Tech-Demo Video we made here:

Adventure Time with Felix & Snoopy

I was bringing my girlfriend home -she lives a few hundred metres away- and we happened upon my cat, Snoopy. He joined us for the rest of the way, and even met my girlfriend’s parents. After saying goodbye to her I decided to go on a little adventure with Snoopy.

I had been on adventures with him before, just wandering about the area, stopping whenever something seems interesting. They always ended quite soon though, either because I had something to do or because he entered someone’s garden and I didn’t want to be charged with unlawful entry. This time was different though. I was in the mood to walk around, it was still warm, and I had time. Usually Snoopy takes the lead when we go exploring, but this time he just sat around so I started moving instead.

Snoopy in the shower
Snoopy likes weird places

I noticed this before, but Snoopy is a huge Tsundere! Whenever he follows me somewhere, he doesn’t just stick to me. Instead he tries to walk parallely through someone’s front garden, or a few metres behind me. This is especially funny when I walk around a corner and he runs after me, trying to catch up, only to abruptly slow down when he sees me waiting for him.

What made this adventure truly special for me though, was I gained another follower! A shy cat who I’d seen before, but who never let me pet her(him?) was suddenly a few metres behind Snoopy and trotting along for just a few steps before lying down on the road. I didn’t want to force it along and also I thought Snoopy might be jealous, so I kept on walking.

Shy follower cat around 10.30pm
The shy cat

After turning a few more corners with Snoopy I suddenly saw a flash of white running into the fence, and upon closer inspection saw a small hole in the boards. It was the same cat as before, and when I moved away from the fence she came out and sat down in a “respectable distance” away from me and Snoopy. Snoopy appeared to be heightening his senses, so I joined in and just observed the fields in front of me and listened to the sound of the current in the power cables above.

Shycat's hole in the fence
Shycat through the hole in the fence

While Snoopy and I were relaxing like that, the other cat kept changing it’s position, so I left my shoes where I sat (I had taken them off a while ago) and moved away a bit. Soon after, she moved over to where I sat and examined the area. After another while of enjoying the night Snoopy and I moved on, and the other cat followed us for a bit, before turning back. Snoopy and I went home, and I was inspired enough from this experience to write this Blog post 🙂

Semester Project BA1: Dreams of Pan

sleeping-pan

Dreams of Pan is a 2D puzzle platformer. You control Pan, a boy with a vivid fantasy! You accompany Pan on a journey through his dreams, where you will have to protect him from the dangers that his troubled emotions bring! As Pan falls into deeper sleep stages, you will uncover emotions he has hidden away; Fear, Sadness, Anger! In the first level, the core emotion is “happiness”. Pan doesn’t have much to worry about yet, but the game will gradually get harder!

Dreams of Pan was the first Semester Project I did in the Cologne Game Lab from December 2015 to February 2016. I worked with Anna, Caterina, Patrick and Taylan on this.

Download it HERE, or watch the gameplay video on Youtube HERE.

READ MORE about the dev process!  

The Final Presentation – Process and Afterword

I was personally rather dissatisfied with how our last presentation turned out, granted we didn’t spend enough time on it, due to me being plagued with serious migrane on the day before, when we met to work on the presentation. So this time we decided to start working on it a lot sooner, so we met after our Group Mentoring Specializations on Wednesday, January 27th.

The first piece of the presentation was a document by Anna, who had written down some of the most important things that need to be in the presentation. We then had the idea to “put the presentation in the game”, which at that point was limited to simply making slides, and showing them in the prototype while walking past it and talking about it, much like a normal presentation would be.
After we didn’t get to work on the presentation as much as we planned to on wednesday, because we prioritized the prototype, Patrick started working on the presentation after we went home, orienting himself on Anna’s document.

Friday

I spent most of my working time on Friday intending finishing up the Mentos-ColaLake puzzle, and make it easy for Patrick to implement in his project files. During this time Patrick worked hard on making the presentation as cool as possible, quickly moving away from the “show slides next to another” to the experience that it eventually turned out to be. We gave him feedback whenever a question came up, like how the artists want their assets to be placed, or how he should word some things, but didn’t really get to see what the whole thing looked like until the day after. While the rest of us went to bed between 1am and 2am, Patrick had worked through half the night, uploading the project files for the presentation at 5am!

Saturday

On Saturday, the first thing I did when I saw the project files was simply starting the “game” and walk through the presentation. You can imagine my surprise when there was suddenly no floor, and Pan kept falling “deeper and deeper and deeper…”! I was extremely impressed with the work Patrick had done, so of course the first thing I did was nitpicking ! I went through the presentation a few times and noted down everything that I felt could be improved, and how I would do it. I also read the syllabus a few times, to make sure we include all the important things. We had a lengthy skype conversation we anna also went over the presentation, to add her feedback to mine.
While Patrick was working away on implementing the changes (it was past midnight by then), I had to work on the ColaLake-Mentos level again, because the way I did it before didn’t quite work out, the platforms were to small, or the lake to wide, so I had to add a third platform, and redo the animation for the second one. I finished that up until 3am, and tried implementing it in the project I got from Patrick and it worked as intended (with minor issues).

Sunday

Sunday was long for me!
Patrick and Caterina started chatting at 12am, I joined a bit later and Anna as well, and we continued optimizing the presentation.
We were still missing something for the “reflection on development process including a detailed project plan”, as we weren’t entirely sure how we should best convey it all. Eventually we decided to use the Project Plan as a timeline to show what happened.
First I went through all of our chat histories (Skype and Whatsapp) and added mot important dates to the project plan, writing them below the timeline, so one can quickly see what the plan was, and what actually happened. I realized that it was incredibly bland to look at, so I decided to remove some more of the less important dates, color coded everything (production, design, art, programming) and made the more important dates even more visible. I finished up with the Plan at half past midnight.

Versions 1, 2 and 3 of the Project Plan Show

After taking a small break, I wrote a script (performance) for how we could do the presentation. For this I once again walked through the presentation a few times, and wrote down what exactly I would say, paying close attention to how long each part would take me to say. Along the way I noticed a few more things I’d like to change, and those were implemented the day after. I was done with this script at 4:30am, quickly uploaded it to our dropbox and fell right into bed.
The script I wrote for the presentation, we mostly stuck to that!

Monday – Presentation Day!

We had decided to meet at 10:30am on Monday morning, to put the finishing touches on the project files/presentation, decided who said what, and make sure the timing works out as planned. Anna wasn’t quite happy with the gameplay portion of the script I wrote, so she changed it to point out some more things that I missed. She also wrote down things the artists could mention about their process, as I as a non-artist couldn’t think of anything.
Caterina was also fighting, as she had to deal with a terrible migraine, but she managed to still do the presentation without a problem!

Feedback

I was very happy with how our presentation turned out, and the feedback we got was mostly positive too!
However we made one major mistake, which is the part of the gameplay we showed.  We just started at the beginning and showed how it all looked in-game, and since the beginning of the game is rather unexciting, it didn’t make as much of an impact, and didn’t show as much of the game that it could have! Instead we should have shown the ColaLake puzzle, even if that meant skipping most of the level before.

We also received good feedback for the game, most notably that the environment feels “dead”. We hadn’t noticed that ourselves, but I knew what was meant by that, there is not much movement in the background, almost everything is static. We’ll work on that after wednesday, until the 19th.

Throwing stuff and respawning changes

I’ve mainly been working on two things at the moment, which is coding the throwing for the last puzzle and a proper/pretty respawning process. Both are not 100% polished yet, but they work, and I’m confident that they won’t make any trouble implementing.

Throwing

For the throwing we decided on using a kind of gauge that decides the angle, so the player will need a mixture of planning and timing skills to throw the m&m in the right angle. Here’s the result first:

Things that are still TODO with this mechanic:

-limit throwing speed (rof)
-finetune positioning of angle-gauge
-use proper animation of Pan
-how to leave the throwing state
and the rest of the puzzle itself, the mentos stalactites, platforms and fountains!

The throwing mechanic mainly consists of two pieces of code, the first in the “PlayerInteractScript”, and the second in a “ThrowableScript”. As well as an animation for the red “Aimer” line to bob up and down, and a short animation for the m&ms to shatter.

Below is the relevant code from the PlayerInteractScript:

Screenshot_9

There are two interactions that deal with the throwing. The first is for entering the throwing state, which currently just starts the “Aimer” animation and enables the second interaction. The second interaction does the actual throwing. For this it uses the transform.positions of two objects which I manually placed at the beginning and the end of the “Aimer” line, subtracts one from the other, and uses the resulting vector to provide the direction for the throw, which uses normal Unity 2D Physics.

Next is the “ThrowableScript”. This script is attached to the m&ms that Pan throws. The Script simply detects collision with any object, and reacts accordingly. “TargetMentos” will be the object the player has to hit in order to solve the puzzle. When the m&ms hit any object (except the player) they will be triggered to enter the “Shatter” animation state, which is directly followed by the “AnimDone” state. Once in this state, the object will destroy itself through its Update() function.

Screenshot_3

Respawning

We hadn’t thought much about how we would do the respawning/death animations, but anna and I suddenly got the idea of “falling down the map and then falling on respawn from above”, and Patrick later expanded on it with the idea of the blackscreen to smoothen the transition between locations. So for this I had to redo the whole death/respawn/reset-progress code AGAIN because it wouldn’t look nice as it currently was. But I managed to reduce it a fair bit. Even then, it still looks like a bit of a mess, but to me it makes the most sense like this. The code for this process is almost entirely in the “PlayerInteracScript”, and I’ll go through that in the order the program would go.

The first method is Kill(), which is called by anything that can Kill Pan (like the chocolate River), giving the ‘killing object’ to the method via constructor. This method primarily disables the level-floor’s collider causing pan to fall through the ground and sets the trigger for the camera’s ‘DeathZoomAnimation’. It also causes Pan to do a little jump, and sets the global variable deathCause.

Screenshot_61

 

After the CameraZoom has completed its animation it calls this function:

Screenshot_52

It instantiates the blackscreen and puts it below the player, directly below the area the camera can currently see. It also sets the deathBlackScreenInstantiated bool to true, which sets the Update() function in action next and destroys the colldier that made pan go up, causing him to fall down from now on!

Once the blackscreen has been instantiated, and now that pan is falling, the Update function will let pan fall until a certain point, where the camera only sees the blackscreen, and calls the HandleRespawn() method.

Screenshot_10

The HandleRespawn() method reenables the floor collider, so pan can land again,  and calls the appropriate ResetProgress and Respawn functions (see below).

Screenshot_82

Respawn() simply relocated Pan and the blackscreen to the pre-set respawn location.

Screenshot_7

ResetProgress() resets all progress behind the specified respawn point to it’s default calues.Screenshot_4

And here is the result (you may want to watch it twice, first the Game-view, then the Scene-view):

The Ghost of the Player-Object

This is a really strange bug I experienced, which I don’t entirely understand. To me it felt like a ghost story and I’d really like to share it with everyone, so I’m trying to make this as easy to understand to non-coders as possible!

Screenshot_3

This “KillZoneScript” is attached to a river, which is supposed to kill the player when they touch it. It does two things: The first is that it find a reference (basically a hyperlink) to the  Player-Object when the game is started. The second is that -when the player touches the river- it tells a script that is attached to the Player-Object to run a method in it, which will do the actual death animation etc of the Player.

Now while I was working on implementing an improved death animation of sorts it bugged out -the Kill method wouldn’t be called- , so I did some reconnaissance:

Screenshot_6

Using lots of print functions, and trying to make the program tell me exactly WHAT happens and WHERE the bug is located, I found out that the reference to the player was wrong. This version of the method told me the object it was referencing is named “Player(Clone)” instead of “Player”,as it should be named. So I started suspecting that I might accidentally have tagged another object as “Player” which would explain this problem (the other object would be found instead of the correct one). Eventually, I made the program find all the GameObjects tagged as “Player” and tell me their names:

Screenshot_1

I learned that there were indeed TWO GameObjects tagged as “Player”, which are the “Player(Clone)” (gobjo[0]) that I noticed was weird, as well as the Object named “Player” (gobjo[1]), which had to be the correct object!

Now here is where the story moves from being like any annoying bug hassle to being a ghost story: The “Player(Clone)” object was nowhere to be found! In Unity, ALL objects are displayed in the so called “Hierarchy”, as below:Screenshot_7

And no matter what I did, searching manually or through the search function, whether it was while the game was playing or not, the “Player(Clone)” object would not show up!

I had one idea left, which I thought would serve to confirm my suspicion of the “Player(Clone)” object to be the one to ruin my code, so I changed the method to delete that object:Screenshot_8

Since I knew that “gobjo[0]” contained the evil Clone-Spirit-Demon, I made the method destroy that object during play, so I could see whether that would allow the rest of the method to work. I didn’t quite figure out yet how I would fix it in the long run, since anything that happens during play will be reset once the game is stopped. However as it turned out, I didn’t need to! Mysteriously, the “Player(Clone)” object was destroyed, and remained gone even after leaving play-mode!

And so the spirit of the Player-Object was banished to the depths of the GarbageCollector, and was never heard of again (?).

This was a bit of a weird post, but I really felt the need to share this. I hope I could entertain some of you, maybe even someone that is not an experienced coder!

 

Follow up, 4 days later:

Short follow-up:
The cloning happened again, while we were in a group meeting, and I eventually found out that the cause is somewhere in the mechanim (this user had a similar problem)
It can be fixed by just restarting the editor (how boring :P)