Forum begins after the advertisement:


[Part 2] Inconsistent Dash Distance

Home Forums Video Game Tutorial Series Creating a Metroidvania in Unity [Part 2] Inconsistent Dash Distance

Viewing 7 posts - 1 through 7 (of 7 total)
  • Author
    Posts
  • #14678
    Joshua
    Level 2
    Participant
    Helpful?
    Up
    0
    ::

    I’m using the following code to dash, and calculate its distance. Results can range from 4 units moved to 2, and more minor variations in between.

    <code>    private IEnumerator Dash()
        {
            Vector2 start = rbody.position;
            canDash = false;
            state = State.DASHING;
            animator.SetTrigger("dash");
            rbody.gravityScale = 0;
            rbody.velocity = new Vector2(transform.localScale.x * dashSpeed, 0);
            if (IsGrounded()) Instantiate(dashDustEffect, transform);
            yield return new WaitForSeconds(dashTime);
            rbody.gravityScale = gravity;
            rbody.velocity = Vector2.zero;
            state = State.IDLE;
            yield return new WaitForSeconds(dashCooldown);
            canDash = true;
            CalculateDistance(start);
        }
    
        private void CalculateDistance(Vector2 originalPosition)
        {
            Vector2 distance = rbody.position - originalPosition;
            Debug.Log("Distance: " + distance.x);
        }</code>

    Dash() is called by CheckDash():

    <code>    private void CheckDash()
        {
            if (isDashButtonPressed)
            {
                if (canDash && state != State.DASHING && airDashCount < maxAirDashes)
                {
                    if (!IsGrounded()) airDashCount++;
                    StartCoroutine(Dash());
                }
                else if (!canDash) Debug.LogWarning("canDash is false.");
                else if (state == State.DASHING) Debug.LogWarning("State is DASHING.");
            }
        }</code>

    And CheckDash() is running in Update():

    <code>    void Update()
        {
            ProcessInput();
            if (state != State.DASHING)
            {
                Move();
                CheckJump();
                CheckDash();
                SetTransformScale();
            }
        }</code>

    Putting the Dash() code in FixedUpdate() fixes the distance issue, but when input isn’t checked for in Update() input registration becomes very inconsistent. I’ve tried decoupling the logic, putting parts into Update() and parts into FixedUpdate(), but I can’t quite get things to work. Advice would be welcome!

    #14680
    Joseph Tang
    Level 13
    Moderator
    Helpful?
    Up
    0
    ::

    I’ve tested your code out and nothing is wrong about it. Similarly, the code we use have just about the same effect. Both experience minor distance difference from dashing. Because of this, i suspect that the reason behind the inconsistency is the update rates in Unity not being fast/consistent enough to keep track of the WaitForSeconds accurately.

    Testing out the values of the distance, i can say that with a dashTime of [0.2], the player can move the correct distance of dashSpeed * 0.2. or have a distance of [0.22]. This can be evident if you use a smaller dashSpeed value of [1] or [10].

    Moving the code to FixedUpdate() does not appear to solve this issue either as the dashTime effectively increased to [0.22], with some inconsistencies to increase further to [0.24].

    Of course, in lower dashSpeed values, such an inconsistency is fine, but with higher values, the [0.02] difference is quite high. Thus, I would recommend using a method that does not involve WaitForSeconds but something more solid/accurate. Like using the CalculateDistance() method you have.

    For instance, you could split up the Dash() code into two parts, one which activates the dash animation and speed boost, & a code to check if you’ve reached the desired destination of (originalPosition.x + _distance, rb.position.y), which then stops the dashing.

    #14681
    Joshua
    Level 2
    Participant
    Helpful?
    Up
    0
    ::

    Thank you for the reply! I didn’t realize just how much the margin of error scaled with the amount of ‘dashSpeed’ I multiplied with. I was using rather high numbers (70-120) to get that snappy ‘instant’ feel. With my current settings things still feel pretty good, with less variant in distance:

    View post on imgur.com

    After dashing a bunch of times, the largest difference is about ~0.6 (4.2 – 3.5999). I honestly have no idea whether this is acceptable; do games like Hollow Knight have 100% consistency? One might assume with gameplay sections like Path of Pain.

    #14682
    Joseph Tang
    Level 13
    Moderator
    Helpful?
    Up
    0
    ::

    To add on, this is caused by Unity’s Project Settings for time, being at a fixed timestep of [0.02] which acts as the update rate for your physics engine and time. [Essentially 50fps].

    So, good to keep in mind the limitation for unity’s update rate, but i recommend taking a shot at the suggestion of tracking the position difference instead of the time difference as when you have higher dashSpeed’s, it might do better to constrain the distance than the time.

    You can also see this fixed time step affect other things such as character and camera jittering and how interpolate helps with it in our article here:

    Fix jittery camera movement in Unity with Rigidbody Interpolate

    To see exactly how timestep works for Unity, look into this.

    #14683
    Joshua
    Level 2
    Participant
    Helpful?
    Up
    0
    ::

    Thanks for the extra information. Which makes me think: is there a reason why the guide doesn’t just interpolate from position A to B, depending on desired distance and speed? That should always be consistent. Although you’d have to do some extra raycasting work to avoid going through walls.

    #14684
    Joseph Tang
    Level 13
    Moderator
    Helpful?
    Up
    0
    ::

    If you mean our Metroidvania series, the series was made a year prior and we weren’t aware of this issue until you pointed it out. [Rather minute detail so thanks for spotting this.] The current method appears to work well enough given the mechanic and so we didn’t think to interpolate it.

    I’ll test out your idea and see what can be done to make it more reliable. I can potentially integrate a fix into the series sometime soon as I have only recently finished updating it at the moment.

    #14685
    Joshua
    Level 2
    Participant
    Helpful?
    Up
    0
    ::

    The guide is great by the way, didn’t mean to be overly critical. I’m just curious. Please let me know how it goes!

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

Go to Login Page →


Advertisement below: