Forum begins after the advertisement:

 


[Part 6] Zombie won’t chase player

Home Forums Video Game Tutorial Series Creating a Metroidvania in Unity [Part 6] Zombie won’t chase player

Viewing 11 posts - 1 through 11 (of 11 total)
  • Author
    Posts
  • #18836
    Tyler Fruge
    Level 5
    Participant
    Helpful?
    Up
    0
    ::

    my zombie keeps flipping but not chasing me.

    Video: https://imgur.com/a/ejXEA1I

    code:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class Cadaver : Enemy
    
    {   [SerializeField] private float flipWaitTime;
        [SerializeField] private float ledgeCheckX;
        [SerializeField] private float ledgeCheckY;
        [SerializeField] LayerMask whatIsGround;
    
         float timer;
    
        // Start is called before the first frame update
        protected override void Start()
        {
            base.Start();
            rb.gravityScale = 12f;
        }
    
    
    
        protected override void UpdateEnemyStates()
        {
    
    
            switch (currentEnemyState)
            {
                case EnemyStates.Cadaver_Idle:
                    Vector3 _ledgeCheckStart = transform.localScale.x > 0 ? new Vector3(ledgeCheckX, 0) : new Vector3(-ledgeCheckX, 0);
                    Vector2 _wallCheckDir = transform.localScale.x > 0 ? transform.right : -transform.right;
    
                    if (!Physics2D.Raycast(transform.position + _ledgeCheckStart, Vector2.down, ledgeCheckY, whatIsGround)
                        || Physics2D.Raycast(transform.position, _wallCheckDir, ledgeCheckX, whatIsGround))
                    {
                        ChangeState(EnemyStates.Cadaver_Flip);
                    }
                    if (transform.localScale.x > 0)
                    {
                        rb.velocity = new Vector2(speed, rb.velocity.y);
                    }
                    else
                    {
                        rb.velocity = new Vector2(-speed, rb.velocity.y);
    
                    }
                        break;
    
                    case EnemyStates.Cadaver_Flip:
                    timer += Time.deltaTime;
    
                    if(timer > flipWaitTime)
                    {
                        timer = 0;
                        transform.localScale = new Vector2(transform.localScale.x * -1, transform.localScale.y);
                        ChangeState(EnemyStates.Cadaver_Idle);
                    }
                    break;
            }
        }
    }
    #18837
    Terence
    Level 31
    Keymaster
    Helpful?
    Up
    0
    ::

    @Alp can you see anything in the code here that is causing the enemy to flip but not move / chase the player?

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class Cadaver : Enemy
    
    {   [SerializeField] private float flipWaitTime;
        [SerializeField] private float ledgeCheckX;
        [SerializeField] private float ledgeCheckY;
        [SerializeField] LayerMask whatIsGround;
    
         float timer;
    
        // Start is called before the first frame update
        protected override void Start()
        {
            base.Start();
            rb.gravityScale = 12f;
        }
    
    
    
        protected override void UpdateEnemyStates()
        {
    
    
            switch (currentEnemyState)
            {
                case EnemyStates.Cadaver_Idle:
                    Vector3 _ledgeCheckStart = transform.localScale.x > 0 ? new Vector3(ledgeCheckX, 0) : new Vector3(-ledgeCheckX, 0);
                    Vector2 _wallCheckDir = transform.localScale.x > 0 ? transform.right : -transform.right;
    
                    if (!Physics2D.Raycast(transform.position + _ledgeCheckStart, Vector2.down, ledgeCheckY, whatIsGround)
                        || Physics2D.Raycast(transform.position, _wallCheckDir, ledgeCheckX, whatIsGround))
                    {
                        ChangeState(EnemyStates.Cadaver_Flip);
                    }
                    if (transform.localScale.x > 0)
                    {
                        rb.velocity = new Vector2(speed, rb.velocity.y);
                    }
                    else
                    {
                        rb.velocity = new Vector2(-speed, rb.velocity.y);
    
                    }
                        break;
    
                    case EnemyStates.Cadaver_Flip:
                    timer += Time.deltaTime;
    
                    if(timer > flipWaitTime)
                    {
                        timer = 0;
                        transform.localScale = new Vector2(transform.localScale.x * -1, transform.localScale.y);
                        ChangeState(EnemyStates.Cadaver_Idle);
                    }
                    break;
            }
        }
    }
    #18838
    Ser Apustaja
    Level 6
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    It looks like your enemy, the Cadaver, is currently set up to flip but may not be moving towards the player effectively. Here are a few points to consider that could help you resolve the issue:

    1. Movement Logic: In the Cadaver_Idle state, the enemy is applying a velocity based on its scale (direction). However, if the enemy is not continuously checking for the player’s position and changing its state to actively chase the player, it will remain idle after flipping. You might want to add a condition to check if the player is within a certain range and switch to a chasing state.

    2. Chasing Logic: Ensure that you have a state for chasing the player (e.g., EnemyStates.Cadaver_Chase) and implement the logic to move towards the player’s position. You might need to add a new case in the switch statement for chasing.

    3. Speed Variable: Make sure that the speed variable is defined and assigned a value. If speed is not initialized or set to zero, that would explain why the enemy appears to flip but not move.

    4. Raycasting Logic: The raycasting logic checks for walls and ledges. Make sure that the conditions under which the enemy flips are appropriate. If the enemy is constantly flipping due to hitting walls or ledges, it may not get a chance to move towards the player.

    5. Player Detection: Implement a method to detect the player (e.g., using a collider trigger or distance checks). If the player is within a certain range, you could switch to the chasing state.

    Here’s a basic example of what you can add:

    case EnemyStates.Cadaver_Chase:
        Vector2 direction = (player.position - transform.position).normalized; // Assuming you have a reference to the player
        rb.velocity = new Vector2(direction.x * speed, rb.velocity.y);
    
        if (Mathf.Abs(direction.x) < 0.1f) // Close enough to stop chasing
        {
            ChangeState(EnemyStates.Cadaver_Idle);
        }
        break;

    You will need to make sure that you have a reference to the player's position (for example, through a public Transform player variable) and adjust the states accordingly.

    By implementing these suggestions, you should be able to get the Cadaver to chase the player after it flips.

    #18842
    Terence
    Level 31
    Keymaster
    Helpful?
    Up
    0
    ::

    @tylerfruge can you share your Enemy code as well, and a recording of your zombie’s Rigidbody component when the game is active. Specifically, make sure to open up the Info tab (all the way at the bottom in the screenshot below) when you are recording. I want to check whether the rigidbody’s velocity gets updated.

    View post on imgur.com
    #18843
    Tyler Fruge
    Level 5
    Participant
    Helpful?
    Up
    0
    ::

    rigid body info:

    View post on imgur.com

    enemy code:

    using System.Collections;
    using System.Collections.Generic;
    using Unity.VisualScripting.Antlr3.Runtime.Tree;
    using UnityEngine;
    
    public class Enemy : MonoBehaviour
    {
        [SerializeField] protected float health;
        [SerializeField] protected float recoilLength;
        [SerializeField] protected float recoilFactor;
        [SerializeField] protected bool isRecoiling = false;
    
        [SerializeField] protected float speed;
    
        [SerializeField] protected float damage;
    
        protected float recoilTimer;
        protected Rigidbody2D rb;
    
        protected enum EnemyStates
        {
            //Cadaver
            Cadaver_Idle,
            Cadaver_Flip
        }
        protected EnemyStates currentEnemyState;
    
        // Start is called before the first frame update
        protected virtual void Start()
        {
            rb = GetComponent<Rigidbody2D>();
        }
        // Update is called once per frame
        protected virtual void Update()
        {
            UpdateEnemyStates();
    
            if (health <= 0)
            {
                Destroy(gameObject);
            }
            if (isRecoiling)
            {
                if (recoilTimer < recoilLength)
                {
                    recoilTimer += Time.deltaTime;
                }
                else
                {
                    isRecoiling = false;
                    recoilTimer = 0;
                }
            }
        }
    
        public virtual void EnemyHit(float _damageDone, Vector2 _hitDirection, float _hitForce)
        {
            health -= _damageDone;
            if (!isRecoiling)
            {
                rb.AddForce(-_hitForce * recoilFactor * _hitDirection);
                isRecoiling = true;
            }
        }
        protected void OnCollisionStay2D(Collision2D _other)
        {
            if (_other.gameObject.CompareTag("Player") && !PlayerController.Instance.pState.invincible)
            {
                Attack();
                PlayerController.Instance.HitStopTime(0, 5, 0.5f);
            }
        }
    
        protected virtual void UpdateEnemyStates() { }
    
        protected void ChangeState(EnemyStates _newState)
        {
            currentEnemyState = _newState;
        }
    
        protected virtual void Attack()
        {
            PlayerController.Instance.TakeDamage(damage);
        }
    
    }
    #18844
    Terence
    Level 31
    Keymaster
    Helpful?
    Up
    0
    ::

    Why is it that your Cadaver script does not have any settable attributes on it? Because it inherits Enemy, so there should be some settings like Health, Speed, etc.

    Can you turn on Debug Mode on your Inspector, and show me what you see on the Cadaver component when the game is playing?

    How to turn on Debug Mode: https://discussions.unity.com/t/turn-on-debug-mode/242854/2

    #18845
    Tyler Fruge
    Level 5
    Participant
    Helpful?
    Up
    0
    ::

    oh it DOES have health, speed and damage, i just have to click on the cadaver a few times for it to show.

    do you mean like this?

    View post on imgur.com
    #18846
    Terence
    Level 31
    Keymaster
    Helpful?
    Up
    0
    ::

    Can you double check if your platform is correctly marked as ground, or whether your _ledgeCheckStart is calculated correctly? Your Cadaver never changes state out of Cadaver_Flip, which is why it is unable to move, as the movement code is in Cadaver_Idle.

    It is likely because when your cadaver switches state to Idle, the highlighted code below immediately fires and changes the state back to Cadaver_Flip:

    protected override void UpdateEnemyStates()
    {
    
    
        switch (currentEnemyState)
        {
            case EnemyStates.Cadaver_Idle:
                Vector3 _ledgeCheckStart = transform.localScale.x > 0 ? new Vector3(ledgeCheckX, 0) : new Vector3(-ledgeCheckX, 0);
                Vector2 _wallCheckDir = transform.localScale.x > 0 ? transform.right : -transform.right;
    
                if (!Physics2D.Raycast(transform.position + _ledgeCheckStart, Vector2.down, ledgeCheckY, whatIsGround)
                    || Physics2D.Raycast(transform.position, _wallCheckDir, ledgeCheckX, whatIsGround))
                {
                    ChangeState(EnemyStates.Cadaver_Flip);
                }
                if (transform.localScale.x > 0)
                {
                    rb.velocity = new Vector2(speed, rb.velocity.y);
                }
                else
                {
                    rb.velocity = new Vector2(-speed, rb.velocity.y);
    
                }
                    break;
    
                case EnemyStates.Cadaver_Flip:
                timer += Time.deltaTime;
    
                if(timer > flipWaitTime)
                {
                    timer = 0;
                    transform.localScale = new Vector2(transform.localScale.x * -1, transform.localScale.y);
                    ChangeState(EnemyStates.Cadaver_Idle);
                }
                break;
        }
    }
    #18847
    Tyler Fruge
    Level 5
    Participant
    Helpful?
    Up
    0
    ::

    yes, the platform is labeled as ground, and i typed the code in just like it was in the video

    #18852
    Terence
    Level 31
    Keymaster
    Helpful?
    Up
    0
    ::

    Add the highlighted portion here and show me what is in your Console when the enemy is flipping:

    protected override void UpdateEnemyStates()
    {
    
    
        switch (currentEnemyState)
        {
            case EnemyStates.Cadaver_Idle:
                Vector3 _ledgeCheckStart = transform.localScale.x > 0 ? new Vector3(ledgeCheckX, 0) : new Vector3(-ledgeCheckX, 0);
                Vector2 _wallCheckDir = transform.localScale.x > 0 ? transform.right : -transform.right;
    
                if (!Physics2D.Raycast(transform.position + _ledgeCheckStart, Vector2.down, ledgeCheckY, whatIsGround)
                    || Physics2D.Raycast(transform.position, _wallCheckDir, ledgeCheckX, whatIsGround))
                {
                    print("Detected a ledge.");
                    ChangeState(EnemyStates.Cadaver_Flip);
                }
                if (transform.localScale.x > 0)
                {
                    rb.velocity = new Vector2(speed, rb.velocity.y);
                }
                else
                {
                    rb.velocity = new Vector2(-speed, rb.velocity.y);
    
                }
                    break;
    
                case EnemyStates.Cadaver_Flip:
                timer += Time.deltaTime;
    
                if(timer > flipWaitTime)
                {
                    timer = 0;
                    transform.localScale = new Vector2(transform.localScale.x * -1, transform.localScale.y);
                    ChangeState(EnemyStates.Cadaver_Idle);
                }
                break;
        }
    }
    #18853
    Tyler Fruge
    Level 5
    Participant
    Helpful?
    Up
    0
    ::

    this is what shows whenever the cadaver flips: https://imgur.com/a/QDEmdw8

Viewing 11 posts - 1 through 11 (of 11 total)
  • You must be logged in to reply to this topic.

Go to Login Page →


Advertisement below: