Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
This question was closed Dec 07, 2016 at 03:48 AM by getyour411 for the following reason:

The question is answered, right answer was accepted

avatar image
0
Question by ddunteman · Dec 06, 2016 at 06:55 AM · aizombie

Zombie AI running in place but not moving

I am using the Zombie AI Pack from the Unity Asset store, but I am having an issue with the enemy AI's movement. Basically, my zombie AI is running in place (which means that it is accurately sensing the player and reading the tag correctly), but it is not actually moving toward the player. Would anyone know how to fix this issue? Here is the code below:

 using UnityEngine;
 using System.Collections;
 
 [RequireComponent (typeof (Animator))]
 [RequireComponent (typeof (NavMeshAgent))]
 [RequireComponent (typeof (CapsuleCollider))]
 
 public class ZombieInstance : MonoBehaviour {
 
     public float hp = 100.0f, damage = 20.25f, bodieRemovalTime = 10.0f, moveSpeed = 2.0f, fieldOfView = 45.0f, viewDistance = 5.0f, playerSearchInterval = 1.0f, minChase = 5.0f, maxChase = 10.0f, minWander = 5.0f, maxWander = 20.0f;
     /*
      * Health points of this zombie.
      * Damage of the attacks of this zombie.
      * Time to wait for deleting the dead bodie.
      * GLOBAL SPEED OF THE ZOMBIE I RECOMMEND 2 FOR WALKERS AND 7 FOR RUNNERS, DEPENDS ON YOUR GAME
      * FIELD OF VIEW OF THE ZOMBIE
      * VIEW DISTANCE OF THE ZOMBIE
      * INTERVAL USED TO CHECK IF THE ZOMBIE IS LOOKING AT THE PLAYER, JUST TO PREVENT OVERUSE OF RESOURCES
      SET 0 IF YOU DON'T CARE OR KEEP IT BETWEEN 1.0F AND 0.5F, RECOMMENDED
      *Min time to chase the player
      *Max time to chase the player (will be random between these 2 values)
      *Min time to wander around
      *Max time to wander around (works the same way)
     */
     public string playerTag = "Player", bodiesTag = "DeadPlayer";
     /*
      * SET HERE THE TAG TO IDENTIFY YOUR PLAYER
      * YOUR PLAYER DEAD BODIES
     */
     public bool canRun = false, eatBodies = false;
     /*
      * CAN YOUR ZOMBIE RUN?
      * WILL IT EAT THE DEAD PLAYER BODIES?
     */
     public Transform zombieHead = null;//Pivot point to use as reference, use it as if it were the eyes of the zombie.
     public LayerMask checkLayers;//Layers to check when searching for the player (after the check interval)
 
     /*Zombie sounds AnimationStates
      * 0 = Sound on wandering, idle or whatever.
      * 1 = Sound for chasing player.
      * 2 = Sound for losing player or extras.
      * 3 = Sound while eating.
      * Length of 4.
     */
     public AudioClip[] audioClips = new AudioClip[4];
     /*
      * If you want to set a new clip, you must change the length of the array and edit the inspector script.
      * You can find the needed line by searching "AnimationStates", on the script ZombieUI.cs
     */
 
     private bool playerChase = false, wandering = false, eatingBodie = false;
     /*
      * Will be true when the zombie is chasing the player, then the code will randomize when will stop doing it.
     */
     private float lastCheck = -10.0f, lastChaseInterval = -10.0f, lastWander = -10.0f;
     /*
     *Last time we checked the player's position.
     *Last or next time we chased the player before losing him.
     *Last time we set a wander position
     */
     private NavMeshAgent agent;//This zombie's nav mesh agent
     private Animator Anim;//This zombie's animator
     private Transform player = null, wanderManager = null;//Player position/transform
     private Vector3 lastKnownPos = Vector3.zero;//Last known player position
     private AudioSource SNDSource;//zombieHead should always have 2 audioSources
 
     void Start () {
         //THIS IS USED TO GET THE LOCAL NAV MESH AGENT, wanderManager AND ANIMATOR OF THIS ZOMBIE
         agent = GetComponent<NavMeshAgent>();
         Anim = GetComponent<Animator>();
         SNDSource = zombieHead.GetComponent<AudioSource>();
         wanderManager = GameObject.FindWithTag("wanderManager").transform;
 
         //SET THE MAIN VALUES
         agent.speed = moveSpeed;
         agent.acceleration = moveSpeed * 40;
         agent.angularSpeed = 999;
         resetZombie();
             
     }
 
     void Update(){
         /* IN CASE YOU CHANGE YOUR PLAYER GAMEOBJECT OR THE ZOMBIE IS SPAWNINg */
         if(Anim.GetCurrentAnimatorStateInfo(0).IsName("Spawn"))
             return;
 
         if(player == null){
             if(eatingBodie)
                 resetZombie();
             GameObject newPlayer = GameObject.FindWithTag(playerTag);
             GameObject bodySearch = GameObject.FindWithTag(bodiesTag);
             if(newPlayer != null && !newPlayer.name.Contains("Clone")){
                 //There is a bug in unity that i couldn't fix, so i added the clone thing, so yeah...
                 player = newPlayer.transform;
             }else if(eatBodies && bodySearch != null){
                 player = bodySearch.transform;
                 eatingBodie = true;
                 followBodie();
             }else{
                 doWanderFunctions();
 
                 if(newPlayer != null && newPlayer.name.Contains("Clone")){//Prevent that bug on the next search
                     Destroy(newPlayer);
                 }
 
                 return;//DON'T DO ANYTHING UNTIL WE HAVE THE PLAYER GAMEOBJECT, GO BACK, ABOOORRTTT!!!!
             }
         }
 
         /* ACTUAL ZOMBIE CODE */
 
         if(Time.time > lastCheck){//SEARCH FOR THE PLAYER AFTER INTERVAL
             checkView();
             lastCheck = Time.time + playerSearchInterval;
         }
 
         if(!eatingBodie){
             /* PLAYER SEARCH ALGORITHMS */
             if(playerChase && Anim.GetBool("isChasing")){
                 if(Time.time > lastChaseInterval){
                     gotoLastKnown();
                 }else{
                     chasePlayer();
                 }
             }
 
             //SET THE ATTACK AND RESET IT
             AnimatorStateInfo state = Anim.GetCurrentAnimatorStateInfo(0);
             if(!state.IsName("Attack") && playerChase && reachedPathEnd()){//READY TO ATTACK!
                 Anim.SetTrigger("doAttack");
                 Anim.SetBool("isIdle", false);
                 Anim.SetBool("isChasing", false);
                 playerChase = false;
             }
             if(state.IsName("Attack") && state.normalizedTime > 0.90f){
                 chasePlayer();
                 Attack();//HERE WE CALL THE PLAYER'S DAMAGE
             }
         }else{
             /* EAT BODIE ALGORITHMS */
             if(reachedPathEnd()){//This means we are in the right position to eat the bodie.
                 startEating();
             }else{
                 followBodie();//In case or explosions or stuff like that.
             }
         }
 
         //MAKE THE ZOMBIE WANDER AROUND THE MAP
         if(wandering){
             if(reachedPathEnd()){
                 resetZombie();
             }
             if(Time.time > lastWander){//IF WE ARE READY TO CHOOSE A NEW POSITION
                 wanderManager.SendMessage("getNewPos", this.gameObject, SendMessageOptions.RequireReceiver);
             }
         }
 
     }
 
     //Just to make this code prettier, simplify with functions...
     void checkView(){
         RaycastHit hit = new RaycastHit();
         Vector3 checkPosition = player.position - zombieHead.position;
         if(Vector3.Angle(checkPosition, zombieHead.forward) < fieldOfView){ //Check if player is inside the field of view
             if (Physics.Raycast(zombieHead.position, checkPosition, out hit, viewDistance, checkLayers)) {
                 if(hit.collider.tag == playerTag){//do this..
                     chasePlayer();
                     lastChaseInterval = Time.time + Random.Range(minChase, maxChase);
                 }
             }
         }else if(meleeDistance()){
             chasePlayer();
             lastChaseInterval = Time.time + Random.Range(minChase, maxChase);
         }
     }
 
     void gotoLastKnown(){
         Anim.SetBool("isChasing", true);
 
         if(canRun)
             Anim.SetBool("isRunning", true);
 
         Anim.SetBool("isIdle", false);
         playerChase = true;
         agent.SetDestination(lastKnownPos);
         agent.Resume();
         wandering = true;
         eatingBodie = false;
     }
 
     void chasePlayer(){
         Anim.SetBool("isChasing", true);
 
         if(canRun)
         Anim.SetBool("isRunning", true);
 
         Anim.SetBool("isIdle", false);
         playerChase = true;
         agent.SetDestination(player.position);
         lastKnownPos = player.position;
         agent.Resume();
         wandering = false;
         eatingBodie = false;
         playSound(audioClips[1], false, false, true, true);
     }
 
     void stopChase(){
         Anim.SetBool("isChasing", false);
 
         if(canRun)
             Anim.SetBool("isRunning", false);
 
         Anim.SetBool("isIdle", true);
         playerChase = false;
         agent.Stop();
         wandering = false;
         eatingBodie = false;
     }
 
     void resetZombie(){
         Anim.SetBool("isIdle", true);
         Anim.SetBool("isChasing", false);
         Anim.SetBool("isEating", false);
 
         if(canRun)
             Anim.SetBool("isRunning", false);
 
         playerChase = false;
         agent.Stop();
 
         wandering = true;
         eatingBodie = false;
         playSound(audioClips[0], false, false, true, true);
     }
 
     void startEating(){
         Anim.SetBool("isChasing", false);;
 
         if(canRun)
             Anim.SetBool("isRunning", false);
 
         Anim.SetBool("isIdle", false);
         Anim.SetBool("isEating", true);
 
         playerChase = false;
         agent.SetDestination(player.position);//Just to keep track of it, ignore this.
         agent.Stop();//Won't actually follow the bodie, let's store that for later.
         wandering = false;
         eatingBodie = true;
         playSound(audioClips[3], true, true, false, true);
     }
 
     void followBodie(){
         Anim.SetBool("isChasing", true);
 
         if(canRun)
             Anim.SetBool("isRunning", true);
 
         Anim.SetBool("isIdle", false);
         Anim.SetBool("isEating", false);
         playerChase = false;
         agent.SetDestination(player.position);//In this case "player" will be a dead bodie.
         agent.Resume();//Lets follow it, to prevent mistakes.
         wandering = false;
         eatingBodie = true;
         SNDSource.Stop();
     }
 
     void setNewWanderPos(Vector3 targetPos){
         Anim.SetBool("isIdle", false);
         Anim.SetBool("isChasing", true);
 
         if(canRun)
             Anim.SetBool("isRunning", true);
 
         playerChase = false;
         agent.SetDestination(targetPos);
         agent.Resume();
         lastWander = Time.time + Random.Range(minWander, maxWander);
         playSound(audioClips[2], false, false, true, true);
     }
 
     /* PARAMS:
      * Sound: Sound clip AudioClip
      * loop: boolean, to make the audio loop
      * randomStart: boolean, Start the clip at a random time
      * checkSameClip: boolean, prevent the replay of the audio if it is the same clip
      * isPlayingCheck: boolean, when preventing replay, should check if it's still playing while the same clip?
     */
     void playSound(AudioClip sound, bool loop, bool randomStart = false, bool checkSameClip = false, bool isPlayingCheck = false){
         if(checkSameClip && SNDSource.clip == sound && !SNDSource.isPlaying)
             return;
 
         if(isPlayingCheck && SNDSource.clip == sound && SNDSource.isPlaying)
             return;
 
         SNDSource.clip = sound;
         SNDSource.loop = loop;
 
         if(randomStart)
             SNDSource.time = Random.Range(0.0f, sound.length);
         
         SNDSource.Play();
     }
 
     //ONLY WHEN THE PLAYER AND DEAD BODY VARIABLE ARE NULL
     void doWanderFunctions(){
         //MAKE THE ZOMBIE WANDER AROUND THE MAP EXACTLY LIKE THE UPDATE SYSTEM, JUST TO MAKE EVERYTHING EASIER
         if(wandering){
             if(reachedPathEnd()){
                 resetZombie();
             }
             if(Time.time > lastWander){//IF WE ARE READY TO CHOOSE A NEW POSITION
                 wanderManager.SendMessage("getNewPos", this.gameObject, SendMessageOptions.RequireReceiver);
             }
         }
     }
 
     void Attack(){
         if(!meleeDistance())//DON'T DO ANYTHING IF WE ARE NOT AT A MELEE DISTANCE TO THE PLAYER
             return;
 
         /*
          * HERE YOU SET DAMAGE TO PLAYER YOU MUST DO THE CODE BY YOURSELF
          * REMEMBER THE PLAYER VARIABLE IS ALREADY SET
         */
         agent.updateRotation = false;
         transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(agent.destination - transform.position, transform.up), 7.0f *Time.deltaTime);
         agent.updateRotation = true;
         player.SendMessage("Damage", damage, SendMessageOptions.RequireReceiver);
     }
 
     void Damage(float dmg){
         /*HERE YOU CALL DAMAGE FOR ZOMBIE EXAMPLE: 
         *zombieObject.SendMessage("ZombieDamage", float value, SendMessageOptions.RequireReceiver);
         */
         hp -= dmg;
 
         if(player != null)
             chasePlayer();
 
         if(hp < 0.0f || hp == 0.0f){//This zombie is freakin' dead!
             this.tag = "Untagged";
             BroadcastMessage("ActivateR", SendMessageOptions.RequireReceiver);//Activate ragdoll or spawn the dead bodie.
             Anim.enabled = false;//Deactivate things that might screw the ragdoll up.
             agent.enabled = false;
             GetComponent<Collider>().enabled = false;
             Destroy(gameObject, bodieRemovalTime);
             enabled = false;
         }
     }
 
     //Check if agent reached the player
     bool reachedPathEnd (){
         if (!agent.pathPending && agent.remainingDistance <= agent.stoppingDistance){
             if (!agent.hasPath || agent.velocity.sqrMagnitude == 0.0f){
                 return true;
             }
             return true;
         }
         return false;
     }
 
     bool meleeDistance(){
         if(Vector3.Distance(transform.position, player.position) < 2.0f){
             return true;
         }
 
         return false;
     }
 }

And the relevant inspector screenshots:

alt text

alt text

screen-shot-2016-12-05-at-100537-pm.png (66.4 kB)
screen-shot-2016-12-05-at-100547-pm.png (42.6 kB)
Comment
Add comment · Show 1
10 |3000 characters needed characters left characters exceeded
â–¼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image ddunteman · Dec 07, 2016 at 12:38 AM 0
Share

Nope, and that fixed it. Unity beginner here, thanks so much!

1 Reply

  • Sort: 
avatar image
0
Best Answer

Answer by slavo · Dec 06, 2016 at 02:18 PM

Hi, do you bake Navmesh for your scene?

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
â–¼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Follow this Question

Answers Answers and Comments

6 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

[Zombie AI] Enemy grows and pushes me when coming towards me? 1 Answer

ZOMBIE AI SCRIPT 1 Answer

oncollisionenter2d always collides 2 Answers

Character Controller Is Lagging Behind Enemy 2 Answers

Random zombies walking into a room 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges