当前位置: 动力学知识库 > 问答 > 编程问答 >

c# - Unity 5: Enemy Animator Controller and AI logic

问题描述:

so I'm working on enemy ai and I'm using a state machine and an animator controller.

That enemy has 5 states: Idle, LookingForBlood(chasing the player), Shoot, RunningAway and Dead.

So far, the transitions between Flying and Shoot && my HitR and back to Shoot are working just perfectly, now my problem is when I shoot the enemy 4 times, he is supposed to run away for 10sec and then coming back (LookingForBlood state) and the states are looping like that till one is dead, BUT instead of just transitionning back to his flying animation and fly away, the get hit animation just keeps on looping and the enemy still "run away" but not in his flying animation.

Then the second problem is after running away, he is supposed to come back and look for me, and once he sees me, Shoot and so on (I guess you understand the loop now lol...), but instead, he doesn't stop at the ranged distance he can shoot from, it doesn't face me to shoot and that's pretty much it.

Here's my code and screenshots, if you guys see something I haven't seen for a couple of days now, it would be nice lol. I've also commented as much as possible so it's easier to understand.

using UnityEngine;

using System.Collections;

public class AngryJoe_AI : MonoBehaviour

{

// Variables for State machine

[HideInInspector]

public enum JoeState // Those are Angry Joe's states

{

Idle, // Occurs only when the player is dead

LookingForBlood, // Enemy looking for the player (from start)

Shoot, // Enemy's Attacking skill

RunningAway, // Occurs when the player shoots Joe

Dead

}

public JoeState currentState; // The current state

// Variables for stats

public int hp = 200; // Health Point

float speed = 5f; // Normal speed

float scaredSpeed = 100f; // Running away speed

// Variables for the "Shoot" State

int damage = 1; // The minimum damage when shooting (set to 1 for testing)

float fireRate = 1.5f; // How fast can he shoot

float attackCooldown; // Cooldown time between shots

// Variables for the "RunningAway" State

float panicRecoverytime = 10f; // Time Joe needs to recover from running away

public Transform[] hidingPoints;// Points where enemy can go and hide

// Variables for visual effect

GameObject blood; // The blood that will flash on screen whenever the player gets attacked

// Variables for components and game ojbect used

Animator anim; // Animations

NavMeshAgent agent; // Path Finder

GameObject player; // The player

// Variables for Joe's sight

float heightMultiplier = 1.36f; // From how high can Joe see (eyes/head position)

float sightRange = 10f; // How far can Joe see

RaycastHit hit; // This will store the info of what the ray hits

void Start ()

{

anim = GetComponent<Animator>();

agent = GetComponent<NavMeshAgent>();

player = GameObject.FindGameObjectWithTag("Player");

currentState = JoeState.LookingForBlood;

blood = GameObject.Find("Hurt_Panel");

blood.SetActive(false); // We only want to see the effect when the player is attacked

attackCooldown = Time.time;

}

void Update ()

{

// Depending on which state the enemy is, different methods will be called

switch (currentState)

{

case JoeState.Idle:

Idle();

break;

case JoeState.LookingForBlood:

LookingForBlood();

break;

case JoeState.RunningAway:

StartCoroutine(RunAway());

break;

case JoeState.Shoot:

Shoot();

break;

case JoeState.Dead:

Die();

break;

}

// if the enemy and the player are alive, the bellow behaviours apply

if (hp > 0 && PlayerStats.playerStats.hp > 0)

{

// Testing purposes

Debug.Log(Vector3.Distance(transform.position, player.transform.position));

if (currentState == JoeState.LookingForBlood || currentState == JoeState.RunningAway)

{

// We start the animation

anim.SetBool("Flying", true);

}

else

{

// We stop the animation

anim.SetBool("Flying", false);

}

// While Joe is looking for the player, if he finally sees it, then he starts shooting at him.

if (Physics.Raycast((transform.position + Vector3.up * heightMultiplier), transform.forward, out hit, sightRange) && currentState != JoeState.RunningAway)

{

// If Joe is not running away and is currently looking for the player then

if (hit.collider.tag == "Player")

{

Detect(); // Make sur you look at the player in order to shoot

// Play the animation

anim.SetBool("InRange", true);

currentState = JoeState.Shoot;

}

if (hit.collider.tag != "Player")

{

anim.SetBool("InRange", false);

currentState = JoeState.LookingForBlood;

}

}

}

if (hp <= 0)

{

currentState = JoeState.Dead;

}

// If the player is dead, chill, you can Idle

if (PlayerStats.playerStats.hp == 0 && hp > 0)

{

currentState = JoeState.Idle;

}

}

void LookingForBlood()

{

agent.speed = speed; // We set the normal speed

agent.SetDestination(player.transform.position); // Go to the player

}

void Detect()

{

// 3 versions here

//Quaternion rotation = Quaternion.LookRotation(player.transform.position - transform.position);

//transform.rotation = Quaternion.Slerp(transform.rotation, rotation, rotationDamping * Time.deltaTime);

//transform.LookAt(player.transform);

Vector3 lookDirection = player.transform.position - transform.position;

lookDirection.y = 0; // Here I can lock the y axis so when the enemy looks at the player

// and the player is really close, the enemy doesn't bend

transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(lookDirection), 0.1f);

}

void Shoot()

{

agent.SetDestination(transform.position); // We stop the navmesh agent so the enemy can shoot

//Detect(); // Look at the player to make sure you're aiming at him

if (Time.time > attackCooldown)

{

anim.SetTrigger("Shoot");

PlayerStats.playerStats.hp -= damage; // Damage is applied to the player's health

// If the shooting animation is not playing, then show the blood (aesthetic..)

blood.SetActive(true); // We show the blood effect

Invoke("VanishHurt", 0.15f); // We then hide the blood effect

attackCooldown = Time.time + fireRate; // We reset the delay between shots

}

}

void VanishHurt()

{

blood.SetActive(false);

}

// This Coroutine will be triggered if the enemy gets attacked by the player

public IEnumerator RunAway()

{

anim.SetBool("InRange", false); // Back to the flying animation

//anim.SetBool("Flying", true);

agent.speed = scaredSpeed; // When you're scared, you usually go faster :)

agent.SetDestination(hidingPoints[(int)Random.Range(0f, hidingPoints.Length -1)].position);

yield return new WaitForSeconds(10f);

attackCooldown = 0f; // We reset the delay between shots

currentState = JoeState.LookingForBlood;

}

void Idle()

{

anim.SetBool("PlayerDead", true);

}

void Die()

{

agent.SetDestination(transform.position);

anim.SetTrigger("Die");

GetComponent<CapsuleCollider>().enabled = false;

}

}

Could someone see if my logic is wrong in terms of how I set it?

分享给朋友:
您可能感兴趣的文章:
随机阅读: