Forum begins after the advertisement:


[Part 3] Help me with attacks

Home Forums Video Game Tutorial Series Creating a Metroidvania in Unity [Part 3] Help me with attacks

Viewing 3 posts - 1 through 3 (of 3 total)
  • Author
    Posts
  • #17335
    Josh kelly
    Level 1
    Participant
    Helpful?
    Up
    0
    ::

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

    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;
            }
        }
    }
    #17337
    Ser Apustaja
    Level 4
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    It looks like you’re having trouble with the attack functionality in your PlayerController script. Here are a few things to check and suggestions to help you troubleshoot the problem:

    1. Check Input Settings: Ensure that the “Fire1” input is correctly set up in Unity’s Input Manager. Go to Edit -> Project Settings -> Input Manager and check that the “Fire1” action is configured correctly.

    2. Attack Cooldown: You might want to add a cooldown mechanism for the attacks. Right now, the attack can be triggered every frame if the button is held down. Consider adding a variable to control the time between attacks, like this:

      float timeBetweenAttack = 0.5f; // Set this to your desired cooldown time
    3. Initialization of timeBetweenAttack: You haven’t initialized timeBetweenAttack anywhere in your code. Make sure it has a value at the start:

      void Start()
      {
          // ... other initializations
          timeBetweenAttack = 0.5f; // or whatever value you want
      }
    4. Debugging the Attack Function: You have some debug logs, which is great! Make sure to check the console output to see if “Side attack triggered!”, “Upward attack triggered!”, or “Downward attack triggered!” are being logged when you press the attack button.

    5. Check OverlapBox Parameters: Ensure that the SideAttackTransform, UpAttackTransform, and DownAttackTransform are set correctly in the Unity Editor and that their positions correspond to where you want your character to be able to hit. Also, ensure that SideAttackArea, UpAttackArea, and DownAttackArea have sensible sizes that match your intended attack hitboxes.

    6. Layer Mask for Attackable Objects: Make sure that the objects you are trying to hit are on the correct layer that corresponds to attackableLayer. If these objects are not on this layer, they won’t be detected by the attack.

    7. Check for Collider Issues: Ensure that the colliders of the attackable objects are set up correctly, and that they are not disabled or set to a layer that doesn’t interact with the player’s attack layer.

    8. Unity Physics Settings: Make sure that the Physics2D settings in Unity do not have any issues that could prevent the overlaps from registering correctly.

    9. Testing Hit Detection: If you’re still having issues, consider simplifying the Hit method to just log the position and size of the attack area:

      void Hit(Transform _attackTransform, Vector2 _attackArea)
      {
          Debug.Log($"Attacking at {_attackTransform.position} with area {_attackArea}");
          Collider2D[] objectsToHit = Physics2D.OverlapBoxAll(_attackTransform.position, _attackArea, 0, attackableLayer);
          Debug.Log($"Objects hit: {objectsToHit.Length}");
      }

    By checking these points, you should be able to identify and fix the issue with your attack not registering. If you’ve checked all of these and it still isn’t working, feel free to provide more details about what is happening when you attempt to attack, and I’ll do my best to assist further!

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

    @joshkelly if your issue is still not fixed, record a video of the attacks using ScreenToGif and post it here. I will have a look at it for you.

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

Go to Login Page →


Advertisement below: