All posts by Isak

When You Want to Have a Conversation: Dialorg

One of the absolute key parts of Ludus is the ability to interact with NPCs and participate in the Roman society from the perspective of a lanista. To achieve this we needed a competent dialogue system. I think anyone who has worked with dialogue trees will know what type of features to expect from that kind of tool, but with our emphasis on modability I think some of our decisions in the actual implementation might be different from some other games.

While we have developed quite ambitous plans for the ways you can interact with the NPCs in Ludus in addition to simple scripted dialogues which rely on what will hopefully be a pretty sophisticated AI – we still maintain that it is important to be able to create more tailor-made content which we can mix with the more spontaneous systems we’re attempting to develop.

Even though simulating almost everything fully is super awesome – if you sprinkle in some more set-in-stone-ish events, we can hopefully put the player in awe of what outcomes arise during the course of the game. It should hopefully also be hard to tell what was scripted and what was simulated, just that we would like to guarantee or at least make it more likely that interesting things happen no matter what.

ice-cream-bear

One way we can do this is to make dialogues that will push the simulation quite hard in a certain direction with the side effects that occur on certain dialogue nodes.

So that’s the justification for still having hardcoded dialogues in the game, but how do you actually go about authoring the dialogues?

Initially when we started we were using a tool called ChatMapper which is a fairly decent choice. But we soon realized that in order to actually export dialogues that the conversation middleware could use, every modder would have to buy a license. Since we care a lot about modders we decided that this was not acceptable so we got rid of both ChatMapper and the middleware. After researching alternatives, we set out to create our own way of authoring dialogues and our own dialogue system.

We wanted a plain text format that could easily be edited by hand and read with eyes (instead of toes!). A common choice for hierarchical data would be XML or JSON, but we’re not huge fans of those. As an Emacs user I soon had the epiphany that the Emacs Org Mode format would be quite nice for modeling a dialogue tree. It has nice properties such as not having to worry about closing tags or parenthesis for the tree nodes. Emacs comes with nice ways to edit and view it, which certainly helps, and we could add extensions to make it even nicer to edit. However if we have the time we might even put an editor for dialogues in the game itself.

2000px-Org-mode-unicorn.svg

Either way if you are not familiar with org-mode, you might want an explanation on how the format is structured! The way you write an org document is that you create a headline which you do by putting a number of asterisks (*) and a space, and then the name of the headline. After that you put a newline and anything you put below that will belong to the headline. Examples of things you’d put in the headlines are things such as paragraphs and source blocks and various attributes and such. The nesting level of the headline is determined by the number of asterisks before the name of the headline. Here’s a very simple example of a document:

* My headline
This is a pragraph that belongs to "My headline"
** My child headline
This paragraph is in a headline which is a child to "My headline"

Here's another pragraph, they are separated by two newlines.
*** My grandchild headline
This paragraph belongs to headline which is a child to "My child headline"!
** My second child headline
This is the second child to "My headline"
* My other headline
This headline is not a child of "My headline" it is a sibling.
** My other child headline
And so on!

It might be hard to read at first but again just pay attention to the asterisks before the headline title and you should be able to visualize the nesting. Emacs makes it much easier to visualize the nesting since you can turn on “org-indent-mode” which is very helpful. You usually indent the text under a headline in emacs but I stopped doing that when I noticed that it broke org-indent-mode which looks much nicer anyway. Even so, even without any indentation to make it more clear I find this format to be less noisy than something like XML or JSON. I think this format could be pleasant for other things than just dialogues, for example I think it could fit quite well as a plain-text representation of a scene-graph.

I mentioned that other than paragraphs you could put things such as source blocks and attributes under a paragraph. Let’s discuss the syntax of these a little bit. For source blocks we use the exact same syntax as Emacs org-mode, which looks like this

#+BEGIN_SRC boo
import UnityEngine
Debug.Log("Gonna set some values now in my boo script")
ludus.dialogue_state.likes_turtles = true
ludus.dialogue_state.hates_bacon = false
Debug.Log("Done setting values! :)")
#+END_SRC

If you have a keen eye you’ll notice that we explicitly say that the language for the source is “boo”, you’ll be able to use any language here that there exists a driver for, and even add your own language driver if your favorite is missing (assuming everything goes right). But that’s for another post about the scripting system!

yoink

Attributes have a similar syntax and can be put on their own or attached to another element in the headline’s section, such as a source block or paragraph. For example, we support an attribute called WHEN which you attach to a source block to specify when that script should run, a particularly useful stage to run a script is “condition” which can help filter out certain dialogue nodes if the script condition script returns false. An example could look something like this

* You were mean to the NPC
#+ACTOR: npc
#+CONVERSANT: player

I can't believe you said I'm lame. Dang you man.

#+WHEN: condition
#+BEGIN_SRC boo
script_return ludus.dialogue_state.were_mean
#+END_SRC

This example also shows the attributes ACTOR and CONVERSANT which, unlike the WHEN attribute, is not directly attached to an element of the headline – instead it is an element itself. What distinguishes an attribute element from an attribute for an element is the two newlines separating the elements, just like with paragraphs. The main thing that distinguishes an attribute element from a regular element is that you can’t attach attributes to attributes.

acting

That is really almost all of the syntax, the last thing that you might be yearning for is text substitution. Well for that you can use a macro language which again is just any programming language that has a driver for the scripting system. In order to set the property for what macro language to use you use what is called a “property drawer”. Which looks like this:

:PROPERTIES:
:MACRO-LANGUAGE: boo
:END:

Once you’ve done this you can use boo in order to evaluate any code that will in the end return a string for what should be substituted. Like this:

And that's the way {{{ script_return "it is!" }}}!

Finally in org-mode, headlines can have keywords prepended to them, such as TODO. We decided to adopt this for creating link headlines by adding the keyword LINK to designate that the headline is a link. The way you write a link is as follows:

** LINK my link headline
[[The title of the headline I am linking to]]

As you can see this means that it is good practice to name your headline something unique.

That covers basically most of it, there are other useful features as well such as running a script when entering and exiting a dialogue (and even individual dialogue nodes) for setup and cleanup etc. But this article isn’t really intended to fully document every feature of our dialogue format, but rather to introduce you to the basic ideas and principles on how we (and hopefully modders!) will write dialogues for the game. We suspect that the format will evolve over time so documenting everything right now would probably be time down the drain.

If you want to you can take a look here in order to read an example of a dialogue that I’ve been using for testing which showcases everything I mentioned in this post. It kind of lives in its own space for now in that it doesn’t have any real side effects in the real game, but it illustrates how you can arrange a dialogue – quite sloppily though because it was quickly thrown together for testing purposes, the result of running that dialogue (with a work-in-progress UI) can be seen below (click to maximize)! Thanks for reading!

dialoguehurhur

Resolving Missing Script References in Unity

Recently, I have been moving some of our important and core code out of the Unity Assets directory and instead compiling them in to a .NET dll. When I did this I encountered in to the issue of all the scenes and prefabs that were using MonoBehaviours from those scripts had lost their reference.

hillaryshocked

I found this surprising initially because I thought the references to components were simply using the .NET assembly name of the class with all the namespaces etc, perhaps in combination with something else to be able to track renames of classes. However it turns out that all it basically does is to put a GUID in the script .meta file which it in turn puts in the guid property of the m_Script field of the objects in the .unity scene files – along with a fileID property. The fileID property is always the same for scripts in the Assets directory, but it is different for every class in a dll – I suppose it uses this to narrow down the search for the assembly reference or something like that.

Now this is very little information to work with, so it’s actually harder than it should be to resolve these references. You basically can’t see the name of any script it was using or anything useful besides the GUID. When you look at the scene file you can even see that it has an m_Name and m_EditorClassIdentifier property, but it doesn’t fill them in! This is most likely why, when you look at a missing script in the inspector, it doesn’t even show you the name of it, so you have to rely on your memory to figure out what it was if you are going to fix it by hand – and I don’t know about you, but I certainly can’t do that. TL;DR the format was meticulously designed to break your heart.

ddcry

If you are in total panic right now, and don’t have any way to recover the meta files associated with your old scripts, then anything in this post beyond this paragraph won’t be useful to you. All the advice I can give is that you may be able to look in the scene files at the field names shown for the component and see how the variable names line up with those in your classes. Then you figure out what the new GUID and fileID for those are and edit it in there by hand. That will take quite some time however and I wouldn’t wish it upon my worst enemy. You could probably make some really fancy analysis program for recovery, and someone should maybe do so, but that would take a lot of effort. The best way to not end up in big trouble is to backup your stuff and put your meta files in version control. And also to use the plain text unity scene/prefab format (check the Editor Settings and/or rtfm). Do this, and the gods will smile upon you, or at the very least, I will.

I did look around a bit to see if someone already solved the problem, but pretty much the only “solution” I could find was scripts that would find the missing script references and let you assign them manually, which doesn’t help at all because you can’t get any hint of what the script was named so it’s only slightly better than checking every component manually by clicking on it. But that’s not good enough.

Expectasians-High-Expectations-Asian-Father

I managed to make a solution that does eliminate a large portion of the manual labor. There is still some set up that you do for every missing component, but it’s relatively small. I’ll describe the workflow first, and then tell you how it works internally. Finally I will share the script with you in case you don’t want to write your own.

You start out by figuring out which components possibly could be the ones that are missing. For me this was easy, I knew that the references went missing when I compiled things in to a DLL, so all I really had to do was to search through all of the source files for the DLL for lines containing “MonoBehaviour“. If you don’t know, then one thing you might do is simply to check the scripts from your recently removed meta files. Unity removes these automatically because it hates you so I can’t stress enough how it’s important to have them in version control. Once you’ve done that you can search through the file that the meta file was for in your sources for MonoBehaviours.

Now that you hopefully know which components likely went missing, and have those written down somewhere. You can create a fresh new empty scene, and have it contain nothing but an empty object containing just the MonoBehaviour you are currently fixing.

Save this scene – locate your meta file. Once you have done this, you are set up to run my script to fix one component in your entire project.

What you do is that you pass the script the meta file, as well as the scene you just set up and saved, and also one or more paths that it should search through for scenes and prefabs. It does this recursively so you don’t need to specify every subdirectory of every subdirectory etc.  Passing multiple directories is mainly useful if you have a huge Assets directory and want it to only look through “Assets/Scenes” and “Assets/MyPrefabs” or something like that. I just passed it “Assets” and it was fast enough.

goodenough2txt

What the script will then do is that it will read your meta file, and find the guid that used to be correct. Then it will read your scene file to extract what the new guid is, and also the new fileID. Knowing what the old fileID was is not important, it will simply replace the old one with the new one, it only needs to know what the old guid was to be able to locate it in scenes and prefabs. Once it has the data it asks you if the data seems to make sense to you, and if you answer “y”, then it will start replacing all of the old references for you. Here is a sample invocation of the script, cleaned up a little to remove some of the verbosity:

{ ludus } » racket Pipeline/fix-script-references.rkt ../../../oldludusmetas/CrowdDuplicator.boo.meta Assets/Scenes/FixReferences.unity Assets

I’m going to replace guid 79e4e0dfe8d9bf94b9622e6d68377772 with d79c0ede0316c2b429fad82aa7fc643f and set the file ID to 1803148156, is this ok?(y/n): y
Okay proceeding…
Found old reference(s) in C:\Users\usefulProgrammer\src\boo\ludus\Assets\ExperimentsArchive\drawcalltest\crowd.unity, replacing..
Found old reference(s) in C:\Users\usefulProgrammer\src\boo\ludus\Assets\Scenes\Crowd.unity, replacing..
Found old reference(s) in C:\Users\usefulProgrammer\src\boo\ludus\Assets\Scenes\CrowdPoses.unity, replacing..
<… and so on>

Done!

Once it’s finished you remove the component from the empty object in the scene and add the next component, save and change the meta file to the current relevant one. If you accidentally start mixing meta files etc then you will pretty much be screwed, so be careful with this. Also don’t forget to back up everything before you do this! Cool? Cool.

racketlogo

And that’s really all there is to it, I wrote the script using Racket, which was very pleasant. The script is available here under a CC0 license.

This process could probably be improved somewhat, for example you could script the editor to add all of the components for you and try to figure out which meta file it should look at etc, but that is definitely more difficult to implement and probably rather error prone. If Unity actually used the m_Name field or m_EditorClassIdentifier that they simply left empty – then it would have been less of an undertaking to automate this further. For me, going further than this would stop saving time for us in this situation, which is why I started writing the script in the first place. If we end up having a bigger catastrophy which requires really intense recovery then I’ll let you know what I do about it. But since we are using version control I suspect we won’t need anything more sophisticated than this.

I hope this post helped you out, or at the very least made you put your .meta files in version control because otherwise you could lose everything. See you next time.

fiiiiiiiiine

Prototypeception – A Prototype Within a Prototype

Since I joined the team we have been working hard towards a prototype that we can start showing off to people and iterate on. The plan is to have something usable by early next year. The codebase I was given was mostly made up of  concept code written by Vegard that only he could understand and use to describe what should happen in the various, cryptic scenes which showed nothing but numbers on a blue background.

One of the systems I’ve been reworking is the fighting system. Currently it is only a simple DnD D20 style system with modified rules that changes the way health and critical strikes work by using hitpoints and vitality (or as the original document calls them: vitality and wound points). In short: regular hits consume hitpoints, when all of the hitpoints are depleated you start losing vitality points, when all of the vitality points are gone, you are defeated – if a critical strike happens, damage skips hitpoints and goes directly to vitality.

The fighting system is completely independent of whatever you display on the screen, this gives us flexibility to try out different ways to present the fights to the player, without having to modify how the underlying system operates. In the beginning, the only visualization I had created for myself looked like this:

earlyfightinstructions

Note the intense effort I put in to change the default background color of Unity. This does not look like much but everything we needed was there, the gladiators were generated randomly and we could observe how different stats provided different advantages in fights.

A quick rundown of the interface: you don’t actually control any of the gladiators directly, the game is about managing gladiators after all, not playing as one. In the current state, the only input you have on the fight is the intensity of the fight. Basically, the gladiators go at each other for a few hits, then they stop, giving you an opportunity to shout instructions on how they should fight. If they fight with a high intensity they do more damage and the audience also gets more excited. If they take it easy the audience will find it less interesting but you also don’t risk exhausting – or even killing one of your gladiators. The gladiators are not equally good at taking instructions, it is based on both your and the gladiator’s stats. In some cases, the gladiator will even do the opposite of what you asked them.

The next step was to build a more stimulating interface for the system. I started by taking the animations that Vegard had been working on and making it possible to trigger them from code. I also grabbed the crowd agents and some colour correction from previous scenes and  with a little effort, I had something that was looking like this:

croppedluduspink

Sometime around this point I had the idea of trying to set a milestone for making a prototype that we could show off on the London Indies Pub Night in December, which was about one and a half week away. The other guys liked the idea so we decided to go for it.

Of course, just standing on a regular boring plane with the crowd just cheering normally isn’t fun enough. So I picked a random texture laying around (that had nothing to do with ground) and slapped it on there and made the crowd do a wave. Just for fun!

fightwithwaveomgsocoolandpink

These strange naked manequinn men fighting in pink space was pretty interesting to view but the time had come to put some actual gladiator meshes in there. At this point I had also added the hitpoint and vitality bars instead of showing numbers:

pinkspacegladiatorwithhealthbars

At this point it was also less necessary to display character attributes on the screen since a lot of them show quite well in the generated character mesh. For example if they are stronger and have a higher constitution they will appear larger than weaker gladiators.

After this I added sliders for controlling intensity as well as stamina bars. Following that I put the arena in there with proper ground, changed sky color and some tweaks until we had something that was pretty displayable for the pub night:

dodgecrowd

Note that during this entire time, the underlying fight system was always the same as the pink – text on the screen – interface in the first screenshot. This type of software design can be very practical in that it lets you swap the presentation layer without changing the logic of the system it’s running underneath.

Now for us, this is far, far from what we want the final product to be. But even this got quite a good reception and got people excited about seeing the game progressing forward. Having a nice milestone like this allowed us to narrow down just the things we needed to meet our “deadline”. It helped us avoid unnecessary yak shaving and reveal what yaks needs to be shaven the most after showing off the prototype. We can also move on to other components of the game such as the roleplaying aspects, knowing that we already have a placeholder for fight resolution that we can iterate on later.

What you should take away from this article is just how useful (sluggish?) it is to set up moderately sized, achievable goals, which, as a bonus, can be used as a nice ice breaker to talk about your game and what it will be while still coming off as credible. It will hopefully keep you from over-engineering systems that you don’t yet know what they should be and make quick decisions that will do for now.

At the very least, you will hopefully experience fun moments where your game displays funny or interesting behaviour. A lot of accidentally artsy screenshots were taken during the development of this prototype . Some of them you can enjoy below.

sofuckinghipster

PerformanceArt2

sphereopening