Report
The Robot Run game was developed as part of the programming brief in the MSc in Games Development in DIT.
I first tried to implement it in XNA, but since I was more familiar with the Unity engine, and I was having some problems playing back mixed animation on the robot character in XNA, I decided to switch to the Unity engine.
The demo is mainly an experiment with steering behaviors. I used Unity steer, which is a port of Open Steer by Craig Reynolds.
I had to merge the arrive and wander behaviors and create a custom vehicle for arrive as I needed to pass the Target object at runtime, and not on initialization as was the case of the provided Vehicle. This meant I had to code my own contructor for this special case, and then set the target to be initialized at runtime, this was the more challenging part of the project, and has room for improvement.
I also integrated animation playback in the steering behaviors.
The merge solution was achieved by instantiating both behaviors on the robot object, and only updating the one I needed depending on the availability (or not) of food. The original plan was to use the subsumption architecture to switch behaviors, but I was unable to implement that.
There would still be room for improvement of the obstacle avoidance processes, but that would mean working on the steering library, rather than the direct implementation of what I required.
All the models and animation were also “home made” I used Wings 3D for modelling and 3Ds Max for animation.
Coding
The main classes I developed for this project were: MyTestMoveToPointObstacles.cs, MyMovesToPoint.cs and DropFood.cs
The first one is a steering behavior, it inherits from Vehicle.cs and instantiates both an MPWanderer and a MyMovesToPoint vehicle.
void Start () {
vehicle = new MyMovesToPoint(this.rigidbody, radius);
wanderer = new MpWanderer( transform, Mass, MovesVertically );
}
The vehicle classes used both inherit from SimpleVehicle, which in turn inherits from SteerLibrary.cs and Vehicle.cs, which are the classes holding the actual steering functionality and get/set calls. The IRadar interface is also implemented on MyMovesToPoint and MPWander to avail of Obstacle monitoring.
Only the required vehicle is updated, the forward animation is played on wandering:
void Update () {
if (DropFood.foodAvailable == true)
{
vehicle.Update(Time.deltaTime);
Debug.Log (“seek”);
}
else {
GameObject bot = GameObject.Find(“Animation_Bot4″);
bot.animation.CrossFade(“fwd”);
wanderer.Update(Time.deltaTime);
Debug.Log (“wander”);
}
}
The wander vehicle was used as is, and is found in the MultiplePursuit.cs class, for the arrive vehicle I had to modify the MovesToPoint class, to accept a target at runtime and play required animations:
//Sergio modified contructor to get target at runtime
public MyMovesToPoint( Rigidbody rigidbody, float radius ) : base( rigidbody )
{
reset();
//no target passed in the contructor
this.Radius = radius;
}
and the code to seek for target:
public void Update (float elapsedTime)
{
if (DropFood.foodAvailable == true)
{
GameObject theTarget = GameObject.Find(“Food(Clone)”);
this.target = theTarget.transform.position;
float d = Vector3.Distance(Position, target);
float r = Radius;
if (d < r)
{
this.moving = false;
bot.animation.Stop(“fwd”);
bot.animation.CrossFade(“crouch”);
return;
}
}
else {
return;
}
I also coded the DropFood.cs class to instantiate a food GameObject and Transform upon pressing a button, it uses a coroutine to yield for 5 seconds after the object is instantiated.
A Static variable is used as condition as to which behavior to update :
using UnityEngine;
using System.Collections;
public class DropFood : MonoBehaviour {
public static bool foodAvailable = false;
public Transform food;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
StartCoroutine(makeFood());
}
IEnumerator makeFood () {
if (Input.GetButtonDown(“Fire1″) && foodAvailable == false)
{
// Instantiate the projectile at the position and rotation of this transform
Transform clone = (Transform)Instantiate(food,transform.position,transform.rotation);
foodAvailable = true;
yield return new WaitForSeconds (5);
foodAvailable = false;
}
}
}
The food object has a simple Unity script attached to it, which destroys the Object after 5 seconds:
function Update () {
//DropFood.foodAvailable = true;
Destroy(gameObject,5);
}
Controls for the player character and camera orbit, were also used, these are written in Unity Script.
Sergio.