Unity as a level editor

I recently came over the problem to involve artits and game designer to the new Pokemon3D content. Every middle to big range indie game is going to face the problem having a fancy level editor. There are different ways to handle this, let’s see what are possible scenarios:

Human readable formats

C’mon guys, this sucks. We are over it…. For a small prototype or hacking it is ok, but for more…forget it!

Import from exported editor format

Some editors can export their data into a custom, human readable format – like Tiled. It is an acceptable solution to support these export formats because you can encourage other people using an existing tool.

I tested this extensively in a small zelda clone I implemented using the löve framework and Tiled. It can export lua-files directly which is a really cool thing. Furthermore, you can define custom properties and custom object layers with properties to describe your level.

tiled custom maps

custom maps with custom properties

When you export your map to lua you get something like this (shortened):

This is a valid lua which can be loaded, and processed with a single line of code.

With the custom object layer and custom properties to any objects you can add behaviors and attach custom objects which can be easily read. The only disadvantage may be the fact it can be a bit “messy” with to many custom objects, as everthing needs to be known how it is named. But I was surprised how well this worked and I saved the time to write custom editor as well!

Editor Plugins

This can be some kind of cool extension regarding to a existing editor. This depends on your editor (and its API Documentation!) A very good example the Unity editor. A not so good example is IMHO blender, I don’t find this API kind of clear and easy.

Own editor

This can be the most confortable way for artits and content creators, but is often super expensive to develop. You may have the best workflow for the game but it is an expensive, handly crafted solutions you have to maintain the same as your game.

 Solution: Unity

I decided to use Unity because I love the usability and that it’s used by a lot of people. From there I had to different ways to implement the export.

YAML Conversion

My first try was to use the yaml-scene file and import it using a custom command line tool. To be honest: I think YAML sucks as hell. It is told to be clear to read and extend, but I feel a bit confused about the syntax. After trying out loading the file with YAML.NET – which was impossible because Unity yaml files uses features which has not been implemented yet in YAML.NET – I stopped using this method.

Editor-Plugin

This was the solution which feels like took me to the right way: The Editor API of Unity is written in C#, so you can write new plugins super easy and you are able to use the classes from the runtime like game objects, components, meshes,  materials and assets. The solution gave me the following toolset for a game level designer:

  1. Having Unity installed, import a custom package (containing the plugin)
  2. An extea Window is available for exports with properties for settings like target folder
  3. Create Your Scene using Unity as usual
  4. When ready, press export
  5. After progress finished, I can directly start the game and test my level!

export

After pressing export, I all models are saved with the entity definitions in json with optionally exporting the models in my custom format for superspeed loading. Lets see how I have implemented this cool plugin!

HINT: I did not expose all the source code because I did some refactorings and I want to highlight important things for your usage. To see the full implementation of it take a look at github: https://github.com/nilllzz/Pokemon3D/tree/master/UnityExport/Editor

Having your main entry class

To provide a Unity plugin, you need to create a C# Script file inside a folder called Editor. It does not matter where this folder is, you can even have multiple of them in different paths. Open the created file to get started!

Create a Window

There are several ways providing plugins, I have chosen to create a custom window you can show like the inspector. Your editor class simply needs to inherit from EditorWindow and provide a static class for a Menu Item to create it:

This creates a Menu Item in Unity for Window -> Pokemon Map Export. When you save your script file you should already be able to open an empty window.

Create Window Content

To create content you use IMGUI with OnGUI() Method:

You can look up the code using the Unity documentation for IMGUI. It is I think straight forward. All the field with underscore are private ones of the MapExporter class. The interesting line is the one with ExportScene(). Here, the whole export process is started.

Show a Progress bar

We now will take a look at ExportScene(), which of course does the most interesting export. But lets simplify this first and think about usability: This export will take severals seconds depending on the scene size. Let us show a progress bar and close it after finishing everything:

Isn’t it deadly simple? Showing a Progressbar and in all cases the exports finishes (even in error situations) the progress bar disappears. If you want to try out now, just insert in the try block some Thread.Sleep() and see how cool this is!

Creating Json Objects to serialize

For my use case, I have to serialize my data to json-files and optionally custom mesh data, so I defined some classes I can serialize directly. Here is my root class:

Of course the other types like BattleMapDataModel are also classes which are marked as Serializeable. When I transformed all the Unity objects to my data, I can save my data this way to the file system:

Process Data

The last step is to process my Unity scene, iterate over the game objects and convert my relevant component information to the serialization classes. I would like to highlight the most important things you need to know about.

As Unity treats your scene as scene graph you need to get all the game objects by accessing the root objects:

SceneManager is a static class of the Unity runtime. This line of code is the entry point for getting everthing of the scene. For my purpose, I simply need to get all game objects as list and not as a tree, so I write some code to iterate the tree and get a flat list of all game objects:

The method AddGameObjectAndProcessChildren() gets a game object, adds it to the provided list and invokes a recursive call to the child objects. It is important to know you get the child objects using the mandatory transform component and usingTransform.GetChild().

The next step is to iterate over all game objects and analyze its components. I am just interested in game objects which has a visual representation, so this game object needs to have a MeshFilter and MeshRenderer. So to get all the relevant objects I did this:

If you already worked with Unity you will see this is like writing code for a game. This is something I totally loved.

Process Data – Extract Transformation

One of the most important data is getting the transformation. This can be more tricky you will think because of your coordinate system. If you use a right handed like me in MonoGame, you need to flip some information. To be honest: I tried it out until it worked. It may depend also on your imported models.

Transform as a parameter is the transform component of my game object of interest. I converted it to my serializable classes and returning it to add it in my own data structure hierarchy.

Process Data – Extract referenced 3D Mesh

the second important information is to get the mesh and material referenced information. I needed to reexport the referenced model as a file to my target system. I also added the option to convert the Unity model to my custom model format, but I can also just export the existing model file. Therefore you have to get along with the AssetDatabase class. This allows you to find referenced files like 3d models. You just need to get this from your meshfilter component:

By getting the AssetPath from the MeshFilter attached mesh you can get the reference to the model file and do whatever you want. I simply reference the path and later I allow to copy the referenced model file to the target folder optionally. I use the ?? operator to get mesh, which is sometimes the shared and sometimes not, one of them will not be null.

The second option was to convert the mesh file to an optimized format which can be loaded directly with binary readers. This is super fast and solves all the importing problems in the game with mesh formats. This is also super simple, I was able to export it in very short time to a custom binary format:

I just needed the vertices, normals and 1st level UVs with the main texture from the material, so this is everything to convert. I store the referenced texture from the material as a relative path in the model file by using AssetDatabase as well.

Create a package and add some prefabs

After implementing my features in a Unity project, it is super easy to create a separate package. This allows others to use my solution by simply importing a whole package. This is done by choosing a folder from your asset hierarchy and pressing right mouse button on it -> export package.

Before I did this, I added some prefabs so the game designer can test its solution. I created a player with a camera in the scale of the in game – so the designer can simply drop it in their scene and see if its scaling fits to the game. Of course you need to exclude these game objects from your export ;).

Source code

You can find the complete Unity package in github: https://github.com/nilllzz/Pokemon3D/tree/master/UnityExport/Editor

Summary

You can create your own editor or extend existing ones, but you need to think about what is the right tool for you. For me using Unity was a super choice and I can recommend this for a fancy map export.

My soluation is very simple: of course you can use more components like colliders or rigid body for your system or even export script contents.

Compared to develop a whole editor from scratch, It took me about a half a day to get this run as expected.

If you like, share this article or give a comment on twitter.

Implementing a collision trigger system

The current problem I am thinking about is a collision trigger system. This is something different than a collision system so I needed to implement it in a separate way. The basic idea is adapted from the trigger system of unity. First of all: what’s the difference between a collision and a trigger?

Collision

There are an amount of objects which has a defined boundary which are not allowed to touch or intersect each other.

Collision also is tightly bound to their response. So you need to think about what will happen when two objects collide. You need to separate them and maybe one or both of them needs to respond by bouncing off. The problem is, you cannot generalize this, as this depends on your use case. For example in a jump ‘n’ run game you are usally want to jump against a wall and stay the closest to it – not bouncing off. If you implement a pool game, the balls of course needs to bounce from the borders or the other balls with friction. But this can be handled by defining this behavior in your collider with certain properties.

Trigger

There are an amount of objects which has a defined boundary which are allowed to touch each other, but this information is notified to listers.

There is no collision response, the objects which collides by triggers stay in their new position. The clue with this system is the notification: OnEnter, OnStay, OnLeave. OnEnter is called once when the contact started, OnStay is called in the next frame after OnEnter when the contact is yet present and OnLeave is called when the object had contact but now don’t have any more.

Use Cases for Triggers

When I came across this idea I thought is a perfect solution for – as the name implies – trigger based events in a game. For example if the player passes a door, you would like to spawn an enemy. A naive implementation would be to check the player position and when he passes the first time a specific z-coord, spawn enemy and save state in a bool. Nah, this is nasty. It would be way cooler if you define a trigger inside a door, which is a boundary like a collider. When the player contacts the collider, you get an OnEnter() notification, which can spawn the enemy. This is generated ONCE the contact has begun. You can go even further and you can deactivate the trigger so this will exactly happen once. This is so amazing!

There are of course a lot of diffent cases where this comes handy. You can define a sphere trigger for an enemy which reacts OnTriggerStay() to behave different when the player is near to the enemy.

Implementation

For the first view I thought this is trivial to implement – and basically it is. But the more I think about it I get different considerations about the details. The basic problem is to find out:

  • Is it a new colliding object?
  • Is it an already colliding object?
  • Is any colliding object lost?

For each update of the trigger system I need to update this for all triggers AND all colliders. This means all potential collision partners for triggering needs to save their partners from last contact update in a list. Imagine we checked two objects and they collide. Now we need to match the cases above.

Is it a new colliding object?

This is simple. You need to check if this is an object you collided last time by checking the list. If not, it is a new contact and you can fire OnEnter().

Is it an alread colliding object?

This is also simple. If the previous check failed and it is not a new contact it must be an existing contact and you can fire OnStay()

Is any colliding object lost?

This is something more interesting. You cannot check this when a collision happens. You can only check this after all collision checks. All collision partners which were not new and are not colliding in this frame got lost.
So you have to mark all contact partners as “has been touched this frame” and all remaining objects can be removed from the list and fire the event OnLeave().

Handling deleted / deactivated objects

The last thing is to handle disabled triggers. For all the three cases you also need to think about what is going to happen when any trigger or collider is disabled. For new collisions it is trivial, as you simply skip the check. The interesting part is when the trigger is registered somewhere in a collider or trigger and now it is disabled. I think there is no right solution but you need to define the behavior. I found the following ideas:

  • call OnLeave() always. This is a simple solution but may be sometimes a bad idea when this trigger has a real OnLeave() action connected.
  • just ignore. This is also possible but what happens when the trigger gets reactivated? It would continue to detect as OnStay(). You may remove it from the list to avoid this.
  • Have a separate Event called OnDeactivated(). This seems to be a good idea, but does not solve the problems regarding to the already detection state.
  • Just remove from all lists. This seems to be a good way to handle it properly. When a collider or trigger is disabled just remove them from all detection history.

So when you have some kind of C# the collision manager will may handle it this way (Please not it is pseudo-C# and totally untested, but you get the idea though):

I think the code is relatively clear. It checks all possible collision partners and HandleTriggerEvents() take care of event notification and states. Afterwards remaining Objects needs to be removed and OnLeave() called. This method may look this way:

 

Identifying collision partners

Imagine of the Events has been fired. You can register to this notification and found a trigger event has been fired. This is great but you also need to find out which trigger / collider has triggered. So you need to mark your colliders with some kind of extra attributes. The simplest way would be to attach a string tag which is compared during the notification. This is a simple solution and I think it will work in a lot of environments. Another idea would to be able to attach to each collider a user data object which can be checked to a type during runtime. I don’t like runtime checks of types as this seems to a bit “blind”. Furthermore you also need to attach some kind of identification to your user data object which is some kind of more complicated as the direct string tag solution.

Summary

It seems to be a good idea that all colliders and triggers have a list of collision partners from last collision update to find out if it is a new or existing contact. When an collision update is ready we can check untouched objects, mark them as Left by removing them from our lists and calling OnLeave(). When an object is disabled it is good idea to remove them silently from the collision lists to avoid unwanted notifications.

A new blog starts…

Blogs about game development are not rare so far. I think a lot of them are writing blog entries as a reminder for themselves or getting some order in the mess of your head – which is absolutely ok. The same belongs to me!

I am working as a full-time software developer for different kind of software, especially for .NET and in the future for web applications.

So why this blog? The answer is totally easy to answer: I play games, and I develop software. For both I have a lot of passion. Some of you may ask why I don’t work for the gaming industry, as this would fulfill my dreams. Several years ago, I thought about this and the plan was to become a game developer. But I had some arguments, which really makes me think about this idea.

The first persons who were against this idea were my parents. They told me “learn something useful”, “what will be the case when you can’t get a job for games but for other IT systems?”, “Games don’t give you high salaries…” and so forth. Maybe your parent did tell you same and you feel bothered. I was thinking the same way and I focused on this topic by learning as much as possible about game development.

Some years later I started to join one of the biggest german messes for indie game developers: the Dusmania. Today it is called devmania and is in Mainz every year. I really love this mess as I can talk to people having to make the same decision as I have to. It was (and is!) amazing. I met a very cool guy who lives in Berlin. We try to meet every year if possible, as I really like his way he arranged with game programming. He gave me his advice, which I follow up to day:

Don’t develop games as a job. You may ruin your hobby because you have to develop games. Create games in your free time and do what you want when you want. You are never forced and you can decide what YOU want.

I followed this idea and I have to say: he was deadly right. I know some people working at game development studios which were great indie developers before and now lost their passion a bit. Maybe you will come to the same solution and I guarantee: you won’t lose anything.

To sum this up: What’s this blog about:

  • Games
  • Software Development
  • Technical Articles
  • Events

If you like to follow this blog I would really appreceate. If you have wishes I should write about you can write a tweet on twitter