Search Unity

Zombie Horde Movement

Discussion in 'Navigation' started by laspencer, May 20, 2017.

  1. laspencer

    laspencer

    Joined:
    Jul 7, 2013
    Posts:
    4
    Hello,

    I am working on a Top-Down (for now) survival shooter. I am am experienced programmer (fairly new to Unity). I have used Unity's navmesh and understand how it works. I am wondering how I would do horde AI. Not only following the player, but some choosing to attack and attempt to break down windows / doors, and others taking the easiest path through already open doors.

    Basically, how do I limit a window to maybe 5 or 6 zombies at a time trying to get through while the rest choose a different entrance? How is something like this usually done in Unity with the navmesh system. I am not asking for someone to code it for me, just the best approach. Thank you
     
  2. JBR-games

    JBR-games

    Joined:
    Sep 26, 2012
    Posts:
    708
    Id be curious how others may work on this.

    Some ideas- use multiple targets.
    have a simple list script for attackable objects.
    When an object is attacked by a zombie add that zombie to its list.
    only let a zombie attack an object that has an open list of attackers.
    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5.  
    6. public class JBR_AI_Search_System : MonoBehaviour {
    7. //add proper tags in inspector
    8. public string playerTag;
    9. public string npcTag;
    10. public string MiscTargetTag;
    11.  
    12. // allow targeting of each type of target
    13. public bool canTargetPlayerTag;
    14. public bool canTargetNPCTag;
    15. public bool canTargetMiscTargetTag;
    16.  
    17.  //list of all targets
    18.     public List<GameObject> allTargets = new List<GameObject>();
    19.     //array of each target type
    20.     public GameObject[] playerTargets;
    21.     public GameObject[] NPCTargets;
    22.     public GameObject[] miscTargets;
    23.  
    24.  // Use this for initialization
    25.     void Start()
    26.     {
    27. //optimization does this check 10 times per second vs. 30-60 times in regular update
    28.  InvokeRepeating("CheckForTargets", 0.1f, 0.1f);
    29. }
    30. void CheckForTargets(){
    31.  //clear list of targets before we redo the list
    32.             allTargets.Clear();
    33.             //if checked add all player targets
    34.             if (canTargetPlayerTag)
    35.             {
    36.                 playerTargets = GameObject.FindGameObjectsWithTag(playerTag);
    37.                 for (int i = 0; i < playerTargets.Length ; i++)
    38.                 {
    39.                     allTargets.Add(playerTargets[i]);
    40.                     Debug.Log(playerTargets[i]);
    41.                 }
    42.             }
    43.             //if checked add all NPC targets
    44.             if (canTargetNPCTag)
    45.             {
    46.                 NPCTargets = GameObject.FindGameObjectsWithTag(npcTag);
    47.                 for (int i = 0; i < NPCTargets.Length ; i++)
    48.                 {
    49.                     allTargets.Add(NPCTargets[i]);
    50.                 }
    51.             }
    52.             //if checked add all Misc targets
    53.             if (canTargetMiscTargetTag)
    54.             {
    55.                 miscTargets = GameObject.FindGameObjectsWithTag(MiscTargetTag);
    56.                 for (int i = 0; i < miscTargets.Length ; i++)
    57.                 {
    58.                     allTargets.Add(miscTargets[i]);
    59.                 }
    60.             }
    61.             //checked through list of all targets
    62.             if (allTargets.Count > 0)
    63.             {
    64.                 for (int i = 0; i < allTargets.Count ; i++)
    65.                 {
    66.              
    67.                     //sift through all the targets for the best one
    68.                     // checks the distance away from ai to target
    69.                     float cDistance = Vector3.Distance(this.transform.position, allTargets[i].transform.position);
    70. Debug.Log("All Targets - " + allTargets[i] + "distance " + cDistance);
    71. }
    72.  
     
    Last edited: May 22, 2017
    philippecaseiro and Bojangl like this.
  3. JBR-games

    JBR-games

    Joined:
    Sep 26, 2012
    Posts:
    708
    Attackers handling
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4.  
    5. // basic Aggro handling of anything that can be attacked
    6. public class JBR_AttackableObject : MonoBehaviour {
    7.  
    8.     public int maxAttackers = 6;        //max allowed attackers
    9.     public GameObject[] Attackers ;     //Array of attackers
    10.     public bool LimitReached = false;   //if array is full sets to true
    11.  
    12.  
    13. // Use this for initialization
    14.     void Start () {
    15.         Attackers = new GameObject[maxAttackers];
    16.         Debug.Log(Attackers.Length);
    17.     }
    18.  
    19.     // Update is called once per frame
    20.     void Update () {
    21.  
    22.     }
    23.     //method for adding Attackers
    24.     public void TakeDamage(GameObject attackerGO)
    25.     {
    26.         //look through all array slots
    27.         for (int i = 0; i < Attackers.Length +1; i++)
    28.         {
    29.             // first we check that this attacker hasnt been added to the array already
    30.             if(Attackers[i] == attackerGO)
    31.             {
    32.                 Debug.Log("Duplicate Attacker " + this.gameObject.name);
    33.                 return;
    34.             }
    35.             //next we add the attacker to the first open slot in the array
    36.             if(Attackers[i] == null )
    37.             {
    38.              
    39.                 Attackers[i] = attackerGO;
    40.                 Debug.Log("New Attacker added " + this.gameObject.name);
    41.                 return;
    42.             }
    43.             //if we made it to maxAttackers limit then set as limit reached
    44.             if(i >= maxAttackers)
    45.             {
    46.                 LimitReached = true;
    47.                 Debug.Log("Limit Reached " + this.gameObject.name);
    48.                 return;
    49.             }
    50.         }
    51.     }
    52.     //method for removing Attackers
    53.     public void RemoveAttacker(GameObject removedAttacker)
    54.     {
    55.         //look through all array slots
    56.         for (int i = 0; i < Attackers.Length; i++)
    57.         {
    58.             if (Attackers[i] == removedAttacker)
    59.             {
    60.                 LimitReached = false;
    61.                 Attackers[i] = null;
    62.                 Debug.Log("Removed Attacker " + this.gameObject.name);
    63.                 return;
    64.             }
    65.         }
    66.     }
    67. }
     
    Bojangl likes this.