It’s time to break out…

December 8, 2009
by Nathan Whitehouse (nw08)

…the pathfinding algorithms.

Working on A* to navigate the waypoints.

Then on summarizing it here.


Finding your way about

December 3, 2009
by Nathan Whitehouse (nw08)

I’ve rehauled the entire waypoint system to allow more intellegent navigation of an indoor environment.

The waypoint system I had before simply said ‘if you can’t find the player, just loop around these waypoints until you do”. That’s alright when the AI has a large field of vision, or is near the player, but in an indoor environment with multiple paths and many barriers, that just doesn’t cut it.

Here’s a shot of the current system. It’s probably about 80% done:

What you see here is a small section of the level I’m using to test navigation. The textures are slightly random and all very free. Hence the goofy fluorescence. Scattered throughout the level are waypoints. They show up in the editor as cubes of various colors, but they are invisible in the actual game. Waypoints are grouped into ‘paths,’ marked by color. Each waypoint stores information about itself, such as what path it is in, its position in that path, and what paths are connected to that waypoint.

Waypoints are split into paths for several reasons. The prime reason is that it allows the AI to reach a specific destination much more quickly. If the AI is alerted to the player’s presence by an alarm (something which, in this system, would be extremely easy to implement), the AI can figure out how to get to the player from even a great distance away. It simply checks what path the player is on, then, if the AI is not on that path, can check the nearest connected path, until it figures out a route and begins traveling it.

It’s not quite working yet. I’m having some problems keeping the AI from getting confused if it sees the player, chases him, and then loses sight. It should just grab the nearest waypoint that leads to where it lost sight of the player, and travel along that path, but oftentimes it grabs an impractical waypoint as its target (at one point I was crashing the game with a possibly infinite loop. Oops).

Other minor tweaks abound, too, including tighter movement for the enemy more suited to indoor environments.


Never did get around to mentioning this

November 4, 2009
by Nathan Whitehouse (nw08)

Never hurts to give this a mention, but I’d just like to note that all code on this blog, unless noted otherwise, is by Nathan Whitehouse. Just send a heads up if you’re going to use anything posted here.


What are we looking at?

November 2, 2009
by Nathan Whitehouse (nw08)

This is the code in the enemy AI script that tests whether the enemy can see the player or not.

<pre>function findPlayer(){
var hit : RaycastHit;
var distanceToPlayer : float;
directionToTarget = theTarget.transform.position – transform.position;
directionToPlayer = thePlayer.transform.position – transform.position;
distanceToPlayer = Vector3.Distance(transform.position, thePlayer.transform.position);
var targetAngle = Vector3.Angle(directionToTarget, transform.forward); //for vision
var playerAngle = Vector3.Angle(directionToPlayer, transform.forward);
Debug.Log(playerAngle);
Debug.Log(distanceToPlayer);

if(Mathf.Abs(targetAngle) < visionAngle && distanceToPlayer < visionRange){
Physics.Linecast(transform.position, thePlayer.transform.position, hit);
//Debug.Log(hit.collider.name);
if(hit.collider.name == thePlayer.collider.name){
canSeePlayer = true;
theTarget = thePlayer;
}else{
canSeePlayer = false;
}
}else{
canSeePlayer = false;
}
if(distanceToPlayer < hearRadius){
canHearPlayer = true;
theTarget = thePlayer;
}else{
canHearPlayer = false;
}
if(canSeePlayer == false && canHearPlayer == false){    //This has to ultimately be the final else
canSeePlayer = false;
canHearPlayer = false;
FindNextWaypoint();
}
}</pre>

There’s a fair amount of Unity mumbo jumbo in there. In the beginning, I define the variables I’ll need. Some of them, such as distance to player, are somewhat self explanatory.

After the variables (and two debug prints to the console) comes the actual code. The idea is that the enemy checks for the strictest test, then the second strictest, and so on. Currently there are only two tests however. The first, and the one we’re interested in here, is whether the enemy can see the player or not. To see the player, the AI requires three things. First, the player must be within a certain angle of the front of the enemy (in it’s cone of vision). Secondly, the player must not be too far away from the enemy. And thirdly, there must be no solid object blocking the player from the enemy.

It was this third element that caused a lot of trouble. I tried many ways of doing this. While eventually I used a linecast, I spent a lot of time trying to get a raycast to work. Linecasts and raycasts are built into Unity; a linecast is between two points, and a raycast is emit from a single point. Both provide information on the first game object they hit which has a collider component on it. Raycasts provide more information and control than a linecast; but ultimately the easiest method turned out to be checking whether the linecast hits the player or something else first.

Over time, playing around with the raycast/linecast systems more, I began to realize that my conditional structures were causing a lot of the weirdness I was seeing.

Level design is going well; it’s a much slower process than I anticipated though!

One tricky thing has been scaling things correctly. I ended up creating a little player nub object, designed to serve as a consistent reference for the size of the character, but some of the earlier stuff is somewhat strangely proportioned. The purple object in the image there is a standardized door-size object.


I see you.

October 26, 2009
by Nathan Whitehouse (nw08)

I’d mentioned some problems getting the AI to not see through walls. They didn’t look like hard problems, but they took forever to fix. Look for an update to this post with some more depth on what had to happen, but for right now, back to scheme….

-Nate


The Doors

October 20, 2009
by Nathan Whitehouse (nw08)

Door Closed…

Door open!

The door and control panel are both modeled by me; I’ve been putting together a complete asset list and trying to get those out of the way early. I’m not spending much time on detail.

The control panel object you see can be linked to a door, and interacting with it using an ‘interact’ key causes the door to either open or close.

I’ve been having extreme problems with making the AI not be able to see through walls. I thought I had it down, but then AI weirdness, like suddenly standing still and inching away slowly from the player, or rocking back and forth, started showing up, and since then it’s been nothing but a headache.

The idea was to cast a line between the enemy and the player. If a collider was detected in between them, then the AI would not see the player even if they were in the AI’s theoretical field of vision. I am not completely sure what is going on, and I’ve tried many methods of this implementation, and done things like cast the ray (or line) from an empty game object above the enemy’s head so that terrain wasn’t getting in the way (he’s a stubby little guy). I’ve let this slow me down for a while, though, so now I’m trying to sort of play catch up on the non-AI design work I have to do. In my original plan, assets and gameplay specifics were supposed to come later. To some degree they still are; I won’t be able to know what the AI can do in the end until I try to make it do it. But right now I’m trying to get all the pieces I can done.


Misc.

October 14, 2009
by Nathan Whitehouse (nw08)

Lots of updates.

Some week and a half ago I started modeling a ‘test’ level. I had downloaded blender, but was finding it difficult to pick up. Then I remembered a program I had downloaded a long time ago called Cheetah 3D. I opened it up and found it easy to pick up; over a few hours I eventually found myself with a little maze level. Of course, I hadn’t tried to save yet (bad practice, I know, but I had been more tinkering than building), and when I did I was greeted with the message that saving is prohibited in the trial version.

I left the level open for about two days before finally plunking down the cash to buy a Cheetah license. Of course, I didn’t end up using that original level, but I now have all the tools I need to create assets and animate them. The project isn’t focused on that aspect, meaning they likely will be ugly and basic, but I think when I set out I underestimated how limited I would be without spending some of my time creating assets.

I’ve also added a sight radius in addition to a hearing radius for the enemies – if you are within their ‘cone of vision,’ they can detect you from much farther away, but only if there is nothing blocking their sight (this is an imperfect system; I’ll blog a little about it when I have more than a minute).

I’ve also been busy with a combination of work for another class, but I’ve gotten past the rough part of that.

Forthcoming in the next few days is a description of what I hope final gameplay to be like, and some research discussion.

And a link to a webplayer! I promise!

-Nate


Waypoints

September 29, 2009
by Nathan Whitehouse (nw08)

Are working. All objects tagged “Waypoint” are dynamically added to an array of waypoints. When the AI opponent comes within a set distance of the target waypoint, that waypoint is moved to the back of the array, and the new top waypoint becomes the target destination.

Of course, if the player gets near, the AI abandons the waypoints and chases the player until he manages to escape, in which case it’s back to the waypoints.

function FindNextWaypoint(){
var currentWaypoint : GameObject;
var distanceToWaypoint : float;
distanceToWaypoint = Vector3.Distance(transform.position, allWaypoints[0].gameObject.transform.position);
if(distanceToWaypoint < 10){
theTarget = allWaypoints[1];
currentWaypoint = allWaypoints.Shift();
allWaypoints.Add(currentWaypoint);
}else{
theTarget = allWaypoints[0];
}
}

FindNextWaypoint is called when the player leaves the AI’s hearing radius. A logical next step would be to make the AI start with the nearest waypoint when the player eludes it, rather than the last waypoint it was on in the series.


IT LIVES

September 29, 2009
by Nathan Whitehouse (nw08)

As of last night, those who boot up the game will find themselves being doggedly perused by a tiny, speedy little box and a lethargic floating capsule. Progress!

The two opponents are able to find the player, orient themselves towards him or her, and move towards them. Movement took a bit of doing, in part because of quaternions being the default form in which object rotations are stored. Thankfully, after much time spent trying to manipulate the quaternions themselves, I found that Unity has some handy functions for those who don’t want to dip into the complex plane. Such as Quaternion.LookAt, which allows easy focusing of an object’s attentions.

The movement portion works, but I’m not sure I completely understand it. For example, the capsule-shaped enemy is set to ignore gravity, causing it to lazily float towards its target (It could quickly float, if I changed the public variable “speed” in the inspector). Because it has a collide, however, if the player jumps on top of it, he can cause it to become ‘destabilized’ and spin about for a moment. Once the capsule has been destabilized, it will usually orient itself right side up again, but will no longer chase the player. Instead, it simply begins to drift towards the heavens, wobbling ever so slightly, until out of sight or shot down mercifully by the player. I don’t know why this happens. It could be the way I’m moving objects isn’t completely right, or it could simply be that physics objects with no gravity act really strangely (so far the cube is well behaved).

I’ve given the enemies a ‘hearing range’ – the player’s presence in a certain radius allows the enemies to chase him. Otherwise they simply wait and listen. Very crude, but it’s a start. I’m working on waypoints – if the enemies don’t know where the player is, they should go to places he might be, or patrol. Also, the enemies should have a vision range in front of them larger than their listening range, should chase a little bit after they can no longer detect the player, and ideally a motionless player will not cause any ‘noise’ for the enemies to hear.

There are also assorted touch ups, including better aiming, easier to edit variables in most functions, and some nice new trees that really ‘spruce’ up the level.

Sorry.


Quaternions…

September 28, 2009
by Nathan Whitehouse (nw08)

…make me wish I knew more math.

That is all.