- Home /
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 :) 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;
}
Answer by Griffo · Jul 29, 2012 at 08:03 AM
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;
}
// -------------------------------------------------------
Your answer
Follow this Question
Related Questions
Enemy AI things to consider 2 Answers
Is this the most efficient way to attack the closest enemy? 0 Answers
Problem with enemy AI 1 Answer
How do I make my AI attack in the FPS tutorial? 0 Answers
Melee range AI 1 Answer