Building A Stealth Game — Helping Your Guards “See”
How to implement a very simple method of player detection
In this article we continue working on our simple stealth game in Unity. A “stealth game” is a game where we seek to achieve our objectives by avoiding contact with the enemies rather than fight them.
This particular game will be a variation on “The Great Fleece” project from GameDevHQ. This project is a collection of assets put together with the express purpose of being the aid for learning cinematography and building a basic stealth game.
In the last article, we learned how to use Unity’s navigation features to have our AI enemies “patrol” a route. But a patrolling guard is of little use if it can’t spot intruders like the player. In this article, we are going to learn a simple method for letting them do that.
Repurposing the Collider
As you might guess from the header, what we’re going to do is make use of the Collider feature to “see”. This is not a perfect approach, and we’ll get into the downsides later, but it is a very simple method and can work quite well in some scenarios.
We start by finding our guard object and adding a cube object to it. Feel free to add a different object, such as a cylinder or capsule, if you feel it more appropriate. Whatever object it is, there will be a matching collider on it by default.
Next, reshape and position your new object relative to your guard object. For instance, imagine your guard object is modelled after a human being. You would then probably want your new object to extend forward from the front of the model out to a reasonable distance.
Finally, we need to set the Collider to be a trigger by checking the Is Trigger box, and we need to add a Rigid Body component to the guard object and make sure that the Rigid Body is not using gravity.
With these settings configured, we can now go ahead and remove the mesh filter and renderer components of the “sight” object so that it is no longer visible. We’ll still have the Collider exactly as we formed it already.
In the script
So at this point, the guard object is detecting when other colliders are crossing the path of its “vision”, but we haven’t yet told the guard what to do about it. This will be done in the script.
If the guard object does not already have a script, create one and attach it to the guard object. Within this script we now need to create a new method — OnTriggerEnter. This method fires when the parent object’s Collider intersects with another object’s Collider, so long as one of the objects has a Rigid Body and only one of their Colliders is set to be a trigger.
OnTriggerEnter is a void method, and takes one Collider-type parameter. This parameter represents the Collider component of whatever object has been collided with. Through this parameter, we can access the Collider’s parent object and do all sorts of things.
Here’s the method signature:
private void OnTriggerEnter(Collider collider)
The problem is this method fires for every collision that occurs. For what we’re attempting to do, we’re only interested in collisions with the player object. A good technique for this is to examine the tag on the collider parameter.
If you, for example, gave the player object a tag of “Player”, then we could have a line in our method checking if the collider parameter’s tag matches. If it doesn’t, then the code doesn’t run.
if (collider.tag == “Player”)
What does the guard do?
We have our Collider set, and our script is set up to only run code when it collides with an object with the “Player” tag. The guard has noticed the player, so now what?
Well, that’s up to you. There’s any number of ways we could proceed from this point, from a change in the guard’s behavior to an immediate game-over.
I mentioned earlier that we would discuss issues with this approach. As we can see, it’s a very simple approach and easy to set up. So what’s the issue?
For starters, it’s a very rigid method of perception. We are forced to make a certain solid shape to represent our guard’s vision, and it’s all or nothing. The player is either seen or completely unseen. Also, since this method has nothing to do with actual visibility, things like cover or shadows are not taken into account at all.
This is not to say this method is worthless, but we must pay attention to the scenario in question to determine if this is the correct approach to use.
This is a very simple and basic method of detection that may not be right for every situation, but is a good place to start thinking about how our AI characters can search for and find things they’re meant to look for.
In the next article, we’re going to iterate on this idea a bit and see what we can add to this approach by building some security cameras for the game. Until then, thanks for reading.