0
\$\begingroup\$

I have two behaviors on my player. "Walk" and "Dodge". Individually they work as intended by altering the players Rigidbody.velocity. However trying to dodge while holding left or right will trigger "Dodge" then "Walk" will over ride the change since you're holding left or right.

"Walk Script" within the update loop If you press left or right

_body2D.velocity = new Vector2(speed * direction, _body2D.velocity.y);

"Dodge Script" within the update loop If you press the dodge input it will move the player the opposite direction their facing.

_body2D.velocity = new Vector2( - (speed * direction), _body2D.velocity.y);

if you hold left or right while pressing the dodge input it will dodge in the direction you're pressing.

_body2D.velocity = new Vector2(speed * direction, _body2D.velocity.y);

I've tried changing the script execution order to prioritize the Dodge behavior over Walk. I've tried disabling the walk script during the animation with the following method.

ToggleScripts(!_animator.IsInTransition(0));

protected void ToggleScripts(bool value)
{
    foreach (var script in disabledScripts)
        script.enabled = value;
}
\$\endgroup\$
  • 2
    \$\begingroup\$ Why not += to the velocity instead of completely changing it? \$\endgroup\$ – Bálint Aug 7 '18 at 18:09
  • 2
    \$\begingroup\$ Yeah you want to be using += to add on to your current velocity not setting it equal to a new value each time. \$\endgroup\$ – Pheonix2105 Aug 7 '18 at 18:20
  • \$\begingroup\$ you'd need to set some sort of clamp so the value doesn't grow exponentially thought wouldn't you? What if the Dodge velocity needs to exceed the amount that is clamped on the walk speed? \$\endgroup\$ – Pyreal Aug 7 '18 at 18:22
  • 1
    \$\begingroup\$ You are correct yes, you'd need to clamp the value. If the value exceeded the clamp it would just be set to maximum value, and it doesn't always 'grow' as such, sometimes you might be applying a velocity opposite to your current one effectively slowing you down, Velocity is the speed of something in a particular direction \$\endgroup\$ – Pheonix2105 Aug 7 '18 at 18:31
2
\$\begingroup\$

The Rigidbody.velocity's documentation in Unity specifically does not recommend that you modify the velocity vector, since you may override previous acceleration forces applied. Back then, since I didn't understand how Rigidbodies worked, I had different approaches:

  • An approach where I had a VelocityAccumulator component class, where I applied all the accelerations vectors desired to be applied at the end of each frame.
  • Have a vector that stores all the applied accelerations and apply it to the velocity at the end of frame.

Example of the approach 1:

[RequireComponent(typeof(Rigidbody))]
public class VelocityAccumulator : MonoBehaviour
{
    private Rigidbody rigidbody;
    private Vector3 velocity;

    void Awake()
    {
        rigidbody = GetComponent<Rigidbody>();
    }

    void FixedUpdate()
    {
        if(rigidbody.useGravity) velocity += Physics.gravity;
        rigidbody.velocity = velocity;
        velocity = Vector3.zero;
    }

    public void AddAcceleration(Vector3 acceleration)
    {
        velocity += acceleration;
    }
}

Example of approach 2:

public class Example : MonoBehaviour
{
    Vector3 currentVelocity, jumpForce, movementForce;
    bool walk, jump;

    void Update()
    {
        if(jump) currentVelocity += jumpForce;
        if(walk) currentVelocity += movementForce;
        GetComponent<Rigidbody>().velocity = currentVelocity;
        currentVelocity = Vector3.zero;
    }
}

Which, turns out that at the end, the best solution is to use Rigidbody.AddForce, which does the same thing, and its already built-in. Just take note that the movement will be relative to the mass, so you'll have to either tweak the mass or multiply the force by the mass.

Hope it helps.

\$\endgroup\$
  • 1
    \$\begingroup\$ so this seems to work pretty well, it is a bit more floaty than my previous movement but i'll work out the kinks. I added a Vector2.ClampMagnitude(); with maxWalkSpeed and maxDodgeForce. \$\endgroup\$ – Pyreal Aug 7 '18 at 18:37
  • \$\begingroup\$ As a side note, I forgot to mention that Rigidbody.AddForce takes an optional ForceMode (ForceMode.Force by default) enum, each one treats the force differently, you could use a certain ForceMode to ignore the mass (like ForceMode.Acceleration or ForceMode.VelocityChange). Be sure to check the ForceMode documentation: docs.unity3d.com/ScriptReference/ForceMode.html \$\endgroup\$ – LinkWindcrafter Aug 7 '18 at 19:16
  • \$\begingroup\$ I want my movement to be at a set speed always from start to stop so it's very precise, one side effect of adding force seems to be the acceleration. I'm playing around with the Forcemodes but 2d Seems to only have Force or Impulse. \$\endgroup\$ – Pyreal Aug 7 '18 at 19:26
1
\$\begingroup\$

Best way i can think of doing it would be to have the "Walk" and "Dodge" scrips be one "Movement" scrip.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Movement : MonoBehaviour {

public bool is_Dodgeing = false;

// Update is called once per frame
void Update () {
    if(Input.GetButtonDown("Walk") && !is_Dodgeing)
    {
        //Walk code
    }

    if(Input.GetButtonDown("Dodge"))
    {
        is_Dodgeing = true;
        //Dodge code
        //Make sure to set is_Dodgeing to false when done with Dodge code
    }
  }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.