When using rigidbody2D.MovePosition along with the mouse delta input, the object moves around incorrectly, unpredictably, and jittery.
I'm trying to make a game where you are a cursor and have to progress through puzzle levels, but I am having trouble with the movement. I'm using the new input system. The movement was fine when making the custom cursor position set to the mouse position and making the custom cursor move according to the mouse delta. However, this wouldn't work with collision, because the cursor would just travel over walls and such. I tried to use rigidbody.MovePosition, which should achieve the same thing but it produced a weird movement that wasn't smooth at all and didn't go to where I wanted it to go. Just setting the velocity of the rigidbody didn't work either and produced similar results. I've tried altering settings on the rigidbody, but nothing seems to work. I've also put the code I use to move the cursor inside FixedUpdate, but that didn't fix it either. I'm using Unity 2020.3.26f1 if you need it.
Here's the full script, the only line that should matter I have commented.
using UnityEngine;
using UnityEngine.InputSystem;
public class CursorScript : MonoBehaviour
{
#region Input
private PlayerInput playerInput;
private InputAction mousePosition;
private InputAction deltaMousePosition;
private InputAction click;
private void Awake()
{
playerInput = GetComponent<PlayerInput>();
mousePosition = playerInput.actions["MousePosition"];
click = playerInput.actions["Click"];
deltaMousePosition = playerInput.actions["MouseDelta"];
}
#endregion
public Camera cam;
public float sensitivity;
public SpriteRenderer spriteRenderer;
public Sprite[] sprites;
void Start()
{
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
void Update()
{
Vector2 realMousePosition = cam.ScreenToWorldPoint(mousePosition.ReadValue<Vector2>());
//Here's the code that moves the cursor
GetComponent<Rigidbody2D>().MovePosition(new Vector2(transform.position.x, transform.position.y) + deltaMousePosition.ReadValue<Vector2>() * sensitivity);
spriteRenderer.sprite = sprites[0];
if (click.ReadValue<float>() == 1)
spriteRenderer.sprite = sprites[1];
}
}
Here's a video that shows the movement I'm experiencing better (The low frames make it hard to notice but you might be able to see it): https://youtu.be/2lj1KntAZKU
You can start by going to the Project Settings -> Physics -> Simulate on Update (instead of FixedUpdate). It makes physics simulations run every update instead of every fixed update.
If that doesn't work, you can troubleshoot by adding a Vector2 variable such as PreviousPosition
to the class. You can also add a Rigidbody2D variable rb
and cache the Rigidbody2D
component within Start()
rb = GetComponent<Rigidbody2D>();
At the end of Update()
, use previousPosition = realMousePosition;
. At the beginning of Update()
, you can use the difference between the vectors to move the Rigidbody,
void Update()
{
Vector2 realMousePosition =
cam.ScreenToWorldPoint(mousePosition.ReadValue<Vector2>());
//Here's the code that moves the cursor
rb.MovePosition(rb.position + (realMousePosition - previousPosition) * sensitivity);
// You could probably write something better, but my idea here is to not have to assign the sprite every frame.
spriteRenderer.sprite = sprites[0];
if (click.ReadValue<float>() == 1 && spriteRenderer.sprite != sprites[1])
spriteRenderer.sprite = sprites[1];
else if (spriteRenderer.sprite != sprites[0])
spriteRenderer.sprite = sprites[0];
previousPosition = realMousePosition;
// You can also try this:
// previousPosition = rb.position;
}