28 July 2013

Area (concave) triggers

One issue with physics triggers in game engines is that the volumes need to be convex. Say you have a river with lots of turns and curls. You may want to play a water sound effect when the player is near the water. It is impossible to create a trigger that matches the shape of the river, so you place multiple convex (box?) triggers all over the river, enabling the same sound. If it's a long and complex river, this can be a lot of work.

This is of course only one example, perhaps you have a complex dungeon with lots of turns, where you want triggers around the turns. You can create a box volume that envelops a complete turn, but that might overlap with other parts of the dungeon. You might create multiple volumes fitting the corridor and reporting their events to another single game object but that can get messy easily. It's also less efficient.

The engine of Divinity II uses NVidia's PhysX, so back at Larian we faced the same restriction. For that engine I introduced the concept of area triggers, an idea based on concepts that I used in my master thesis. Now I'm working on a game made in Unity and ran into a similar problem so I decided to rewrite the idea in Unity.

Problem at hand

In Unity, you can have a concave mesh collider as trigger, but it will only generate events for character controllers or rigid bodies with a sphere, capsule or box collider. Also, it will generate exit and enter events when the object passes through the surface of the trigger, and not the volume. So if a sphere passes through a concave trigger volume it will generate four events: an enter when it first touches the surface, an exit when the object does not touch that surface anymore (but the sphere is still inside the volume) and then another enter and exit when the sphere passes through surface of the trigger on the other side.

What we desire is a single enter and exit event, and correct stay events.

Proposed solution

In 2D, we have an algorithm that can decide whether a point is inside a polygon or not. The algorithm can be found here. So what I suggest here is that we create so called 'areas', existing out of a 2D polygon and a top and a bottom. To determine whether a point is inside the volume defined by the area, we simply need to check whether it's between top and bottom (easy out) and inside the polygon. When the physics trigger sends an exit/enter event we can now check whether it's valid. For an exit event we need to check if the position of the given collision object is inside the area. If it is, we remember the object as still inside in a list (the physics engine however believes it's not). For an enter event we need to check whether the collider is already registered and if so, simply remove it from the list.

This means there is only a small overhead we introduce for the exit event.

Code

The snippet below illustrates the idea. When the OnTriggerExit method is called, it is possible that the collider 'other' is still inside the area. If so, it is added in the 'insideObjects' list, else it is a genuine exit event and the message is translated into 'OnAreaTriggerExit'.

If an OnTriggerEnter event is received we first check if it's not registered as already inside. If not the event is forwarded as 'OnAreaTriggerEnter', else it is removed from the insideObjects list.

public class AreaTrigger : MonoBehaviour
{
 ...
   
 public void OnTriggerEnter (Collider other) {
  if(!insideObjects.Contains(other))
   this.gameObject.SendMessage("OnAreaTriggerEnter",other, SendMessageOptions.DontRequireReceiver);
  else
   insideObjects.Remove(other);
 }
 
 public void OnTriggerExit (Collider other) {
     if(ContainsPoint(other.transform.position))
   insideObjects.Add(other);
  else
   this.gameObject.SendMessage("OnAreaTriggerExit",other, SendMessageOptions.DontRequireReceiver);
 }
 
 public void OnTriggerStay (Collider other) {
  this.gameObject.SendMessage("OnAreaTriggerStay",other, SendMessageOptions.DontRequireReceiver);
 }
 
 public void Update() {
  foreach(Collider other in insideObjects)
   this.gameObject.SendMessage("OnAreaTriggerStay",other, SendMessageOptions.DontRequireReceiver);
 }
 
 ...
}

Creating these areas

While this idea turns out to be working just fine, we still need to be able to create these 'areas'. For that I wrote a custom editor. You simply create an empty gameobject and attach the area trigger script. All needed components will be added. With the game object selected, control clicking in the scene will add points to the area forming the polygon. Once you have three or more points a blue volume will be rendered. The points that make up the area have handles, so you can move the points of the polygon around (don't forget the 'Display Handles' option in the Inspector). You can also add and edit points in the inspector. To hide the blue volume simply disable the renderer.

The screenshot below illustrates how this looks.

Source

The source code of the area trigger class and it's editor script, all bundled up in a demo project has been placed on bitbucket. I'm open to all possible improvements and suggestions.

You simply open this demo and hit the play button, a sphere will start turning round through the area trigger and in the log you'll see the correct area trigger events being fired.

It's all open source and no license etc, but I'd like to know if you used this, just post me a comment or send me an e-mail. Questions are welcome!

14 February 2013

More games from Belgium

A bit less than a year ago I wrote a post about game development in Belgium. I said that the game development industry in Belgium is slowly growing. Today I say that it is growing a lot faster. Let me provide some more links.

First of, we now have "FLEGA" which is short for the Flemish game association. The intend is to support and group Flemish game developers and represent them on international game conferences, allowing for smaller game studios to be present on these events. I would have liked it to be a Belgian association, since "Flanders" is hardly known in the world and we are still Belgian, but it appears that even in our little sector there is some separation.

If you look at the directory page on the website the number of game developing companies and organizations has grown a lot since last year, compared to the list from Fabrice's website that I used last year as an overview of game developers.

Last year there was talk of funding from the Flemish government. They did as promised and now the project we're working on at Die Keure has received a piece of that budget, among others. Next deadline for projects is the 15th of April, more info can be found on the VAF website. It's a lot of paperwork, but they have very helpful people at the VAF.

I recently attended BETT to promote Monkey Tales Games. I learned there that many publishers and developers are "gamifying" education. I also learned that there are almost no decent educational games, the Monkey Tales Games are easily the best I've seen, without wanting to boast.
Technology will be omnipresent in the future schools, at least if I may believe what I have seen. Smart boards are smarter than ever, there are even motion tracking smart boards, and before we know it, every school will have several tablet classes (movable closets with 20+ tablets in them that replace computer classes). So there is a big fast growing market for educational games.
One thing is for sure in this market: the tablet will be the device of choice, so we better go mobile with our (educational) games.

It's exciting to see all these game companies popping up and creating games, to see that there are a lot of people attending the Global Game Jam and the Unity3D day in Antwerp, that the industry is coming alive. Cool times are coming!