Search Unity

  1. We would like to hear your feedback about Unity and our products. Click here for more information.
    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,994
    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,236
    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.