Search Unity

Enemy detecting player

Discussion in 'Scripting' started by DustyShinigami, Jun 14, 2019.

  1. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    I'm currently struggling to get my enemy to detect the player, go over to him and attack. I've tried setting up a Raycast from the enemy for it to see the player, but I can't get that to work, despite managing it with the player's bullet hitting the enemy. At the moment, my enemies move back and forth between two way-points. Not sure if that is preventing my enemies from doing anything else.

    This is the script I have set up at the moment:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.AI;
    5.  
    6. public class EnemyController : MonoBehaviour
    7. {
    8.     public GameObject thePlayer;
    9.     public Animator anim;
    10.     public float moveSpeed;
    11.     public float rotSpeed;
    12.     public bool moveLeft;
    13.     public bool canMove;
    14.     public Transform startPoint;
    15.     public Transform target;
    16.     public int maxHealth;
    17.     public float currentHealth = 30;
    18.     public float invincibilityLength;
    19.     public Renderer enemyRenderer;
    20.     public float flashLength;
    21.     public ParticleSystem enemyDamage;
    22.     public HealthManager theHealthManager;
    23.     public float sightRange;
    24.     public bool playerDetected;
    25.  
    26.     private float invincibilityCounter;
    27.     private float flashCounter;
    28.     private SphereCollider enemyCollider;
    29.  
    30.     void Awake()
    31.     {
    32.         anim = GetComponent<Animator>();
    33.         enemyCollider = GetComponent<SphereCollider>();
    34.     }
    35.  
    36.     void Start()
    37.     {
    38.         //thePlayer = GameObject.FindGameObjectWithTag("Player").transform;
    39.         canMove = true;
    40.         currentHealth += maxHealth;
    41.     }
    42.  
    43.     void FixedUpdate()
    44.     {
    45.         RaycastHit detection;
    46.         if(Physics.Raycast(transform.position, transform.forward, out detection, sightRange))
    47.         {
    48.             if(detection.collider.tag == "Player")
    49.             {
    50.                 anim.SetTrigger("isAttacking_1");
    51.             }
    52.             //Debug.Log(detection.transform.name);
    53.             //playerDetected = true;
    54.             //anim.SetTrigger("isAttacking_1");
    55.         }
    56.     }
    57.  
    58.     void Update()
    59.     {
    60.         if (invincibilityCounter > 0)
    61.         {
    62.             invincibilityCounter -= Time.deltaTime;
    63.             flashCounter -= Time.deltaTime;
    64.             if (flashCounter <= 0)
    65.             {
    66.                 enemyRenderer.enabled = !enemyRenderer.enabled;
    67.                 flashCounter = flashLength;
    68.             }
    69.             if (invincibilityCounter <= 0)
    70.             {
    71.                 enemyRenderer.enabled = true;
    72.             }
    73.         }
    74.         if (canMove)
    75.         {
    76.             if (moveLeft)
    77.             {
    78.                 transform.position = Vector3.MoveTowards(transform.position, startPoint.position, moveSpeed * Time.deltaTime);
    79.                 transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(0f, 270f, 0f), rotSpeed * Time.deltaTime);
    80.             }
    81.             else if (!moveLeft)
    82.             {
    83.                 transform.position = Vector3.MoveTowards(transform.position, target.position, moveSpeed * Time.deltaTime);
    84.                 transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(0f, 90f, 0f), rotSpeed * Time.deltaTime);
    85.             }
    86.             if (transform.position == target.position)
    87.             {
    88.                 anim.SetBool("isFloating", true);
    89.                 anim.SetFloat("Speed", 0.2f);
    90.                 moveLeft = true;
    91.             }
    92.             else if (transform.position == startPoint.position)
    93.             {
    94.                 anim.SetBool("isFloating", true);
    95.                 anim.SetFloat("Speed", 0.2f);
    96.                 moveLeft = false;
    97.             }
    98.             if (playerDetected)
    99.             {
    100.                 transform.position = Vector3.MoveTowards(transform.position, thePlayer.transform.position, moveSpeed * Time.deltaTime);
    101.             }
    102.             if(transform.position == thePlayer.transform.position)
    103.             {
    104.                 anim.SetTrigger("isAttacking_1");
    105.             }
    106.         }
    107.     }
    108.     public void Damage(float amount)
    109.     {
    110.         if (invincibilityCounter <= 0)
    111.         {
    112.             currentHealth -= amount;
    113.             enemyDamage.Play();
    114.             if (currentHealth <= 0)
    115.             {
    116.                 enemyDamage.Play();
    117.                 StartCoroutine("EnemyDeath");
    118.             }
    119.             else
    120.             {
    121.                 invincibilityCounter = invincibilityLength;
    122.                 enemyRenderer.enabled = false;
    123.                 flashCounter = flashLength;
    124.             }
    125.         }
    126.     }
    127.     public IEnumerator EnemyDeath()
    128.     {
    129.         transform.localScale += new Vector3(1.5f, 1.5f, 1.5f) * Time.deltaTime;
    130.         enemyCollider.enabled = false;
    131.         Instantiate(theHealthManager.deathEffect, transform.position, transform.rotation);
    132.         yield return new WaitForSeconds(0.5f);
    133.         Destroy(gameObject);
    134.     }
    135. }
    136.  
     
  2. SparrowsNest

    SparrowsNest

    Joined:
    Apr 6, 2017
    Posts:
    1,837
    First, on Start(), why are you doing "currentHealth += maxHealth;" and not "currentHealth = maxHealth;"?

    when you do the raycast, you go from transform.position to transform.forward,
    first thing is if your pivot is on the ground it will most likely hit to ground.
    second, you're casting to transform.forward so you'll only detect him if you point exactly on him.
    thrid, you only set a animation trigger, even if he is detected, how is it communicated to the rest of the script?


    also, your Update loop looks like an Italian dish, and by the way your using the "moveLeft" I get a 2D side scrolling feel, please explain more about the world where this takes place (not the lore of the game, the environment)
     
  3. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    Close. It’s a 2.5D platformer. The models are in 3D and the backgrounds 2D pixel art. The character walks on 3D platforms that have culling, whereas the enemies are ghost-like and float back and forth slightly above the ground. The setting is inside a volcano and you play as a flame.

    I was trying to set the starting position of the ray from the enemy and for it to go forwards in the hopes of hitting the player ahead from a certain distance. I’d like for the enemy to abandon it’s routine if it detects the player, and come after him. If the player gets well out of range, it goes back to it’s routine.
     
  4. SparrowsNest

    SparrowsNest

    Joined:
    Apr 6, 2017
    Posts:
    1,837
    As i've said, in a 3D environment this type of ray will rarely hit player, if this was a 2D platformer then yeah, but still not an optimal check.

    what is usually done in 3D environment to check for visibility is
    1) check the (square) distance, if it's inside the sight radius proceed to check 2 else return false
    2) check the angle, between the enemy.forward and the vector to the player, if it's in the zoned defined as visible (say 75 degrees?) proceed to check 3 else return false
    3)do a raycast from the enemy to the player, if it hits the player - return true, if it hits something else, something is between them, probably hiding them from each other, return false.

    you can add any other check you want in there, and there are lots of other ways, but I found this type of structure (and these 3 checks) the best for simplicity and performance.

    okay, how are you communicating this to the script logic?
    all I see you doing is triggering the animator when sighted.
     
  5. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    I really have no idea, to be honest. I’m not sure how I’d set any of this up. :-/
     
  6. SparrowsNest

    SparrowsNest

    Joined:
    Apr 6, 2017
    Posts:
    1,837