Forum begins after the advertisement:


Hey my attacks will not register attacking help me find whats wrong in my code.

Home Forums Video Game Tutorial Series Creating a Metroidvania in Unity Hey my attacks will not register attacking help me find whats wrong in my code.

Viewing 4 posts - 1 through 4 (of 4 total)
  • Author
    Posts
  • #17334
    Josh kelly
    Level 1
    Participant
    Helpful?
    Up
    0
    ::
    
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class PlayerController : MonoBehaviour
    {
        [Header("Horizontal Movement Settings")]
        [SerializeField] private float Walkspeed = 1;
        [Space(5)]
    
    
        [Header("Vertical Movement Settings")]
        [SerializeField] private float Jumpforce = 45;
        private float jumpBufferCounter = 0;
        [SerializeField] private float jumpBufferFrames;
        private float coyoteTimeCounter = 0;
        [SerializeField] private float coyoteTime;
        private int airJumpCounter = 0;
        [SerializeField] private int maxAirJumps; 
        [Space(5)]
    
    
        [Header("Ground Check Settings")]
        [SerializeField] private Transform groundCheckPoint;
        [SerializeField] private float groundCheckY = 0.2f;
        [SerializeField] private float groundCheckX = 0.5f;
        [SerializeField] private LayerMask whatIsGround;
        [Space(5)]
    
    
        [Header("Dash Settings")]
        [SerializeField] private float dashSpeed;
        [SerializeField] private float dashTime;
        [SerializeField] private float dashCooldown;
        [SerializeField] GameObject dashEffect;
        [Space(5)]
    
        [Header("Attack Settings")]
        bool attack = false;
        float timeBetweenAttack, timeSinceAttack;
        [SerializeField] Transform SideAttackTransform, UpAttackTransform, DownAttackTransform;
        [SerializeField] Vector2 SideAttackArea, UpAttackArea, DownAttackArea;
        [SerializeField] LayerMask attackableLayer;
    
        PlayerStateList pState;
        private Rigidbody2D rb;
        private float xAxis, yAxis;
        private float gravity;
    
        private bool canDash; 
        private bool dashed;
    
        Animator anim;
    
        public static PlayerController Instance;
    
        private void Awake()
        {
            if (Instance != null && Instance != this)
            {
                Destroy(gameObject);
            }
            else
            {
                Instance = this;
            }
        }
    
        // Start is called before the first frame update
        void Start()
        {
            rb = GetComponent<Rigidbody2D>(); 
            anim = GetComponent<Animator>();
            pState = GetComponent<PlayerStateList>();
            gravity = rb.gravityScale;
            canDash = true;  // Ensure dashing is enabled at the start
            print($"Can Dash on start: {canDash}");
        }
    
        private void OnDrawGizmos()
        {
            Gizmos.color = Color.red;
            Gizmos.DrawWireCube(SideAttackTransform.position, SideAttackArea);
            Gizmos.DrawWireCube(UpAttackTransform.position, UpAttackArea);
            Gizmos.DrawWireCube(DownAttackTransform.position, DownAttackArea);
        }
    
        // Update is called once per frame
        void Update()
        {
            GetInputs();
            UpdateJumpVariables();
    
            if (pState.dashing) return;
            Flip();
            Move();
            Jump();
            StartDash();
            Attack();
        }
    
        void GetInputs()
        {
            xAxis = Input.GetAxisRaw("Horizontal");
            yAxis = Input.GetAxisRaw("Vertical");
            attack = Input.GetButtonDown("Fire1");
        }
    
        void Flip()
        {
            if (xAxis < 0)
            {
                transform.localScale = new Vector2(-1, transform.localScale.y);
            }
            else if (xAxis > 0)
            {
                transform.localScale = new Vector2(1, transform.localScale.y);
            }
        }
    
        private void Move()
        {
            rb.velocity = new Vector2(Walkspeed * xAxis, rb.velocity.y);
            anim.SetBool("Walking", rb.velocity.x != 0 && Grounded());
        }
    
        void StartDash()
        {
            if (Input.GetButtonDown("Dash"))
            {
                if (!canDash)
                {
                    print("Can't dash yet.");
                }
                else if (dashed)
                {
                    print("Already dashed.");
                }
                else
                {
                    print("Starting dash...");
                    StartCoroutine(Dash());
                    dashed = true;
                }
            }
    
            if (Grounded())
            {
                dashed = false;
            }
        }
    
        IEnumerator Dash()
        {
            print("Dash coroutine started");
            canDash = false; // Disable dashing until cooldown is finished
            pState.dashing = true;
            anim.SetTrigger("Dashing");
            rb.gravityScale = 0;
            rb.velocity = new Vector2(transform.localScale.x * dashSpeed, 0);
            if(Grounded()) Instantiate(dashEffect, transform);
            yield return new WaitForSeconds(dashTime); // Dash duration
            pState.dashing = false; // Stop the dash animation
            anim.ResetTrigger("Dashing"); // Reset the dash trigger in case it was still set
            rb.gravityScale = gravity;
            pState.dashing = false;
            yield return new WaitForSeconds(dashCooldown); // Dash cooldown time
            canDash = true; // Re-enable dashing after cooldown
            print("Dash coroutine finished");
            print("Dashing cooled down");
        }
    
        void Attack()
        {
            timeSinceAttack += Time.deltaTime;
            if(attack && timeSinceAttack >= timeBetweenAttack)
            {
                timeSinceAttack = 0;
                anim.SetTrigger("Attacking");
    
                if(yAxis == 0 || yAxis < 0 && Grounded())
                {
                    Debug.Log("Side attack triggered!");
                    Hit(SideAttackTransform, SideAttackArea);
                }
                else if(yAxis > 0)
                {
                    Debug.Log("Upward attack triggered!");
                    Hit(UpAttackTransform, UpAttackArea);
                }
                else if(yAxis < 0 && !Grounded())
                {
                    Debug.Log("Downward attack triggered!");
                    Hit(DownAttackTransform, DownAttackArea);
                }
    
            }
        }
    
        void Hit(Transform _attackTransform, Vector2 _attackArea)
        {
            // Debugging: Log attack position and area
            Debug.Log($"Checking attack at position: {_attackTransform.position} with area: {_attackArea}");
    
            Collider2D[] objectsToHit = Physics2D.OverlapBoxAll(_attackTransform.position, _attackArea, 0, attackableLayer);
    
            if (objectsToHit.Length > 0)
            {
                // Debugging: Log the objects hit
                Debug.Log("Hit objects:");
                foreach (var hit in objectsToHit)
                {
                    Debug.Log("Hit: " + hit.gameObject.name);  // Log the name of the object hit
                }
            }
            else
            {
                Debug.Log("No objects hit.");
            }
        }
    
        public bool Grounded()
        {
            if (Physics2D.Raycast(groundCheckPoint.position, Vector2.down, groundCheckY, whatIsGround) ||
                Physics2D.Raycast(groundCheckPoint.position + new Vector3(-groundCheckX, 0, 0), Vector2.down, groundCheckY, whatIsGround) ||
                Physics2D.Raycast(groundCheckPoint.position + new Vector3(groundCheckX, 0, 0), Vector2.down, groundCheckY, whatIsGround))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    
        void Jump()
        {
            if (Input.GetButtonUp("Jump") && rb.velocity.y > 0)
            {
                rb.velocity = new Vector2(rb.velocity.x, 0);
                pState.jumping = false;
            }
    
            if (jumpBufferCounter > 0 && coyoteTimeCounter > 0)
            {
                rb.velocity = new Vector3(rb.velocity.x, Jumpforce);
                pState.jumping = true;
            }
            else if (!Grounded() && airJumpCounter < maxAirJumps && Input.GetButtonDown("Jump"))
            {
                pState.jumping = true;
                airJumpCounter++;
                rb.velocity = new Vector3(rb.velocity.x, Jumpforce);
            }
    
            anim.SetBool("Jumping", !Grounded());
        }
    
        void UpdateJumpVariables()
        {
            if (Grounded())
            {
                pState.jumping = false;
                coyoteTimeCounter = coyoteTime;
                airJumpCounter = 0;
            }
            else
            {
                coyoteTimeCounter -= Time.deltaTime;
            }
    
            if (Input.GetButtonDown("Jump"))
            {
                jumpBufferCounter = jumpBufferFrames;
            }
            else
            {
                jumpBufferCounter = jumpBufferCounter - Time.deltaTime * 10;
            }
        }
    }```
    #17336
    Ser Apustaja
    Level 4
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    Your code for the PlayerController looks quite comprehensive, but it seems like you might have some issues with the logic or functionality. Here are a few suggestions and common pitfalls you might want to check:

    1. HTML Entities in Code: It looks like you’ve copied the code with HTML entities instead of regular symbols. Make sure to replace instances of < with `, and&with&`. This is crucial for your code to compile properly.

    2. Jump Logic: Ensure that your jump logic works as intended. The jump buffer and coyote time are good practices, but make sure that jumpBufferCounter and coyoteTimeCounter are properly used. For instance, you should reset jumpBufferCounter when you jump.

    3. Dash Logic: The dash logic appears to be functional, but ensure that your dashCooldown and dashTime values are set appropriately in the inspector. The print statements will help you debug if your dash is being triggered correctly.

    4. Animation States: Make sure that your Animator Controller has the proper transitions for “Walking”, “Jumping”, “Dashing”, and “Attacking”. Missing transitions or incorrect parameter names can lead to animations not playing as expected.

    5. Ground Check Logic: Your Grounded method uses raycasting to check for the ground. Ensure that your groundCheckPoint, groundCheckY, and whatIsGround are set correctly in the inspector. If the raycast is not hitting anything, the character may not be recognized as grounded.

    6. Attack Logic: Your attack method might need a check to see if the player is currently attacking before allowing another attack. You might want to add a boolean flag to prevent spamming attacks.

    7. Debugging: Use Debug.Log statements liberally to help track down any issues. For instance, log the values of jumpBufferCounter, coyoteTimeCounter, and other key variables at various points in your code.

    8. Testing: If the player isn’t moving or jumping as expected, double-check your input settings in Unity (Edit > Project Settings > Input) to ensure that “Horizontal”, “Vertical”, “Jump”, and “Dash” are set up correctly.

    Here’s a quick fix for the HTML entities in the Flip function as an example:

    void Flip()
    {
        if (xAxis  0)
        {
            transform.localScale = new Vector2(1, transform.localScale.y);
        }
    }

    Make sure to go through your entire script and replace all instances of HTML entities with the correct symbols. If you continue to face issues, please provide specific error messages or describe what behavior is not functioning as expected!

    #17338
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::

    @ser.apustaja, please try again. He says his attacks will not register attacking. Can you scan through the code again and find out why?

    Treat any HTML characters as the characters they represent, and access the code only for C#.

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class PlayerController : MonoBehaviour
    {
        [Header("Horizontal Movement Settings")]
        [SerializeField] private float Walkspeed = 1;
        [Space(5)]
    
    
        [Header("Vertical Movement Settings")]
        [SerializeField] private float Jumpforce = 45;
        private float jumpBufferCounter = 0;
        [SerializeField] private float jumpBufferFrames;
        private float coyoteTimeCounter = 0;
        [SerializeField] private float coyoteTime;
        private int airJumpCounter = 0;
        [SerializeField] private int maxAirJumps; 
        [Space(5)]
    
    
        [Header("Ground Check Settings")]
        [SerializeField] private Transform groundCheckPoint;
        [SerializeField] private float groundCheckY = 0.2f;
        [SerializeField] private float groundCheckX = 0.5f;
        [SerializeField] private LayerMask whatIsGround;
        [Space(5)]
    
    
        [Header("Dash Settings")]
        [SerializeField] private float dashSpeed;
        [SerializeField] private float dashTime;
        [SerializeField] private float dashCooldown;
        [SerializeField] GameObject dashEffect;
        [Space(5)]
    
        [Header("Attack Settings")]
        bool attack = false;
        float timeBetweenAttack, timeSinceAttack;
        [SerializeField] Transform SideAttackTransform, UpAttackTransform, DownAttackTransform;
        [SerializeField] Vector2 SideAttackArea, UpAttackArea, DownAttackArea;
        [SerializeField] LayerMask attackableLayer;
    
        PlayerStateList pState;
        private Rigidbody2D rb;
        private float xAxis, yAxis;
        private float gravity;
    
        private bool canDash; 
        private bool dashed;
    
        Animator anim;
    
        public static PlayerController Instance;
    
        private void Awake()
        {
            if (Instance != null && Instance != this)
            {
                Destroy(gameObject);
            }
            else
            {
                Instance = this;
            }
        }
    
        // Start is called before the first frame update
        void Start()
        {
            rb = GetComponent<Rigidbody2D>(); 
            anim = GetComponent<Animator>();
            pState = GetComponent<PlayerStateList>();
            gravity = rb.gravityScale;
            canDash = true;  // Ensure dashing is enabled at the start
            print($"Can Dash on start: {canDash}");
        }
    
        private void OnDrawGizmos()
        {
            Gizmos.color = Color.red;
            Gizmos.DrawWireCube(SideAttackTransform.position, SideAttackArea);
            Gizmos.DrawWireCube(UpAttackTransform.position, UpAttackArea);
            Gizmos.DrawWireCube(DownAttackTransform.position, DownAttackArea);
        }
    
        // Update is called once per frame
        void Update()
        {
            GetInputs();
            UpdateJumpVariables();
    
            if (pState.dashing) return;
            Flip();
            Move();
            Jump();
            StartDash();
            Attack();
        }
    
        void GetInputs()
        {
            xAxis = Input.GetAxisRaw("Horizontal");
            yAxis = Input.GetAxisRaw("Vertical");
            attack = Input.GetButtonDown("Fire1");
        }
    
        void Flip()
        {
            if (xAxis < 0)
            {
                transform.localScale = new Vector2(-1, transform.localScale.y);
            }
            else if (xAxis > 0)
            {
                transform.localScale = new Vector2(1, transform.localScale.y);
            }
        }
    
        private void Move()
        {
            rb.velocity = new Vector2(Walkspeed * xAxis, rb.velocity.y);
            anim.SetBool("Walking", rb.velocity.x != 0 && Grounded());
        }
    
        void StartDash()
        {
            if (Input.GetButtonDown("Dash"))
            {
                if (!canDash)
                {
                    print("Can't dash yet.");
                }
                else if (dashed)
                {
                    print("Already dashed.");
                }
                else
                {
                    print("Starting dash...");
                    StartCoroutine(Dash());
                    dashed = true;
                }
            }
    
            if (Grounded())
            {
                dashed = false;
            }
        }
    
        IEnumerator Dash()
        {
            print("Dash coroutine started");
            canDash = false; // Disable dashing until cooldown is finished
            pState.dashing = true;
            anim.SetTrigger("Dashing");
            rb.gravityScale = 0;
            rb.velocity = new Vector2(transform.localScale.x * dashSpeed, 0);
            if(Grounded()) Instantiate(dashEffect, transform);
            yield return new WaitForSeconds(dashTime); // Dash duration
            pState.dashing = false; // Stop the dash animation
            anim.ResetTrigger("Dashing"); // Reset the dash trigger in case it was still set
            rb.gravityScale = gravity;
            pState.dashing = false;
            yield return new WaitForSeconds(dashCooldown); // Dash cooldown time
            canDash = true; // Re-enable dashing after cooldown
            print("Dash coroutine finished");
            print("Dashing cooled down");
        }
    
        void Attack()
        {
            timeSinceAttack += Time.deltaTime;
            if(attack && timeSinceAttack >= timeBetweenAttack)
            {
                timeSinceAttack = 0;
                anim.SetTrigger("Attacking");
    
                if(yAxis == 0 || yAxis < 0 && Grounded())
                {
                    Debug.Log("Side attack triggered!");
                    Hit(SideAttackTransform, SideAttackArea);
                }
                else if(yAxis > 0)
                {
                    Debug.Log("Upward attack triggered!");
                    Hit(UpAttackTransform, UpAttackArea);
                }
                else if(yAxis < 0 && !Grounded())
                {
                    Debug.Log("Downward attack triggered!");
                    Hit(DownAttackTransform, DownAttackArea);
                }
    
            }
        }
    
        void Hit(Transform _attackTransform, Vector2 _attackArea)
        {
            // Debugging: Log attack position and area
            Debug.Log($"Checking attack at position: {_attackTransform.position} with area: {_attackArea}");
    
            Collider2D[] objectsToHit = Physics2D.OverlapBoxAll(_attackTransform.position, _attackArea, 0, attackableLayer);
    
            if (objectsToHit.Length > 0)
            {
                // Debugging: Log the objects hit
                Debug.Log("Hit objects:");
                foreach (var hit in objectsToHit)
                {
                    Debug.Log("Hit: " + hit.gameObject.name);  // Log the name of the object hit
                }
            }
            else
            {
                Debug.Log("No objects hit.");
            }
        }
    
        public bool Grounded()
        {
            if (Physics2D.Raycast(groundCheckPoint.position, Vector2.down, groundCheckY, whatIsGround) ||
                Physics2D.Raycast(groundCheckPoint.position + new Vector3(-groundCheckX, 0, 0), Vector2.down, groundCheckY, whatIsGround) ||
                Physics2D.Raycast(groundCheckPoint.position + new Vector3(groundCheckX, 0, 0), Vector2.down, groundCheckY, whatIsGround))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    
        void Jump()
        {
            if (Input.GetButtonUp("Jump") && rb.velocity.y > 0)
            {
                rb.velocity = new Vector2(rb.velocity.x, 0);
                pState.jumping = false;
            }
    
            if (jumpBufferCounter > 0 && coyoteTimeCounter > 0)
            {
                rb.velocity = new Vector3(rb.velocity.x, Jumpforce);
                pState.jumping = true;
            }
            else if (!Grounded() && airJumpCounter < maxAirJumps && Input.GetButtonDown("Jump"))
            {
                pState.jumping = true;
                airJumpCounter++;
                rb.velocity = new Vector3(rb.velocity.x, Jumpforce);
            }
    
            anim.SetBool("Jumping", !Grounded());
        }
    
        void UpdateJumpVariables()
        {
            if (Grounded())
            {
                pState.jumping = false;
                coyoteTimeCounter = coyoteTime;
                airJumpCounter = 0;
            }
            else
            {
                coyoteTimeCounter -= Time.deltaTime;
            }
    
            if (Input.GetButtonDown("Jump"))
            {
                jumpBufferCounter = jumpBufferFrames;
            }
            else
            {
                jumpBufferCounter = jumpBufferCounter - Time.deltaTime * 10;
            }
        }
    }
    #17341
    Ser Apustaja
    Level 4
    AI Assistant
    (BETA)
    Helpful?
    Up
    1
    ::

    Based on the provided code for the PlayerController class, it looks like you’ve implemented a basic attack system. If the attacks are not registering, there are a few potential areas that could be causing the issue. Here are some things to check and suggestions for debugging:

    1. Attack Input Handling:

      • Ensure that the “Fire1” input is correctly set up in your Input settings in Unity. By default, “Fire1” is usually mapped to the left Ctrl key or mouse button.
      • Check if the attack variable is being set correctly when the attack button is pressed. You can add a debug log in GetInputs() to confirm that the input is being detected:
        void GetInputs()
        {
            xAxis = Input.GetAxisRaw("Horizontal");
            yAxis = Input.GetAxisRaw("Vertical");
            attack = Input.GetButtonDown("Fire1");
            Debug.Log($"Attack input: {attack}");
        }
    2. Time Between Attacks:

      • Make sure that timeBetweenAttack is set to a reasonable value. If it’s too high, you might not be able to attack often enough.
      • If it’s not initialized anywhere in your code, it will default to 0, which could lead to unexpected behavior.
    3. Attack Area and Hit Detection:

      • Verify that the SideAttackTransform, UpAttackTransform, and DownAttackTransform are correctly set in the Unity Inspector. They should be positioned where you expect the attack detection to occur.
      • Check that SideAttackArea, UpAttackArea, and DownAttackArea have reasonable dimensions for detecting hits. If they are too small, the attack might not register.
      • You can log the sizes and positions of your attack areas in the Hit method:
        void Hit(Transform _attackTransform, Vector2 _attackArea)
        {
            Debug.Log($"Checking attack at position: {_attackTransform.position} with area: {_attackArea}");
            // ... rest of the code ...
        }
    4. Layer Masks:

      • Ensure that the attackableLayer mask is correctly set in the Inspector. The objects you want to hit should be on a layer that is included in this mask.
    5. Physics Overlap Check:

      • If the physics overlap check is not returning any colliders, it indicates that there are no objects within the specified area. Confirm that the attack areas are indeed overlapping with the objects you expect to hit.
    6. Animator Triggers:

      • Check if the animator is correctly set up to respond to the “Attacking” trigger. If the attack animation is not playing, it might be an indication that the Animator setup is incorrect.

    By going through these checks and adding debug logs, you should be able to pinpoint where the issue lies. If after these checks the attacks are still not registering, consider isolating the attack logic in a simpler context to test it separately, ensuring that the attack mechanics work independently of other game systems.

      1 anonymous person
    has upvoted this post.
Viewing 4 posts - 1 through 4 (of 4 total)
  • You must be logged in to reply to this topic.

Go to Login Page →


Advertisement below: