Forum begins after the advertisement:


[Part 3] Bat can’t move and attack

Home Forums Video Game Tutorial Series Creating a Metroidvania in Unity [Part 3] Bat can’t move and attack

Viewing 20 posts - 1 through 20 (of 21 total)
  • Author
    Posts
  • #17673
    Pool ForReal
    Level 4
    Participant
    Helpful?
    Up
    0
    ::

    Bat Code

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class Bat :Enemy
    {
        [SerializeField] private float chaseDistance;
        [SerializeField] private float stunDuration;
        float timer;
    
        // Start is called before the first frame update
        protected override void Update()
        {
            base.Start();
            if (!PlayerController.Instance.pState.alive)
            {
                ChangeState(EnemyStates.Bat_idle);
            }
        }
    
        protected override void UpdateEnemyStates()
        {
            float _dist = Vector2.Distance(transform.position, PlayerController.Instance.transform.position);
    
            switch (GetCurrentEnemyState)
            {
                 case EnemyStates.Bat_idle:
                    if(_dist < chaseDistance)
                    {
                        ChangeState(EnemyStates.Bat_Chase);
                    }
                    break;
    
                 case EnemyStates.Bat_Chase:
                    rb.MovePosition(Vector2.MoveTowards(transform.position, PlayerController.Instance.transform.position, Time.deltaTime * speed));
    
                    FlipBat();
                    break;
    
                 case EnemyStates.Bat_Stunned:
                    timer += Time.deltaTime;
    
                    if(timer > stunDuration)
                    {
                        ChangeState(EnemyStates.Bat_idle);
                        timer = 0;
                    }
                    break;
    
                case EnemyStates.Bat_Death:
                    Death(Random.Range(5, 10));
                    break;
            }
        }
    
        public override void EnemyGetsHit(float _damageDone, Vector2 _hitDirection, float _hitForce)
        {
            base.EnemyGetsHit(_damageDone, _hitDirection, _hitForce);
    
            if(health > 0)
            {
                ChangeState(EnemyStates.Bat_Stunned);
            }
            else
            {
                ChangeState(EnemyStates.Bat_Death);
            }
        }
    
        protected override void Death(float _destroyTime)
        {
            rb.gravityScale = 12;
            base.Death(_destroyTime);
        }
    
        protected override void ChangeCurrentAnimation()
        {
           anim.SetBool("idle", GetCurrentEnemyState == EnemyStates.Bat_idle);
    
           anim.SetBool("Chase", GetCurrentEnemyState == EnemyStates.Bat_Chase);
    
            if(GetCurrentEnemyState == EnemyStates.Bat_Death)
            {
                anim.SetTrigger("Death");
            }
        }
    
        void FlipBat()
        {
            sr.flipX = PlayerController.Instance.transform.position.x < transform.position.x;
        }
    }
    #17674
    Ser Apustaja
    Level 6
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    It looks like you’ve pasted the code for a Bat enemy class in Unity, but it seems to contain some issues, particularly with the HTML entities for comparison operators (like < for “). This will cause compilation errors. You need to replace those entities with the actual symbols. Here’s the corrected version of your code:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class Bat : Enemy
    {
        [SerializeField] private float chaseDistance;
        [SerializeField] private float stunDuration;
        float timer;
    
        // Start is called before the first frame update
        protected override void Update()
        {
            base.Start();
            if (!PlayerController.Instance.pState.alive)
            {
                ChangeState(EnemyStates.Bat_idle);
            }
        }
    
        protected override void UpdateEnemyStates()
        {
            float _dist = Vector2.Distance(transform.position, PlayerController.Instance.transform.position);
    
            switch (GetCurrentEnemyState)
            {
                case EnemyStates.Bat_idle:
                    if (_dist  stunDuration)
                    {
                        ChangeState(EnemyStates.Bat_idle);
                        timer = 0;
                    }
                    break;
    
                case EnemyStates.Bat_Death:
                    Death(Random.Range(5, 10));
                    break;
            }
        }
    
        public override void EnemyGetsHit(float _damageDone, Vector2 _hitDirection, float _hitForce)
        {
            base.EnemyGetsHit(_damageDone, _hitDirection, _hitForce);
    
            if (health > 0)
            {
                ChangeState(EnemyStates.Bat_Stunned);
            }
            else
            {
                ChangeState(EnemyStates.Bat_Death);
            }
        }
    
        protected override void Death(float _destroyTime)
        {
            rb.gravityScale = 12;
            base.Death(_destroyTime);
        }
    
        protected override void ChangeCurrentAnimation()
        {
            anim.SetBool("idle", GetCurrentEnemyState == EnemyStates.Bat_idle);
            anim.SetBool("Chase", GetCurrentEnemyState == EnemyStates.Bat_Chase);
    
            if (GetCurrentEnemyState == EnemyStates.Bat_Death)
            {
                anim.SetTrigger("Death");
            }
        }
    
        void FlipBat()
        {
            sr.flipX = PlayerController.Instance.transform.position.x < transform.position.x;
        }
    }

    Key Changes:

    1. Replaced < with “.
    2. Checked for proper alignment and formatting for better readability.

    Make sure that your Enemy class and the PlayerController instance are correctly implemented, and that all necessary components (like rb for Rigidbody and sr for SpriteRenderer) are properly initialized in your script. If you face any specific issues or errors after these changes, feel free to ask!

    #17675
    Pool ForReal
    Level 4
    Participant
    Helpful?
    Up
    0
    ::

    okayy,thank you

    #17677
    Ser Apustaja
    Level 6
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    You’re welcome! If you have any more questions or need further assistance with your code or anything else, feel free to ask. Happy coding!

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

    @ser.apustaja, his issue is not with the code formatting. It’s with the Bat enemy not moving and attacking.

    Can you have a look at his bat code again and suggest possible issues? Ignore the HTML formatting issues and read the HTML characters as the actual character itself.

    #17680
    Ser Apustaja
    Level 6
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    Certainly! Let’s take a closer look at the Bat enemy code and identify some possible reasons why the bat might not be moving or attacking:

    1. Update Method Call:

      • In your Update() method, you’re calling base.Start(), which is incorrect. It should be base.Update() to ensure the base class’s update logic is executed. This could prevent important updates from happening in your bat class.
      protected override void Update()
      {
          base.Update(); // Change this from base.Start() to base.Update()
          if (!PlayerController.Instance.pState.alive)
          {
              ChangeState(EnemyStates.Bat_idle);
          }
      }
    2. State Management:

      • Ensure that the ChangeState() method is correctly managing the enemy states. If the state is not transitioning correctly, the bat may not perform actions like chasing or attacking.
      • For example, check if EnemyStates.Bat_Chase is being reached; you might want to add debug logs to verify if the state is changing.
    3. Chase Logic:

      • In the UpdateEnemyStates() method, check if the distance calculation is working correctly. Make sure PlayerController.Instance is correctly referencing the player and that it has a valid position.
      • Also, ensure that chaseDistance is set to a reasonable value in the inspector, as a very small value could prevent the bat from chasing the player.
    4. Movement Speed:

      • Ensure that the speed variable (which appears to control how fast the bat moves) is defined and set to a positive value. If speed is zero or negative, the bat won’t move.
    5. Animation States:

      • Make sure the animations for “idle,” “chase,” and “death” are correctly set up in your Animator and that they are transitioning properly based on the enemy states. If animations are not playing, it may appear as if the bat is not moving or attacking.
    6. Player Interaction:

      • Check if there are conditions that might prevent the bat from attacking the player. For example, if the attack logic isn’t triggered because the bat is not in the correct state or distance.
    7. Debugging:

      • You can add debug statements to log the current state of the bat and the distance to the player. This can help you identify where the logic may be failing:
      Debug.Log("Current State: " + GetCurrentEnemyState);
      Debug.Log("Distance to Player: " + _dist);

    By checking these areas, you should be able to identify why the Bat enemy is not moving or attacking as expected. If you make these changes and still face issues, please provide any error messages or specific behaviors you’re observing, and I’ll be happy to help further!

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

    @nabilgaming can you have a look at Apu’s new suggestions above and see if it helps?

    #17698
    Pool ForReal
    Level 4
    Participant
    Helpful?
    Up
    0
    ::

    i have tried his first solution and that correct,should i try second solution?

    #17699
    Ser Apustaja
    Level 6
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    Yes, you should try the second solution regarding state management. Ensure that the ChangeState() method is functioning correctly and that the bat is transitioning to the EnemyStates.Bat_Chase state as expected. Adding debug logs can help you verify if the state is changing properly.

    If you encounter any issues or need further clarification, please let me know what specific behavior you’re observing!

    #17708
    Pool ForReal
    Level 4
    Participant
    Helpful?
    Up
    0
    ::

    this my enemy code, its correct?

    using System.Collections;
    using System.Collections.Generic;
    using Unity.VisualScripting;
    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 PlayerController player;
        [SerializeField] protected float speed;
    
        [SerializeField] protected float damage;
        [SerializeField] protected GameObject WhiteBlood;
    
    
        protected float recoilTimer;
        protected Rigidbody2D rb;
        protected SpriteRenderer sr;
        protected Animator anim;
    
        protected enum EnemyStates
        {
            //Centipede
           Centipede_idle,
           Centipede_Flip,
    
            //Bat
            Bat_idle,
            Bat_Chase,
            Bat_Stunned,
            Bat_Death,
    
            //THK
            THK_Stage1,
            THK_Stage2,
            THK_Stage3,
            THK_Stage4,
        }
        protected EnemyStates currentEnemyState;
    
        protected virtual EnemyStates GetCurrentEnemyState
        {
            get { return currentEnemyState; }
            set
            {
                if (currentEnemyState != value)
                {
                    currentEnemyState = value;
    
                    ChangeCurrentAnimation();
                }
            }
    
        }
        // Start is called before the first frame update
        protected virtual void Start()
        {
            rb = GetComponent<Rigidbody2D>();
            sr = GetComponent<SpriteRenderer>();
            anim = GetComponent<Animator>();
        }
    
        protected virtual void Awake()
        {
            rb = GetComponent<Rigidbody2D>();
            player = PlayerController.Instance;
        }
        // Update is called once per frame
        protected virtual void Update()
        {
            if(isRecoiling)
            {
                if(recoilTimer < recoilLength)
                {
                    recoilTimer += Time.deltaTime;
                }
                else
                {
                    isRecoiling = false;
                    recoilTimer = 0;
                }
            }
            else
            {
                UpdateEnemyStates();
            }
        }
    
        public virtual void EnemyGetsHit(float _damageDone, Vector2 _hitDirection, float _hitForce)
        {
            health -= _damageDone;
            if(!isRecoiling)
            {
               GameObject _WhiteBlood = Instantiate(WhiteBlood, transform.position, Quaternion.identity);
                Destroy(_WhiteBlood, 5.5f);
               rb.velocity = _hitForce * recoilFactor * _hitDirection;
            }
        }
    
        protected virtual void OnCollisionStay2D(Collision2D _other)
        {
    
            if (_other.gameObject.CompareTag("Player") && !PlayerController.Instance.pState.invincible && health > 0)
            {
                Attack();
                if (PlayerController.Instance.pState.alive)
                {
                    PlayerController.Instance.HitStopTime(0, 5, 0.5f);
                }
    
            }
        }
    
        protected virtual void UpdateEnemyStates() { }
        protected virtual void ChangeCurrentAnimation() { }
    
        protected void ChangeState(EnemyStates _newState)
        {
            GetCurrentEnemyState = _newState;
        }
        protected virtual void Attack()
        {
            PlayerController.Instance.TakeDamage(damage);
        }
    
        protected virtual void Death(float _destroyTime)
        {
            Destroy(gameObject, _destroyTime);
        }
    }
    
    #17710
    Ser Apustaja
    Level 6
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    Your enemy code has a solid structure, but there are a few issues that need to be addressed:

    1. HTML Entity Issues:

      • You have HTML entities like <, >, and & instead of the actual characters `, and&`. These will cause compilation errors. Replace them accordingly:
        • GetComponent<Rigidbody2D>() should be GetComponent()
        • if (_other.gameObject.CompareTag("Player") && ...) should be if (_other.gameObject.CompareTag("Player") && ...)
    2. Awake and Start Methods:

      • You are initializing rb in both Awake() and Start(). It’s generally better to initialize components in Awake() only, as it ensures they are ready before any other methods are called. You can remove the initialization from Start().
    3. Player Reference:

      • In the Awake() method, you are assigning player to PlayerController.Instance. Ensure that PlayerController.Instance is correctly set up and not null when this code runs.
    4. UpdateEnemyStates Method:

      • The UpdateEnemyStates() method is currently empty. You should implement the logic for handling different enemy states here, or ensure that derived classes override this method to provide their specific behavior.
    5. Death Method:

      • The Death() method is called but does not handle any cleanup or animation before destroying the game object. Consider adding any necessary animations or effects before calling Destroy().
    6. Health Check:

      • In the EnemyGetsHit() method, you should check if health is less than or equal to zero after reducing health. If it is, you should call the Death() method.

    Here’s a corrected snippet for the EnemyGetsHit() method:

    public virtual void EnemyGetsHit(float _damageDone, Vector2 _hitDirection, float _hitForce)
    {
        health -= _damageDone;
        if (health <= 0)
        {
            Death(2f); // Call Death with a specific time
        }
        else if (!isRecoiling)
        {
            GameObject _WhiteBlood = Instantiate(WhiteBlood, transform.position, Quaternion.identity);
            Destroy(_WhiteBlood, 5.5f);
            rb.velocity = _hitForce * recoilFactor * _hitDirection;
        }
    }

    Make these adjustments, and your enemy code should work more effectively. If you have any specific issues or behaviors you're observing, please let me know!

    #17711
    Terence
    Level 31
    Keymaster
    Helpful?
    Up
    0
    ::
    i have tried his first solution and that correct,should i try second solution?
    If the first solution works, then you don’t need to look at #2.

    Let me know if you have any other issues.

    #17713
    Pool ForReal
    Level 4
    Participant
    Helpful?
    Up
    0
    ::

    i have issue with my camera but i can’t upload on forum

    #17714
    Ser Apustaja
    Level 6
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    No problem! You can describe the issue you’re having with your camera in Unity, and I’ll do my best to help you troubleshoot it. Please provide details like:

    1. What specific problem are you experiencing with the camera? (e.g., is it not following the player, not rendering correctly, etc.)
    2. Are you using a specific camera script? If so, please share that code.
    3. Are there any error messages or unexpected behaviors you’re observing?

    The more details you provide, the better I can assist you!

    #17724
    Pool ForReal
    Level 4
    Participant
    Helpful?
    Up
    0
    ::

    my camera doesn’t show anything after i try modify my camera with cinemachine,the display not show anything when running

    View post on imgur.com

    when running

    View post on imgur.com

    camera settings

    #17725
    Ser Apustaja
    Level 6
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    It sounds like there might be a few potential issues with your Cinemachine camera setup. Here are some things to check:

    1. Camera Follow Target:

      • Ensure that your Cinemachine virtual camera’s “Follow” property is set to the player object. If it’s not set correctly, the camera won’t know what to follow.
    2. Camera Position:

      • Check the position of your Cinemachine virtual camera in the scene. If it’s positioned incorrectly (e.g., too far away or inside another object), it may not render anything.
    3. Field of View:

      • Make sure the camera’s field of view is set appropriately. If it’s too narrow or too wide, it might not capture the scene as expected.
    4. Culling Mask:

      • Verify that the culling mask of your camera includes the layers of the objects you want to see. If the layers are not included, the camera won’t render those objects.
    5. Camera Component:

      • Ensure that the main camera in your scene is not disabled and that it has a valid Camera component attached.
    6. Virtual Camera Activation:

      • Check if the virtual camera is enabled and active in the scene. If it’s not, it won’t render anything.
    7. Debugging:

      • You can add debug logs to check if the camera is correctly following the player. For example, log the position of the camera and the player each frame to see if they are updating as expected.

    If you’ve checked all these settings and are still having issues, could you provide more details about your camera settings or any specific configurations you’ve made? This will help narrow down the problem further.

    #17726
    Pool ForReal
    Level 4
    Participant
    Helpful?
    Up
    0
    ::

    but right now its error again, should i try second solution?

    #17727
    Ser Apustaja
    Level 6
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    It seems like you’re facing an issue with your camera setup in Unity, and you’re asking whether you should try a second solution regarding your previous concerns. Since the context isn’t fully clear, let me clarify a few things:

    1. If by “second solution” you mean revisiting the state management suggestions for your Bat enemy, then yes, it’s a good idea to ensure that everything is transitioning properly within the enemy’s state system. However, if you are currently focused on the camera issue, it might be best to address that first.

    2. For the camera issue, please provide specific details about the error you’re encountering. Are there any error messages showing in the console? Knowing this will help me provide more targeted advice.

    3. If you are still receiving errors related to the camera after trying the initial suggestions, please describe the specific errors or behaviors you are observing. This will allow me to give you more effective troubleshooting steps.

    Feel free to share any error messages or additional details about what you’re seeing with the camera, and I’ll do my best to help you resolve it!

    #17728
    Pool ForReal
    Level 4
    Participant
    Helpful?
    Up
    0
    ::

    but right now the code not correct, after i try solution 2

    #17729
    Ser Apustaja
    Level 6
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    It sounds like you’re experiencing issues with your code after implementing the second solution related to state management. Let’s work through this together.

    Here are some steps to help you troubleshoot the code:

    1. Review State Transition Logic:

      • Ensure that the logic for changing states in the ChangeState() method is working correctly. You might want to add debug logs to check if the state is changing as expected.
    2. Check State-Specific Behavior:

      • Verify that any state-specific behavior you added is functioning correctly. For example, if you added logic for Bat_Chase, make sure that the relevant code is executing when the enemy is in that state.
    3. Examine Any Errors:

      • Look for any error messages in the Unity console. If there are errors, they can provide insight into what might be going wrong.
    4. Debugging:

      • Use Debug.Log() statements to output key variables and states to the console. This can help you track down where the logic might be failing.
    5. Revert Temporary Changes:

      • If you made significant changes that are causing problems, consider reverting to the last known good state and gradually reintroducing changes to isolate the issue.
    6. Share Specific Issues:

      • If you’re encountering specific errors or unexpected behaviors, please share those details. Examples include error messages, what the expected behavior is, and what is actually happening.

    If you can provide more context or specific code snippets related to the issues you’re facing, I’ll be able to assist you better!

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

Go to Login Page →


Advertisement below: