Forum begins after the advertisement:


[Part 3] Recoil will still not work no matter what I try

Home Forums Video Game Tutorial Series Creating a Metroidvania in Unity [Part 3] Recoil will still not work no matter what I try

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

    Idk what to do I did most things suggested but it just will not work so help idk if its something to do with the inspector or something else

        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("Attacking")]
            bool attack = false;
            float timeBetweenAttack, timeSinceAttack;
            [SerializeField] Transform SideAttackTransform, UpAttackTransform, DownAttackTransform;
            [SerializeField] Vector2 SideAttackArea, UpAttackArea, DownAttackArea;
            [SerializeField] LayerMask attackableLayer;
            [SerializeField] float damage;
            [SerializeField] GameObject slashEffect;
            [Space(5)]
    
    
            [Header("Recoiling")]
    
            [SerializeField] int recoilXSteps = 5;
            [SerializeField] int recoilYSteps = 5;
            [SerializeField] float recoilXSpeed = 100;
            [SerializeField] float recoilYSpeed = 100;
            int stepsXRecoiled, stepsYRecoiled;
    
    
    
    
    
    
    
            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
    
    
            }
            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();
                Recoil();
    
                if (pState.dashing) return;
                Flip();
                Move();
                Jump();
                StartDash();
                Attack();
    
            }
    
            void GetInputs()
            {
                xAxis = Input.GetAxisRaw("Horizontal");
                yAxis = Input.GetAxisRaw("Vertical");
                attack = Input.GetMouseButtonDown(0);
    
            }
    
            void Flip()
            {
                if (xAxis < 0)
                {
                    transform.localScale = new Vector2(-1, transform.localScale.y);
                    pState.lookingRight = false;
                }
                else if (xAxis > 0)
                {
                    transform.localScale = new Vector2(1, transform.localScale.y);
                    pState.lookingRight = true;
                }
            }
    
            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)
                    {
    
                    }
                    else if (dashed)
                    {
    
                    }
                    else
                    {
    
                        StartCoroutine(Dash());
                        dashed = true;
                    }
                }
    
                if (Grounded())
                {
                    dashed = false;
                }
            }
    
            IEnumerator Dash()
            {
    
                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
    
            }
            void Attack()
            {
                timeSinceAttack += Time.deltaTime;
                if(attack && timeSinceAttack >= timeBetweenAttack)
                {
                    timeSinceAttack = 0;
                    anim.SetTrigger("Attacking");
    
                    if(yAxis == 0 || yAxis < 0 && Grounded())
                    {
                        Hit(SideAttackTransform, SideAttackArea, ref pState.recoilingX, recoilXSpeed);
                        Instantiate(slashEffect, SideAttackTransform);
                    }
                    else if(yAxis > 0)
                    {
                        Hit(UpAttackTransform, UpAttackArea, ref pState.recoilingY, recoilYSpeed);
                        SlashEffectAtAngle(slashEffect, 80, UpAttackTransform);
                    }
                    else if(yAxis < 0 && !Grounded())
                    {
                        Hit(DownAttackTransform, DownAttackArea, ref pState.recoilingY, recoilYSpeed);
                        SlashEffectAtAngle(slashEffect, -90, DownAttackTransform);
                    }
                }
            }
    
            void Hit(Transform _attackTransform, Vector2 _attackArea, ref bool _recoilDir, float _recoilStrength)
    {
    
                Collider2D[] objectsToHit = Physics2D.OverlapBoxAll(_attackTransform.position, _attackArea, 0, attackableLayer);
    
                if(objectsToHit.Length > 0)
                {
                    _recoilDir = true; // Here you should set the corresponding state in PlayerStateList
    
                }
                for(int i = 0; i < objectsToHit.Length; i++)
                {
                    if(objectsToHit[i].GetComponent<Enemy>() !=null)
                    {
                        objectsToHit[i].GetComponent<Enemy>().EnemyHit(damage, (transform.position - objectsToHit[i].transform.position).normalized, _recoilStrength);
    
                    }
                }
            }
            void SlashEffectAtAngle(GameObject _slashEffect, int _effectAngle, Transform _attackTransform)
            {
                _slashEffect = Instantiate(_slashEffect, _attackTransform);
                _slashEffect.transform.eulerAngles = new Vector3(0, 0, _effectAngle);
                _slashEffect.transform.localScale = new Vector2(transform.localScale.x, _attackTransform.localScale.y);
            }
    
    
    
             void Recoil()
        {
            Debug.Log("Recoil");
            if(pState.recoilingX)
            {
                if(pState.lookingRight)
                {
                    rb.velocity = new Vector2(-recoilXSpeed, 0);
                }
                else
                {
                    rb.velocity = new Vector2(recoilXSpeed, 0);
                }
            }
    
            if(pState.recoilingY)
            {
                rb.gravityScale = 0;
                if (yAxis < 0)
                {                
                    rb.velocity = new Vector2(rb.velocity.x, recoilYSpeed);
                }
                else
                {
                    rb.velocity = new Vector2(rb.velocity.x, -recoilYSpeed);
                }
                airJumpCounter = 0;
            }
            else
            {
                rb.gravityScale = gravity;
            }
    
    
    
                //stop recoil
                if(pState.recoilingX && stepsXRecoiled < recoilXSteps)
                {
                    stepsXRecoiled++;
                }
                else
                {
                    StopRecoilX();
                }
    
    
                if(pState.recoilingY && stepsYRecoiled < recoilYSteps)
                {
                    stepsYRecoiled++;
                }
                else
                {
                    StopRecoilY();
                }
    
    
                if(Grounded())
                {
                    StopRecoilY();
                }
            }   
    
            void StopRecoilX()
            {
                stepsXRecoiled = 0;
                pState.recoilingX = false;
            }
            void StopRecoilY()
            {
                stepsYRecoiled = 0;
                pState.recoilingY = false;
            }
    
    
            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, rb.velocity.y * 0.5f); // Reduce jump height
                     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;
                 jumpBufferCounter = 0; // Reset jump buffer when grounded
                }
                else
                {
                    coyoteTimeCounter -= Time.deltaTime;
                }
    
                if (Input.GetButtonDown("Jump"))
                {
                    jumpBufferCounter = jumpBufferFrames;
                }
                else
                {
                    jumpBufferCounter = jumpBufferCounter - Time.deltaTime *10;
                }
            }
        }
    #17399
    Josh kelly
    Level 1
    Participant
    Helpful?
    Up
    0
    ::

    I figured out that the enemy moves when i attack it when increasing or decreasing recoilxspeed but not the player and the player gets sent when i attack from above

    #17400
    Ser Apustaja
    Level 5
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    It seems like you’re trying to manage the movement behavior of both the enemy and the player in your game, particularly in response to attacks. If the enemy is moving when you attack it but the player is not behaving as expected, there may be several factors at play. Here’s a general approach to debug and resolve this issue:

    1. Check Player Movement Logic: Ensure that the player movement logic is correctly implemented. If you want the player to move or react to attacks, you need to ensure that the movement code is triggered in response to the attack.

    2. Verify Attack Logic: When you perform an attack, ensure that the correct events are being fired. For example, check if the attack triggers any movement changes for the player.

    3. Recoil Logic: If you are using recoilxspeed to adjust movement, ensure that this variable is applied to the player’s movement logic when they are attacked. You might need a separate function that handles the recoil for the player.

    4. Collision Detection: If the player is being sent flying when attacking from above, check your collision detection logic. It’s possible that the attack from above has a different set of rules compared to other angles.

    5. Debugging: You can add debug prints or logs to help you understand what values are being processed when the player attacks. For instance, print the current position, speed, and any other relevant variables whenever an attack is initiated.

    6. Handling States: If your game uses states (like idle, attacking, etc.), make sure the player is in the correct state when an attack is performed. If the player is in an “attacking” state, you might want to prevent movement or apply different movement logic.

    7. Test Different Scenarios: Try attacking from various angles and distances to see if the behavior changes. This can help isolate the problem.

    If you can provide a snippet of your code related to player movement and attack handling, I can offer more specific assistance to help you resolve the issue.

    #17404
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::
    I figured out that the enemy moves when i attack it when increasing or decreasing recoilxspeed but not the player and the player gets sent when i attack from above
    Is your issue fixed?
    #17412
    Josh kelly
    Level 1
    Participant
    Helpful?
    Up
    0
    ::

    No idk how to fix it I just realised that my enemy moves with recoilxspeed instead of my player

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

    Can you upload your project onto Google Drive and share the link here? I will help you have a look.

    #17441
    Josh kelly
    Level 1
    Participant
    #17442
    Ser Apustaja
    Level 5
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    It looks like you’re trying to create a hyperlink in HTML that directs users to a Google Drive folder. The code you’ve provided seems mostly correct. Here’s a breakdown of your code:

    <a href="https://drive.google.com/drive/folders/1R8Nfe2o0aC4lQGFnEKB20WTRsQ5kbqJc?usp=drive_link" target="_blank">This should bring you to it</a>

    Explanation:

    • <a>: This is the anchor tag used to create hyperlinks.
    • href: This attribute specifies the URL of the page the link goes to.
    • target="_blank": This attribute opens the link in a new tab.
    • The text between the opening and closing <a> tags (“This should bring you to it”) is what users will see and click on.

    Improvements:

    1. Accessibility: Consider adding rel="noopener noreferrer" to your link for security reasons when using target="_blank".

    Here’s the improved version of your code:

    <a href="https://drive.google.com/drive/folders/1R8Nfe2o0aC4lQGFnEKB20WTRsQ5kbqJc?usp=drive_link" target="_blank" rel="noopener noreferrer">This should bring you to it</a>

    Usage:

    You can use this code snippet in your HTML file where you want the link to appear. When users click on “This should bring you to it,” they will be redirected to the specified Google Drive folder in a new tab.

    If you have any specific issues or additional questions about your code, feel free to ask!

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

    @joshkelly I’m unable to access the file. Sent you an access request.

    #17466
    Josh kelly
    Level 1
    Participant
    Helpful?
    Up
    0
    ::

    Done I think

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

    @joshkelly sorry I still don’t have access. Check your Gmail. An access request should have been sent to you.

    #17520
    Josh kelly
    Level 1
    Participant
    Helpful?
    Up
    0
    ::

    Sorry I shared it now

    #17521
    Ser Apustaja
    Level 5
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    No problem, Josh! If you need help with your code or anything else, feel free to share the details, and I’ll do my best to assist you!

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

    @joshkelly found the issue. It was with the Move() function in PlayerController. You need to add the highlighted line:

        private void Move()
        {
            if(pState.recoilingX) return;
            rb.velocity = new Vector2(Walkspeed * xAxis, rb.velocity.y);
            anim.SetBool("Walking", rb.velocity.x != 0 && Grounded());
        }

    The prevents the character from moving around when we are recoiling. Otherwise, the Move() function will overwrite the recoilX force by resetting the velocity. It’s a bug that we missed out when making the video.

    Hope this helps!

    #17559
    Josh kelly
    Level 1
    Participant
    Helpful?
    Up
    0
    ::

    Thanks it works somewhat it just launches me but i should be able to fix that

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

Go to Login Page →


Advertisement below: