Thursday, February 16, 2012

Some code for the enemy AI for my Treasure Hunter game project.

I have recently started writing code for my Treasure Hunter game project.  The game is being developed in the Unity Game engine.  It is being designed as an old school Zelda clone, with modern graphics and gameplay elements.  This is the first major game design project I have undertaken, and my first time writing such large amounts of code.  I intend to make this a long term project.  The goal is to release something with a high enough level of quality and fun that people will actually play it.  It is also meant to be a portfolio builder that will eventually showcase my programming, animation and game design skills.

So, here is my first post.  It is just an example of the programming work I have been doing so far.  It is my first attempt at writing code for enemy AI that reacts to the player.  Right now it is some relatively simple code  that creates idle, wander, and chase states for the enemy object, based on their distance from the player.  There is also code to handle damage to the player and enemy, as well as a knock back function for both the enemy and player.

I have created some other behaviors for different enemy types not included in this code.  One teleports on top of the player when they are close enough, but the player is able to shield themselves from the damage if they react by blocking.  The other is an enemy with a ranged attack.  It attempts to maintain distance from the player, and fires projectiles to damage the player.  The projectiles may be blocked by the players shield.

I hope as I progress in my programming experience I will be able to write more and more advanced AI code.  As with everything, this is a learning experience.

Blogger does some weird stuff to formatting when I copy/paste code.  Hope this turns out readable.


//Enemy Script//

//Inspector Variables//
var health : int = 5;
var enemySpeed : float = 1.0;
var newPositionDelay : float = 3.0;

//Private Variables//
private var findPlayer : GameObject;
private var playerObject         :       Transform;
private var playerPosition         :       Vector3;
private var damageOn : boolean = true;
private var spawnPosition        :       Vector3;
private var getNewPosition : boolean = true;
private var randomOffsetX : float = 0.0;
private var randomOffsetZ : float = 0.0;
private var wanderPosition : Vector3;

function Start()
{
findPlayer = GameObject.FindWithTag ("Player");        //Load the Player into the script
playerObject = findPlayer.transform;        //Load the Players position into the script
spawnPosition = transform.position; //Save the Enemies Initial position
}

function Update ()
{
//If the player is close enough, chase them.
if (Vector3.Distance(playerObject.position, transform.position) <=  8)
{
EnemyChase();
}

//If the player is a medium distance, wander to random positions nearby.
if (Vector3.Distance(playerObject.position, transform.position) > 8 && Vector3.Distance(playerObject.position, transform.position) < 12)
{
EnemyWander();
}

//If the player is too far away, return to initial position.
if (Vector3.Distance(playerObject.position, transform.position) >  12)
{
EnemyReturnHome();
}
}


function OnTriggerEnter (other : Collider)    //If the enemy is hit by the players weapon, damage the enemy
{
if (other.gameObject.CompareTag("Weapon")) //Check if the object entering the collider is a weapon.
{
health--; //Damage Health
EnemyKnockback(); //Get Knocked Back
if(health <= 0) //Check if health is 0
{
Destroy(gameObject); //If enemy's life is 0, kill the enemy.
}
}
}

function OnTriggerStay (other : Collider) //If the player remains in contact with the enemy, damage the player periodically.
{
if (other.gameObject.CompareTag("Player") && damageOn) //Check if the object inside the collider
                                                                                                         // is a player.
{
Knockback(other.gameObject); //Knockback the player
other.GetComponent("scriptPlayer").DamageHealth();        //Damage the player
damageOn = false; //Prevent further damage until          
                                                                                                                //player has had time to react
yield WaitForSeconds(1.0); //Give player time to react
damageOn = true; //Re-enable damage to the player
}
}

function EnemyKnockback()
{
var startEnemyKnockback = Time.time;
while (Time.time <= (startEnemyKnockback +.2))
{
transform.Translate(0, 0, -12 * Time.deltaTime);
yield;
}
}


function Knockback (other : GameObject)
{  
var startKnockback = Time.time;
while (Time.time <= (startKnockback +.2))
{
other.transform.Translate(0, 0, 12 * Time.deltaTime, gameObject.transform);
yield;
}
}

function EnemyChase()
{
transform.LookAt(playerObject);
transform.position = Vector3
(Mathf.MoveTowards(transform.position.x, playerObject.transform.position.x, enemySpeed * Time.deltaTime),
Mathf.MoveTowards(transform.position.y, playerObject.transform.position.y, enemySpeed * Time.deltaTime),
Mathf.MoveTowards(transform.position.z, playerObject.transform.position.z, enemySpeed * Time.deltaTime));
}

function EnemyReturnHome()
{
transform.position = Vector3
(Mathf.MoveTowards(transform.position.x, spawnPosition.x, enemySpeed * Time.deltaTime),
Mathf.MoveTowards(transform.position.y, spawnPosition.y, enemySpeed * Time.deltaTime),
Mathf.MoveTowards(transform.position.z, spawnPosition.z, enemySpeed * Time.deltaTime));
}

function GetWanderPosition()
{
if(getNewPosition)
{
getNewPosition = false;
randomOffsetX = Random.Range(-5,5);
randomOffsetZ = Random.Range(-5,5);
wanderPosition = Vector3 (spawnPosition.x + randomOffsetX,
                                                          Terrain.activeTerrain.SampleHeight(transform.position)+ 0.2,
                                                          spawnPosition.z + randomOffsetZ);
yield WaitForSeconds (newPositionDelay + Random.Range(-1,2));
getNewPosition = true;
}
}

function EnemyWander ()
{
GetWanderPosition();
transform.LookAt(wanderPosition);
transform.position = Vector3
(Mathf.MoveTowards(transform.position.x, (wanderPosition.x), enemySpeed * Time.deltaTime),
wanderPosition.y,
Mathf.MoveTowards(transform.position.z, (wanderPosition.z), enemySpeed * Time.deltaTime));
}

No comments:

Post a Comment