Need Help With My AI Script

Hi, I’ve been putting together an Enemy AI script, I’m nearly their but I’m having a bit of trouble getting my animations playing only at the right time, for instance when the enemy gets in shooting range he goes to shoot lying down so he does that once by setting a boolean, then while he’s still in range he repeats shooting, then when out of shooting range I’m calling another animation for him to stand up, so he has these animation to do, Walk, Run, lay down, Repeat Firing and Stand up.

I’m very very close, nearly their but my head hurts now :slight_smile: so I’d appreciate any help.

Thank you.

#pragma strict

var playerTarget : Transform; // Referance to the Player
var lookAtDistance = 30;            // Distance to look at the Player
var attackRange = 15; // Range to start the attack
var attackSpeed = 5.0; // Speed to attack
var speedToRun = 1.0; // Speed to run
var chaseSpeed : float = 1.0; // Speed to chase the Player
var waypoint : Transform[]; // The amount of Waypoint you want
var patrolSpeed : float = 2; // The walking speed between Waypoints
var loop : boolean = true; // Do you want to keep repeating the Waypoints
var player : Transform; // Referance to the Player
var dampingLook = 6.0; // How slowly to turn when on patrol
var attackLook = 10.0; // How fast to turn when attacking
var pauseDuration : float = 0; // How long to pause at a Waypoint
var standOffDistance = 2; // The distance you alow the enemy to get to the Player
var shootDistance = 10; // The distance when the enemy can start to shoot the Player
var gunShotSound : AudioClip;
//----------------------------
private var searchTag = "Waypoint01"; // Search for all gameObjects taged with Waypoint01
private var attacking : boolean = false; // Is the enemy attacking the player
private var seePlayer : boolean = false; // Can the enemy see the Player
private var distanceToPlayer : int; // Distance from the enemy to the Player
private var globalVars : GameObject; // Referance to the GameObject with the GlobalVars on
private var nextWaypoint : Transform;
private var curTime : float;
private var currentWaypoint : int = 0;
private var character : CharacterController;
private var gravity : float = 2.0;
private var isAttacking : boolean = false;

function Awake(){

 globalVars = GameObject.Find("Global Vars"); // Find the gameObject with the GlobalVars attached to it

}

function Start(){

    character = GetComponent(CharacterController);
}

function Update(){

distanceToPlayer = Vector3.Distance(playerTarget.position, transform.position); // Distance between the enemy and the Player

 if(distanceToPlayer > attackRange){ //
 seePlayer = false; //
 }else{ // Check to see if the enemy can see the Player
 seePlayer = true; // and set the boolean in globaVars.js
 attack(); //
 } //

 if((currentWaypoint < waypoint.length) && (!seePlayer)){
 patrol();
 }else{ 
 if((loop) && (!attacking)){
 currentWaypoint=0;
        } 
 }
}

function patrol(){ // Patrol the waypoints

isAttacking = false;

    globalVars.GetComponent(GlobalVars).terroristShooting = false;
    globalVars.GetComponent(GlobalVars).playerBeingHit = false;
 walk();

 var target : Vector3 = waypoint[currentWaypoint].position;
//print("Current Waypoint" + " " + currentWaypoint);
 target.y = transform.position.y; // Keep waypoint at character's height so the character dont rise or sink below the ground
 var moveDirection : Vector3 = target - transform.position;

 if(moveDirection.magnitude < 0.5){ // If this number is 1 the character will jerk the last bit to the waypoint and not be over it
 // any lower and the character will get stuck for a second over the waypoint on the iPhone
 if (curTime == 0)
 curTime = Time.time; // Pause over the Waypoint
 animation.Stop("walk"); // Stop the Walk animation and play the Idel animation if Pause Duration set in the Inspector
 idel();
 if ((Time.time - curTime) >= pauseDuration){
 currentWaypoint++;
 curTime = 0;
 }
 attacking = false; // Set to false so the loop will work again after enemy attack()
 }else{        
// Look at and dampen the rotation
 var rotation = Quaternion.LookRotation(target - transform.position);
 transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * dampingLook);
 moveDirection.y -= gravity; // Add gravity so the he always stays on the ground
 character.Move(moveDirection.normalized * patrolSpeed * Time.deltaTime);
 } 
}

function attack(){ // Attack the Player

// Set terroristShooting and playerBeingHit to false to cancell terrorist muzzell flash and blood fade in/out .js
 globalVars.GetComponent(GlobalVars).terroristShooting = false;
 globalVars.GetComponent(GlobalVars).playerBeingHit = false;

// Rotate to face the Player
 var rotation = Quaternion.LookRotation(playerTarget.position - transform.position, Vector3.up);
 transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * attackLook);
 
// Move towards the Player
 var target : Vector3 = playerTarget.position;
 var moveDirection : Vector3 = target - transform.position;
 
 if(distanceToPlayer > shootDistance){
 moveDirection.y = 0; // Stop the character running up off the floor to match the Players Y axis
 moveDirection.y -= gravity; // Add gravity so the he always stays on the ground
 character.Move(moveDirection.normalized * attackSpeed * Time.deltaTime);
 }
 
 if((distanceToPlayer == shootDistance) || (distanceToPlayer < shootDistance)){
 shootLying();
 }
 else run();
 
 FindNearestWaypoint();
 currentWaypoint = FindNearestWaypoint();
 attacking = true; // Set to true so the loop wont set the currentWaypoint to 0 when coming out of attack()
}

function FindNearestWaypoint() : int { // Search for the nearest Waypoint number and return it to currentWaypoint var
    var nearestDistanceSqr = Mathf.Infinity;
    var taggedGameObjects = GameObject.FindGameObjectsWithTag(searchTag); 
    var nearestObj : Transform = null;

// Loop through each Waypoint and remembering nearest one found
    for (var obj : GameObject in taggedGameObjects) {
        var objectPos = obj.transform.position;
        var distanceSqr = (objectPos - transform.position).sqrMagnitude;

 if (distanceSqr < nearestDistanceSqr) {
 nearestObj = obj.transform;
 nearestDistanceSqr = distanceSqr;
 }
}

// first we extract the numbers from the string (starting at the 9th character, and taking 2 characters)
// Remember this will only work if the gameObject name will be 8 letters long, then immediately have 2 numbers after that
    var subTag : String = nearestObj.gameObject.name.Substring(8, 2).ToString();
// then we convert this to an int with parseInt
    return parseInt( subTag );
}

function shootLying(){

if(!isAttacking){
 standToLyingShootOnce(); // Play the lying down animation once while isAttaking is False
}
 isAttacking = true;

 repeatLyingShooting();
 Invoke("fireGunSound", 1.5); // Wait 1.5 seconds while the standToLyingShootOnce animation plays out before shooting
 Invoke("globalVarsValues", 1.5); // Wait 1.5 seconds while the standToLyingShootOnce animation plays out before updating vars
 
if((distanceToPlayer == shootDistance) || (distanceToPlayer > shootDistance)){
lyingToRunning();
//isAttacking = false;
}

// Rotate to face the Player with added degrees Y rotation to line up the enemy with the Player
var lookPos = playerTarget.position - transform.position;
    lookPos.y = 0;
    var rotation = Quaternion.LookRotation(lookPos);
    rotation *= Quaternion.Euler(0, 30, 0); // This adds a 20 degrees
    transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * attackLook);
}

// -------------------------------------------------------
// -------------- Animations of the enemy ----------------
// -------------------------------------------------------

function idel(){
 animation["Idel"].wrapMode = WrapMode.Loop;
 animation.CrossFade("Idel");
}
function walk(){
    animation["Walk"].wrapMode = WrapMode.Loop;
 animation.CrossFade("Walk");
}
function run(){
    animation["Run"].wrapMode = WrapMode.Loop;
 animation.CrossFade("Run");
}
function standShootOnce(){
    animation["Stand Shoot Once"].wrapMode = WrapMode.Loop;
 animation.CrossFade("Stand Shoot Once");
}
function repeatStandShooting(){
    animation["Repeat Stand Shooting"].wrapMode = WrapMode.Loop;
 animation.CrossFade("Repeat Stand Shooting");
}
function runningToSquatShootOnce(){
    animation["Running to Squat Shoot Once"].wrapMode = WrapMode.Loop;
 animation.CrossFade("Running to Squat Shoot Once");
}
function repeatSquatShooting(){
    animation["Repeat Squat Shooting"].wrapMode = WrapMode.Loop;
 animation.CrossFade("Repeat Squat Shooting");
}
function standToLyingShootOnce(){
 animation["Stand to Lying Shooting Once"].layer = 1; // Place on higher level so it will play all the way through
    animation["Stand to Lying Shooting Once"].wrapMode = WrapMode.Once;
 animation.Play("Stand to Lying Shooting Once");
}
function repeatLyingShooting(){
    animation["Repeat Lying Shooting"].wrapMode = WrapMode.Loop;
 animation.CrossFade("Repeat Lying Shooting");
}
function squatToStand(){
    animation["Squat to Stand"].wrapMode = WrapMode.Loop;
 animation.CrossFade("Squat to Stand");
}
function squatShootingToNot(){
    animation["Squat Shooting to Not"].wrapMode = WrapMode.Loop;
 animation.CrossFade("Squat Shooting to Not");
}
function lyingToRunning(){
 animation["Stand to Lying Shooting Once"].layer = 1; // Place on higher level so it will play all the way through
    animation["Lying to Running"].wrapMode = WrapMode.Once;
 animation.Play("Lying to Running");
}
function throwGrenade(){
    animation["Throw 1 Grenade"].wrapMode = WrapMode.Loop;
 animation.CrossFade("Throw 1 Grenade");
}
function hideBehindObject(){
    animation["Hide Behinde Object"].wrapMode = WrapMode.Loop;
 animation.CrossFade("Hide Behinde Object");
}
function jump(){
    animation["Jump"].wrapMode = WrapMode.Loop;
 animation.CrossFade("Jump");
}
function shotOnFace(){
    animation["Shot on Face"].wrapMode = WrapMode.Loop;
 animation.CrossFade("Shot on Face");
}
function shotOnBack(){
    animation["Shot on Back"].wrapMode = WrapMode.Loop;
 animation.CrossFade("Shot on Back");
}
// -------------------------------------------------------

function fireGunSound(){
 
 audio.volume = 1.0;
 audio.clip = gunShotSound;
 if(!audio.isPlaying){
 audio.Play();
 }
}

function globalVarsValues(){    
    globalVars.GetComponent(GlobalVars).terroristShooting = true;
    globalVars.GetComponent(GlobalVars).playerBeingHit = true;
}

This is where I’m at now, but it still needs tweaking, so any help would be greatly appreciated …

What I’m struggling with is getting he animations to play in order without interruption, like when he’s in attack range go from standing to lying down, and when out of range go from lying down to standing without going back into the Update, Patrol.

I’m still very new to Unity and coding so not sure of the best way to achieve this, would it be calling a function, coroutine or if statement ??

Thanks for any advice.

#pragma strict

var playerTarget : Transform; // Referance to the Player
var lookAtDistance = 30;            // Distance to look at the Player
var attackRange = 15; // Range to start the attack
var attackSpeed = 5.0; // Speed to attack
var speedToRun = 1.0; // Speed to run
var chaseSpeed : float = 1.0; // Speed to chase the Player
var waypoint : Transform[]; // The amount of Waypoint you want
var patrolSpeed : float = 2; // The walking speed between Waypoints
var loop : boolean = true; // Do you want to keep repeating the Waypoints
var player : Transform; // Referance to the Player
var dampingLook = 6.0; // How slowly to turn when on patrol
var attackLook = 10.0; // How fast to turn when attacking
var pauseDuration : float = 0; // How long to pause at a Waypoint
var standOffDistance = 2; // The distance you alow the enemy to get to the Player
var shootDistance = 10; // The distance when the enemy can start to shoot the Player
var gunShotSound : AudioClip;
//----------------------------
private var searchTag = "Waypoint01"; // Search for all gameObjects taged with Waypoint01
private var attacking : boolean = false; // Is the enemy attacking the player
private var seePlayer : boolean = false; // Can the enemy see the Player
private var distanceToPlayer : int; // Distance from the enemy to the Player
private var globalVars : GameObject; // Referance to the GameObject with the GlobalVars on
private var nextWaypoint : Transform;
private var curTime : float;
private var currentWaypoint : int = 0;
private var character : CharacterController;
private var gravity : float = 2.0;

private var isAttacking : boolean = false;
private var isShooting : boolean = false;
private var stopedShooting : boolean = false;
private var lyingDown : boolean = false;
private var isLyingDown : boolean = false;
private var standingUp : boolean = false;

// -------------------------------------------------------------

function Awake(){

 globalVars = GameObject.Find("Global Vars"); // Find the gameObject with the GlobalVars attached to it

}

// -------------------------------------------------------------

function Start(){

    character = GetComponent(CharacterController);
}

function Update(){

distanceToPlayer = Vector3.Distance(playerTarget.position, transform.position); // Distance between the enemy and the Player

 if(distanceToPlayer > attackRange){ //
 seePlayer = false; //
 }else{ // Check to see if the enemy can see the Player
 seePlayer = true; // and set the boolean in globaVars.js
 attack(); //
 } //

 if((currentWaypoint < waypoint.length) && (!seePlayer)){
 patrol();
 }else{ 
 if((loop) && (!attacking)){
 currentWaypoint=0;
        } 
 }
}

// -------------------------------------------------------------

function patrol(){ // Patrol the waypoints

isAttacking = false;

if(isLyingDown){
 lyingToRunning(); // If enemy is lying down when back to patrol() than play lyingToRunning() animation for him to get up
 isLyingDown = false;
}

    globalVars.GetComponent(GlobalVars).terroristShooting = false;
    globalVars.GetComponent(GlobalVars).playerBeingHit = false;
 walk();

 var target : Vector3 = waypoint[currentWaypoint].position;

 target.y = transform.position.y; // Keep waypoint at character's height so the character dont rise or sink below the ground
 var moveDirection : Vector3 = target - transform.position;

 if(moveDirection.magnitude < 0.5){ // If this number is 1 the character will jerk the last bit to the waypoint and not be over it
 // any lower and the character will get stuck for a second over the waypoint on the iPhone
 if (curTime == 0)
 curTime = Time.time; // Pause over the Waypoint
 animation.Stop("walk"); // Stop the Walk animation and play the Idel animation if Pause Duration set in the Inspector
 idel();
 if ((Time.time - curTime) >= pauseDuration){
 currentWaypoint++;
 curTime = 0;
 }
 attacking = false; // Set to false so the loop will work again after enemy attack()
 }else{        

// Look at and dampen the rotation
 var rotation = Quaternion.LookRotation(target - transform.position);
 transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * dampingLook);
 moveDirection.y -= gravity; // Add gravity so the he always stays on the ground
 character.Move(moveDirection.normalized * patrolSpeed * Time.deltaTime);
 } 
}

// -------------------------------------------------------------

function attack(){ // Attack the Player

// Set terroristShooting and playerBeingHit to false to cancell terrorist muzzell flash and blood fade in/out .js
 globalVars.GetComponent(GlobalVars).terroristShooting = false;
 globalVars.GetComponent(GlobalVars).playerBeingHit = false;

// Rotate to face the Player
 var rotation = Quaternion.LookRotation(playerTarget.position - transform.position, Vector3.up);
 transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * attackLook);
 
// Move towards the Player
 var target : Vector3 = playerTarget.position;
 var moveDirection : Vector3 = target - transform.position;
 
// Check if "Stand to Lying Shooting Once" is playing if so dont move, else it looks like hes being draged along 
 if(distanceToPlayer > shootDistance && !animation.IsPlaying("Stand to Lying Shooting Once")){
 moveDirection.y = 0; // Stop the character running up off the floor to match the Players Y axis
 moveDirection.y -= gravity; // Add gravity so the he always stays on the ground
 character.Move(moveDirection.normalized * attackSpeed * Time.deltaTime);
 }
 
 if(distanceToPlayer == shootDistance || distanceToPlayer < shootDistance){
 yield shootLying();
 }
 else run();
 FindNearestWaypoint();
 currentWaypoint = FindNearestWaypoint();
 attacking = true; // Set to true so the loop wont set the currentWaypoint to 0 when coming out of attack()
}

// -------------------------------------------------------------

function shootLying(){

while(distanceToPlayer == shootDistance || distanceToPlayer < shootDistance){

if(!isAttacking && !lyingDown){
 lyingDown = true;
 standToLyingShootOnce(); // Play the Lying Down animation once while isAttaking is false
 isAttacking = true;
 isLyingDown = true;
}

//yield standToLyingShootOnce();

 repeatLyingShooting();
 Invoke("fireGunSound", 1.5);
 Invoke("globalVarsValues", 1.5);

if((distanceToPlayer == shootDistance || distanceToPlayer > shootDistance) && (lyingDown)){
lyingToRunning(); // Play the Stand Up animation once while isAttaking is true
Invoke("resetIsAttaking", 1);
}

// Rotate to face the Player with added degrees Y rotation to line up the enemy with the Player
var lookPos = playerTarget.position - transform.position;
    lookPos.y = 0;
    var rotation = Quaternion.LookRotation(lookPos);
    rotation *= Quaternion.Euler(0, 15, 0); // This adds a 15 degrees
    transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * attackLook);
    yield;
}
yield;
}

// -------------------------------------------------------------

// -------------------------------------------------------
// ************** Animations of the enemy ****************
// -------------------------------------------------------

function idel(){
 animation["Idel"].wrapMode = WrapMode.Loop;
 animation.CrossFade("Idel");
}
function walk(){
    animation["Walk"].wrapMode = WrapMode.Loop;
 animation.CrossFade("Walk");
}
function run(){
    animation["Run"].wrapMode = WrapMode.Loop;
 animation.CrossFade("Run");
}
function standShootOnce(){
    animation["Stand Shoot Once"].wrapMode = WrapMode.Loop;
 animation.CrossFade("Stand Shoot Once");
}
function repeatStandShooting(){
    animation["Repeat Stand Shooting"].wrapMode = WrapMode.Loop;
 animation.CrossFade("Repeat Stand Shooting");
}
function runningToSquatShootOnce(){
    animation["Running to Squat Shoot Once"].wrapMode = WrapMode.Loop;
 animation.CrossFade("Running to Squat Shoot Once");
}
function repeatSquatShooting(){
    animation["Repeat Squat Shooting"].wrapMode = WrapMode.Loop;
 animation.CrossFade("Repeat Squat Shooting");
}
function standToLyingShootOnce(){
 animation["Stand to Lying Shooting Once"].layer = 2; // Place on higher level so it will play all the way through
    animation["Stand to Lying Shooting Once"].wrapMode = WrapMode.Once;
 animation.Play("Stand to Lying Shooting Once");
 //yield;
}
function repeatLyingShooting(){
    animation["Repeat Lying Shooting"].wrapMode = WrapMode.Loop;
 animation.CrossFade("Repeat Lying Shooting");
}
function squatToStand(){
    animation["Squat to Stand"].wrapMode = WrapMode.Loop;
 animation.CrossFade("Squat to Stand");
}
function squatShootingToNot(){
    animation["Squat Shooting to Not"].wrapMode = WrapMode.Loop;
 animation.CrossFade("Squat Shooting to Not");
}
function lyingToRunning(){
 animation["Lying to Running"].layer = 1; // Place on higher level so it will play all the way through
    animation["Lying to Running"].wrapMode = WrapMode.Once;
 animation.Play("Lying to Running");
}
function throwGrenade(){
    animation["Throw 1 Grenade"].wrapMode = WrapMode.Loop;
 animation.CrossFade("Throw 1 Grenade");
}
function hideBehindObject(){
    animation["Hide Behinde Object"].wrapMode = WrapMode.Loop;
 animation.CrossFade("Hide Behinde Object");
}
function jump(){
    animation["Jump"].wrapMode = WrapMode.Loop;
 animation.CrossFade("Jump");
}
function shotOnFace(){
    animation["Shot on Face"].wrapMode = WrapMode.Loop;
 animation.CrossFade("Shot on Face");
}
function shotOnBack(){
    animation["Shot on Back"].wrapMode = WrapMode.Loop;
 animation.CrossFade("Shot on Back");
}

// -------------------------------------------------------

// Search for the nearest Waypoint number and return it to currentWaypoint var
function FindNearestWaypoint() : int {
    var nearestDistanceSqr = Mathf.Infinity;
    var taggedGameObjects = GameObject.FindGameObjectsWithTag(searchTag); 
    var nearestObj : Transform = null;

// Loop through each Waypoint and remembering nearest one found
    for (var obj : GameObject in taggedGameObjects) {
        var objectPos = obj.transform.position;
        var distanceSqr = (objectPos - transform.position).sqrMagnitude;

 if (distanceSqr < nearestDistanceSqr) {
 nearestObj = obj.transform;
 nearestDistanceSqr = distanceSqr;
 }
}
// first we extract the numbers from the string (starting at the 9th character, and taking 2 characters)
// Remember this will only work if the gameObject name will be 8 letters long, then immediately have 2 numbers after that
    var subTag : String = nearestObj.gameObject.name.Substring(8, 2).ToString();
// then we convert this to an int with parseInt
    return parseInt( subTag );
}

// -------------------------------------------------------------

function fireGunSound(){
 
 audio.volume = 1.0;
 audio.clip = gunShotSound;
 if((!audio.isPlaying) && (!animation.IsPlaying("standToLyingShootOnce"))){
 audio.Play();
 }
}

// -------------------------------------------------------

function resetIsAttaking(){
isAttacking = false;
lyingDown = false;
}

// -------------------------------------------------------

function globalVarsValues(){
    globalVars.GetComponent(GlobalVars).terroristShooting = true;
    globalVars.GetComponent(GlobalVars).playerBeingHit = true;
}

// -------------------------------------------------------