So I’ve been trying to set up a basic player controller using a square sprite. I understand where I’m making the problem, but I don’t know how to fix it. I feel like it’s an issue with combining Rigidbody2D.MovePosition() for Move() and Rigidbody2D.velocity() for jump. Each function in a vacuum works perfectly for what I want, but when put together, the jump input seems to either get eaten or buffer for like 2 seconds and then the player sprite gets teleported up a few units. Any recommendations on how to fix it? I don’t like the sudden jolt of velocity I get from altering velocity for horizontal movement.
Here’s an example of what’s happening.
Here’s my entire Movement script for reference. It’s pretty small at the moment.
namespace Platformer.Player
{
public class Movement : MonoBehaviour
{
[SerializeField, Range(0f, 1f)] float moveSpeed = 1f;
[SerializeField, Range(2f, 150f)] float baseSpeedMultiplier = 5f;
[SerializeField, Range(1f, 100f)] float jumpVelocity = 1f;
[SerializeField] Rigidbody2D rigidBody = null;
void Awake()
{
if (GetComponent<Rigidbody2D>())
{ rigidBody = GetComponent<Rigidbody2D>(); }
else { Debug.LogError("No Rigidbody2D attached to " + this.name); }
}
void Update()
{
HandleMovement();
}
private void HandleMovement()
{
Move();
Jump();
}
private void Move()
{
float horizontalAxis = Input.GetAxis("Horizontal");
Vector2 startingPos = rigidBody.position;
Vector2 newPos = startingPos + new Vector2(horizontalAxis * Time.deltaTime * moveSpeed * baseSpeedMultiplier, 0f);
rigidBody.MovePosition(newPos);
}
private void Jump()
{
if (Input.GetButtonDown("Jump"))
{
rigidBody.velocity += Vector2.up * jumpVelocity;
}
}
}
}
As an update, I’ve temporarily fixed the inability to move by assigning newPos’s value to rigidBody.position. This however causes really bad catching and jittering on walls when walking into them, which is unacceptable in a game where I want to put in wall jumps and climbing.
You should step back and look at what things like MovePosition and Velocity actually do. Let’s ignore the fact that physics doesn’t run per-frame yet you’re manipulating physics per-frame. Physics runs per fixed-update by default so unless you’re manually running physics per-frame then you’ll potentially have many render frames per simulation step.
You tell the body to move to a specific position per-frame but that’ll only be used when the simulation runs so only the last one you did will do anything. Because whenever the physic system runs it doesn’t use its velocity because you’re permanently telling it to move to a specific position and ignore that stuff yet at the same time you’re manipulating velocity in the hope it jumps.
MovePosition/MoveRotation are typicaly done with Kinematic bodies although in 2D they work with Dynamic bodies but if you’re doing it continuously then it won’t have a chance to do anything else.
Choose a single way you want your bodies to move and stick to it. Modify its velocity, add forces or stick to MovePosition/MoveRotation. If you are setting the body position/rotation directly via those properties then they too will always move there but instantly and this will mean you’re just instantly teleporting from one position to another.
Physics is designed to move bodies via their velocity. MovePosition/MoveRotation do this and work with interpolation however if you use this continuously then that’s the ONLY way you should move stuff. If you manipulate velocity then ONLY do that via directly setting velocity or adding forces or impulses. Certainly never change the Transform and avoid setting the body pose directly.
1 Like
I appreciate the lengthy and thorough response. The long and short of it is, if I’m understanding correctly, that I should keep my bodies moving in one singular way and that the best way is likely velocity rather than MovePosition, as MovePosition is clunkier with Dynamic, player-controlled bodies.
It’s not “clunkier” or has any issue whatsoever, it’s simply that you’re doing multiple conflicting things i.e. continually move to specific positions but at the same time, set velocity to try to get it to move against the positions you’re specifying.