Search Unity

  1. Unity 2019.1 is now released.
    Dismiss Notice

Trying again to find some help!

Discussion in 'Scripting' started by dpetnick89, May 24, 2019.

  1. dpetnick89

    dpetnick89

    Joined:
    Sep 3, 2018
    Posts:
    8
    Hello all, I have recently redone my Enemy AI and Controller scripts. My previous issue of having them shoot through walls has been fixed but now they all just walk straight to a wall and keep walking into it. They wont look for the Player/Target, and wont react to his presence. I could really use a hand here as it's the largest roadblock I've encountered and it has this project on ice. Thanks for any help you guys could give.

    Here is my GuardAI script:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Random = UnityEngine.Random;
    5.  
    6. public class FancyNewGuardAI : MonoBehaviour
    7. {
    8.     public float walkMoveForce = 0f;
    9.     //public float runMoveForce = 0f;
    10.     public float moveForce = 0f;
    11.     public LayerMask whatIsPlayer;
    12.     public LayerMask whatIsObstacle;
    13.     private Rigidbody rbody;
    14.     public float wallCheckDist = 0f;
    15.     private Vector3 moveDir;
    16.     private bool TargetFound;
    17.  
    18.     public float ShootRate = 0f;
    19.     private float shootTimeStamp = 0f;
    20.     public GameObject playerObject;
    21.     public float distanceFromTarget = 0f;
    22.     public float safeDistance = 0f;
    23.     private bool shotFired = false;
    24.  
    25.     public int DealingDamage;
    26.     public GameObject TheEnemy;
    27.     public AudioSource GuardAttackSound;
    28.     public AudioSource GuardAttackNotice;
    29.  
    30.     public float runTurnRate = 0f;
    31.     private float runTurnTimeStamp = 0f;
    32.     public float runTurnDistCheck = 0f;
    33.  
    34.     Animation anim;
    35.  
    36.  
    37.     void Start()
    38.     {
    39.         anim = GetComponent<Animation>();
    40.         rbody = GetComponent<Rigidbody>();
    41.         moveDir = ChooseDirection();
    42.         transform.rotation = Quaternion.LookRotation(moveDir);
    43.         moveForce = walkMoveForce;
    44.         runTurnRate = Random.Range(0.5f, 1.5f);
    45.     }
    46.  
    47.  
    48.     void Update()
    49.     {
    50.         if (TargetFound)
    51.         {
    52.             GuardAttackNotice.Play();
    53.             Shoot();
    54.         }
    55.         else
    56.         {
    57.             LookForTarget();
    58.         }
    59.  
    60.         distanceFromTarget = Vector3.Distance(transform.position, playerObject.transform.position);
    61.     }
    62.  
    63.     void Shoot()
    64.     {
    65.         if (!shotFired)
    66.         {
    67.             if (Time.time > shootTimeStamp)
    68.             {
    69.                 GuardAttackSound.Play();
    70.                 TheEnemy.GetComponent<Animation>().Play("attacking");
    71.                 StartCoroutine(TakingDamage());
    72.                 moveForce = walkMoveForce;
    73.                 shotFired = true;
    74.                 moveDir = ChooseDirection();
    75.                 transform.rotation = Quaternion.LookRotation(moveDir);
    76.                 shootTimeStamp = Time.time + ShootRate;
    77.             }
    78.         }
    79.         else
    80.         {
    81.             Hide();
    82.         }
    83.     }
    84.  
    85.     void Hide()
    86.     {
    87.         if (distanceFromTarget < safeDistance)
    88.         {
    89.             RunToHide();
    90.         }
    91.         else
    92.         {
    93.             moveForce = walkMoveForce;
    94.             shotFired = false;
    95.             TargetFound = false;
    96.             moveDir = ChooseDirection();
    97.             transform.rotation = Quaternion.LookRotation(moveDir);
    98.         }
    99.     }
    100.     void RunToHide()
    101.     {
    102.         rbody.velocity = moveDir * moveForce;
    103.  
    104.         if (Time.time > runTurnTimeStamp)
    105.         {
    106.             if (Physics.Raycast(transform.position, transform.right, runTurnDistCheck, whatIsObstacle))
    107.             {
    108.                 TheEnemy.GetComponent<Animation>().Play("walking");
    109.                 moveDir = -transform.right;
    110.                 transform.rotation = Quaternion.LookRotation(moveDir);
    111.             }
    112.             else if (Physics.Raycast(transform.position, -transform.right, runTurnDistCheck, whatIsObstacle))
    113.             {
    114.                 TheEnemy.GetComponent<Animation>().Play("walking");
    115.                 moveDir = transform.right;
    116.                 transform.rotation = Quaternion.LookRotation(moveDir);
    117.             }
    118.             else
    119.             {
    120.                 TheEnemy.GetComponent<Animation>().Play("walking");
    121.                 moveDir = ChooseDirectionLR();
    122.                 transform.rotation = Quaternion.LookRotation(moveDir);
    123.             }
    124.             runTurnRate = Random.Range(0.5f, 1.5f);
    125.             runTurnTimeStamp = Time.time + runTurnRate;
    126.         }
    127.     }
    128.  
    129.     Vector3 ChooseDirection()
    130.     {
    131.         System.Random ran = new System.Random();
    132.         int i = ran.Next(0, 3);
    133.         Vector3 temp = new Vector3();
    134.  
    135.         if (i == 0)
    136.         {
    137.             temp = transform.forward;
    138.         }
    139.         else if (i == 1)
    140.         {
    141.             temp = -transform.forward;
    142.         }
    143.         else if (i == 2)
    144.         {
    145.             temp = transform.right;
    146.         }
    147.         else if (i == 3)
    148.         {
    149.             temp = -transform.right;
    150.         }
    151.  
    152.         return temp;
    153.     }
    154.  
    155.     Vector3 ChooseDirectionLR()
    156.     {
    157.         System.Random ran = new System.Random();
    158.         int i = ran.Next(0, 1);
    159.         Vector3 temp = new Vector3();
    160.  
    161.         if (i == 0)
    162.         {
    163.             temp = transform.right;
    164.         }
    165.         else if (i == 1)
    166.         {
    167.             temp = -transform.right;
    168.         }
    169.        
    170.         return temp;
    171.     }
    172.  
    173.     void LookForTarget()
    174.     {
    175.         TheEnemy.GetComponent<Animation>().Play("walking");
    176.         Move();
    177.         TargetFound = Physics.Raycast(transform.position, transform.forward, Mathf.Infinity, whatIsPlayer);
    178.     }
    179.  
    180.     void Move()
    181.     {
    182.         rbody.velocity = moveDir * moveForce;
    183.  
    184.         if (Physics.Raycast(transform.position, transform.forward, wallCheckDist, whatIsObstacle))
    185.         {
    186.             moveDir = ChooseDirection();
    187.             transform.rotation = Quaternion.LookRotation(moveDir);
    188.         }
    189.     }
    190.  
    191.     IEnumerator TakingDamage()
    192.     {
    193.         GuardAttackSound.Play();
    194.         DealingDamage = 1;
    195.         yield return new WaitForSeconds(1);
    196.         if (GuardEnemy.GlobalGuard != 6)
    197.         {
    198.             HealthMonitor.HealthValue -= 2;
    199.         }
    200.         yield return new WaitForSeconds(3);
    201.         DealingDamage = 0;
    202.     }
    203. }
    204.  
    Here is my enemy controller script which really just handles death/ragdolling for now:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class EnemyController : MonoBehaviour
    6. {
    7.     public GameObject theGuard;
    8.     public int GuardStatus;
    9.     public FancyNewGuardAI GuardAIScript;
    10.     public static int GlobalGuard;
    11.     public AudioSource GuardDeathSound;
    12.  
    13.     // Start is called before the first frame update
    14.     void Start()
    15.     {
    16.         setRigidbodyState(true);
    17.         setColliderState(false);
    18.         theGuard.GetComponent<Animation>().enabled = true;
    19.     }
    20.  
    21.     public void die()
    22.     {
    23.  
    24.         theGuard.GetComponent<Animation>().enabled = false;
    25.         setRigidbodyState(false);
    26.         setColliderState(true);
    27.  
    28.         if (gameObject != null)
    29.         {
    30.             GuardDeathSound.Play();
    31.             GuardStatus = 6;
    32.         }
    33.  
    34.     }
    35.  
    36.     void setRigidbodyState(bool state)
    37.     {
    38.  
    39.         Rigidbody[] rigidbodies = GetComponentsInChildren<Rigidbody>();
    40.  
    41.         foreach (Rigidbody rigidbody in rigidbodies)
    42.         {
    43.             rigidbody.isKinematic = state;
    44.         }
    45.  
    46.         GetComponent<Rigidbody>().isKinematic = !state;
    47.  
    48.     }
    49.  
    50.  
    51.     void setColliderState(bool state)
    52.     {
    53.  
    54.         Collider[] colliders = GetComponentsInChildren<Collider>();
    55.  
    56.         foreach (Collider collider in colliders)
    57.         {
    58.             collider.enabled = state;
    59.         }
    60.  
    61.         GetComponent<Collider>().enabled = !state;
    62.  
    63.     }
    64.  
    65. }
     
  2. dpetnick89

    dpetnick89

    Joined:
    Sep 3, 2018
    Posts:
    8
    /bump I know this is not the place to ask for help but I'm out of ideas. I have tried countless systems and it's the ONE thing I can't find a workable solution for.
     
  3. APSchmidt

    APSchmidt

    Joined:
    Aug 8, 2016
    Posts:
    1,959
    There is a similar situation in the Stealth project (now deprecated). The guards are supposed to react to the player setting off alarms or being seen by them or making some noise in a room near by (unseen by the guards then).

    There are two scripts that you can study, I don't think the people of Unity will bother if I share them with you; here is the fully commented versions as found in the project:
    • EnemySight manages the way the guards detect the player
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class DoneEnemySight : MonoBehaviour
    5. {
    6.     public float fieldOfViewAngle = 110f;                // Number of degrees, centred on forward, for the enemy see.
    7.     public bool playerInSight;                            // Whether or not the player is currently sighted.
    8.     public Vector3 personalLastSighting;                // Last place this enemy spotted the player.
    9.    
    10.    
    11.     private UnityEngine.AI.NavMeshAgent nav;                            // Reference to the NavMeshAgent component.
    12.     private SphereCollider col;                            // Reference to the sphere collider trigger component.
    13.     private Animator anim;                                // Reference to the Animator.
    14.     private DoneLastPlayerSighting lastPlayerSighting;    // Reference to last global sighting of the player.
    15.     private GameObject player;                            // Reference to the player.
    16.     private Animator playerAnim;                        // Reference to the player's animator component.
    17.     private DonePlayerHealth playerHealth;                // Reference to the player's health script.
    18.     private DoneHashIDs hash;                            // Reference to the HashIDs.
    19.     private Vector3 previousSighting;                    // Where the player was sighted last frame.
    20.    
    21.    
    22.     void Awake ()
    23.     {
    24.         // Setting up the references.
    25.         nav = GetComponent<UnityEngine.AI.NavMeshAgent>();
    26.         col = GetComponent<SphereCollider>();
    27.         anim = GetComponent<Animator>();
    28.         lastPlayerSighting = GameObject.FindGameObjectWithTag(DoneTags.gameController).GetComponent<DoneLastPlayerSighting>();
    29.         player = GameObject.FindGameObjectWithTag(DoneTags.player);
    30.         playerAnim = player.GetComponent<Animator>();
    31.         playerHealth = player.GetComponent<DonePlayerHealth>();
    32.         hash = GameObject.FindGameObjectWithTag(DoneTags.gameController).GetComponent<DoneHashIDs>();
    33.        
    34.         // Set the personal sighting and the previous sighting to the reset position.
    35.         personalLastSighting = lastPlayerSighting.resetPosition;
    36.         previousSighting = lastPlayerSighting.resetPosition;
    37.     }
    38.    
    39.    
    40.     void Update ()
    41.     {
    42.         // If the last global sighting of the player has changed...
    43.         if(lastPlayerSighting.position != previousSighting)
    44.             // ... then update the personal sighting to be the same as the global sighting.
    45.             personalLastSighting = lastPlayerSighting.position;
    46.        
    47.         // Set the previous sighting to the be the sighting from this frame.
    48.         previousSighting = lastPlayerSighting.position;
    49.        
    50.         // If the player is alive...
    51.         if(playerHealth.health > 0f)
    52.             // ... set the animator parameter to whether the player is in sight or not.
    53.             anim.SetBool(hash.playerInSightBool, playerInSight);
    54.         else
    55.             // ... set the animator parameter to false.
    56.             anim.SetBool(hash.playerInSightBool, false);
    57.     }
    58.    
    59.  
    60.     void OnTriggerStay (Collider other)
    61.     {
    62.         // If the player has entered the trigger sphere...
    63.         if(other.gameObject == player)
    64.         {
    65.             // By default the player is not in sight.
    66.             playerInSight = false;
    67.            
    68.             // Create a vector from the enemy to the player and store the angle between it and forward.
    69.             Vector3 direction = other.transform.position - transform.position;
    70.             float angle = Vector3.Angle(direction, transform.forward);
    71.            
    72.             // If the angle between forward and where the player is, is less than half the angle of view...
    73.             if(angle < fieldOfViewAngle * 0.5f)
    74.             {
    75.                 RaycastHit hit;
    76.                
    77.                 // ... and if a raycast towards the player hits something...
    78.                 if(Physics.Raycast(transform.position + transform.up, direction.normalized, out hit, col.radius))
    79.                 {
    80.                     // ... and if the raycast hits the player...
    81.                     if(hit.collider.gameObject == player)
    82.                     {
    83.                         // ... the player is in sight.
    84.                         playerInSight = true;
    85.                        
    86.                         // Set the last global sighting is the players current position.
    87.                         lastPlayerSighting.position = player.transform.position;
    88.                     }
    89.                 }
    90.             }
    91.            
    92.             // Store the name hashes of the current states.
    93.             int playerLayerZeroStateHash = playerAnim.GetCurrentAnimatorStateInfo(0).nameHash;
    94.             int playerLayerOneStateHash = playerAnim.GetCurrentAnimatorStateInfo(1).nameHash;
    95.            
    96.             // If the player is running or is attracting attention...
    97.             if(playerLayerZeroStateHash == hash.locomotionState || playerLayerOneStateHash == hash.shoutState)
    98.             {
    99.                 // ... and if the player is within hearing range...
    100.                 if(CalculatePathLength(player.transform.position) <= col.radius)
    101.                     // ... set the last personal sighting of the player to the player's current position.
    102.                     personalLastSighting = player.transform.position;
    103.             }
    104.         }
    105.     }
    106.    
    107.    
    108.     void OnTriggerExit (Collider other)
    109.     {
    110.         // If the player leaves the trigger zone...
    111.         if(other.gameObject == player)
    112.             // ... the player is not in sight.
    113.             playerInSight = false;
    114.     }
    115.    
    116.    
    117.     float CalculatePathLength (Vector3 targetPosition)
    118.     {
    119.         // Create a path and set it based on a target position.
    120.         UnityEngine.AI.NavMeshPath path = new UnityEngine.AI.NavMeshPath();
    121.         if(nav.enabled)
    122.             nav.CalculatePath(targetPosition, path);
    123.        
    124.         // Create an array of points which is the length of the number of corners in the path + 2.
    125.         Vector3 [] allWayPoints = new Vector3[path.corners.Length + 2];
    126.        
    127.         // The first point is the enemy's position.
    128.         allWayPoints[0] = transform.position;
    129.        
    130.         // The last point is the target position.
    131.         allWayPoints[allWayPoints.Length - 1] = targetPosition;
    132.        
    133.         // The points inbetween are the corners of the path.
    134.         for(int i = 0; i < path.corners.Length; i++)
    135.         {
    136.             allWayPoints[i + 1] = path.corners[i];
    137.         }
    138.        
    139.         // Create a float to store the path length that is by default 0.
    140.         float pathLength = 0;
    141.        
    142.         // Increment the path length by an amount equal to the distance between each waypoint and the next.
    143.         for(int i = 0; i < allWayPoints.Length - 1; i++)
    144.         {
    145.             pathLength += Vector3.Distance(allWayPoints[i], allWayPoints[i + 1]);
    146.         }
    147.        
    148.         return pathLength;
    149.     }
    150. }
    • EnemyAI manages their reaction
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class DoneEnemyAI : MonoBehaviour
    5. {
    6.     public float patrolSpeed = 2f;                            // The nav mesh agent's speed when patrolling.
    7.     public float chaseSpeed = 5f;                            // The nav mesh agent's speed when chasing.
    8.     public float chaseWaitTime = 5f;                        // The amount of time to wait when the last sighting is reached.
    9.     public float patrolWaitTime = 1f;                        // The amount of time to wait when the patrol way point is reached.
    10.     public Transform[] patrolWayPoints;                        // An array of transforms for the patrol route.
    11.    
    12.    
    13.     private DoneEnemySight enemySight;                        // Reference to the EnemySight script.
    14.     private UnityEngine.AI.NavMeshAgent nav;                                // Reference to the nav mesh agent.
    15.     private Transform player;                                // Reference to the player's transform.
    16.     private DonePlayerHealth playerHealth;                    // Reference to the PlayerHealth script.
    17.     private DoneLastPlayerSighting lastPlayerSighting;        // Reference to the last global sighting of the player.
    18.     private float chaseTimer;                                // A timer for the chaseWaitTime.
    19.     private float patrolTimer;                                // A timer for the patrolWaitTime.
    20.     private int wayPointIndex;                                // A counter for the way point array.
    21.    
    22.    
    23.     void Awake ()
    24.     {
    25.         // Setting up the references.
    26.         enemySight = GetComponent<DoneEnemySight>();
    27.         nav = GetComponent<UnityEngine.AI.NavMeshAgent>();
    28.         player = GameObject.FindGameObjectWithTag(DoneTags.player).transform;
    29.         playerHealth = player.GetComponent<DonePlayerHealth>();
    30.         lastPlayerSighting = GameObject.FindGameObjectWithTag(DoneTags.gameController).GetComponent<DoneLastPlayerSighting>();
    31.     }
    32.    
    33.    
    34.     void Update ()
    35.     {
    36.         // If the player is in sight and is alive...
    37.         if(enemySight.playerInSight && playerHealth.health > 0f)
    38.             // ... shoot.
    39.             Shooting();
    40.        
    41.         // If the player has been sighted and isn't dead...
    42.         else if(enemySight.personalLastSighting != lastPlayerSighting.resetPosition && playerHealth.health > 0f)
    43.             // ... chase.
    44.             Chasing();
    45.        
    46.         // Otherwise...
    47.         else
    48.             // ... patrol.
    49.             Patrolling();
    50.     }
    51.    
    52.    
    53.     void Shooting ()
    54.     {
    55.         // Stop the enemy where it is.
    56.         nav.Stop();
    57.     }
    58.    
    59.    
    60.     void Chasing ()
    61.     {
    62.         // Create a vector from the enemy to the last sighting of the player.
    63.         Vector3 sightingDeltaPos = enemySight.personalLastSighting - transform.position;
    64.        
    65.         // If the the last personal sighting of the player is not close...
    66.         if(sightingDeltaPos.sqrMagnitude > 4f)
    67.             // ... set the destination for the NavMeshAgent to the last personal sighting of the player.
    68.             nav.destination = enemySight.personalLastSighting;
    69.        
    70.         // Set the appropriate speed for the NavMeshAgent.
    71.         nav.speed = chaseSpeed;
    72.        
    73.         // If near the last personal sighting...
    74.         if(nav.remainingDistance < nav.stoppingDistance)
    75.         {
    76.             // ... increment the timer.
    77.             chaseTimer += Time.deltaTime;
    78.            
    79.             // If the timer exceeds the wait time...
    80.             if(chaseTimer >= chaseWaitTime)
    81.             {
    82.                 // ... reset last global sighting, the last personal sighting and the timer.
    83.                 lastPlayerSighting.position = lastPlayerSighting.resetPosition;
    84.                 enemySight.personalLastSighting = lastPlayerSighting.resetPosition;
    85.                 chaseTimer = 0f;
    86.             }
    87.         }
    88.         else
    89.             // If not near the last sighting personal sighting of the player, reset the timer.
    90.             chaseTimer = 0f;
    91.     }
    92.  
    93.    
    94.     void Patrolling ()
    95.     {
    96.         // Set an appropriate speed for the NavMeshAgent.
    97.         nav.speed = patrolSpeed;
    98.        
    99.         // If near the next waypoint or there is no destination...
    100.         if(nav.destination == lastPlayerSighting.resetPosition || nav.remainingDistance < nav.stoppingDistance)
    101.         {
    102.             // ... increment the timer.
    103.             patrolTimer += Time.deltaTime;
    104.            
    105.             // If the timer exceeds the wait time...
    106.             if(patrolTimer >= patrolWaitTime)
    107.             {
    108.                 // ... increment the wayPointIndex.
    109.                 if(wayPointIndex == patrolWayPoints.Length - 1)
    110.                     wayPointIndex = 0;
    111.                 else
    112.                     wayPointIndex++;
    113.                
    114.                 // Reset the timer.
    115.                 patrolTimer = 0;
    116.             }
    117.         }
    118.         else
    119.             // If not near a destination, reset the timer.
    120.             patrolTimer = 0;
    121.        
    122.         // Set the destination to the patrolWayPoint.
    123.         nav.destination = patrolWayPoints[wayPointIndex].position;
    124.     }
    125. }
    I hope this will help. :)
     
  4. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    1,182
    Did you actually write any code that's actually supposed to do this? (Just skimming your code I don't see it). I can't tell if you are trying to fix a bug in your code, or if you are asking for advice on how to implement this feature.