Hi, thanks for the tips.
Actually what I want is to make my 2d character (this is why I use Vector2 instead of Vector3) moving from its position to a specific point (in the game, it’s when the player finds a cover and presses the button to make the toon getting behind the cover). And actually yes, I do not want other forces to interfere with this movement, since it will be a very short movement and I’ll already take care that it can be done only in specific circumstances.
I’ve found a way to achieve this with a kinematic rigidbody using the function rigidbody2d.MovePosition(targetposition) within a coroutine:
[SerializeField] Transform destination;
[SerializeField] float moveTime = 0.1f;
private Rigidbody2D rb;
private float inverseMoveTime;
private void Start()
{
rb = GetComponent<Rigidbody2D>();
inverseMoveTime = 1f / moveTime;
Move(destination.position.x, destination.position.y);
}
public void Move(float xDir, float yDir)
{
Vector2 start = rb.velocity;
Vector2 end = start + new Vector2(xDir, yDir);
StartCoroutine(SmoothMovement(end));
}
public IEnumerator SmoothMovement(Vector3 end)
{
float sqrRemainingDistance = (transform.position - end).sqrMagnitude;
while (sqrRemainingDistance > float.Epsilon) // While that distance is greater than a very small amount (Epsilon, almost zero):
{
Vector3 newPosition = Vector3.MoveTowards(rb.position, end, inverseMoveTime * Time.deltaTime); // Find a new position proportionally closer to the end, based on the moveTime
rb.MovePosition(new Vector3(newPosition.x, newPosition.y));
sqrRemainingDistance = (transform.position - end).sqrMagnitude; // Recalculate the remaining distance after moving.
yield return null; // Return and loop until sqrRemainingDistance is close enough to zero to end the function
}
rb.MovePosition(end);
}
The problem is that this code gives strange results when the rigidbody is set to dynamic, which is the case of the character of my videogame, and it’s confirmed by the Unity’s documentation, which says that MovePosition() works only with kinematic rigidbodies. So, as you were suggesting, I’ve tried to add a Vector2 (instead of a Vector3, since I’m in a 2D environement) each loop of the coroutine, with this code:
[SerializeField] Transform destination;
[SerializeField] float moveTime;
private Rigidbody2D rb;
private float inverseMoveTime;
private void Start()
{
rb = GetComponent<Rigidbody2D>();
inverseMoveTime = 1f / moveTime;
Move(destination.position.x, destination.position.y);
}
public void Move(float xDir, float yDir)
{
Vector2 startVelocity = rb.velocity;
Vector2 end = startVelocity + new Vector2(xDir, yDir);
StartCoroutine(SmoothMovement(end));
}
public IEnumerator SmoothMovement(Vector3 end)
{
float sqrRemainingDistance = (transform.position - end).sqrMagnitude;
while (sqrRemainingDistance > float.Epsilon) // While that distance is greater than a very small amount (Epsilon, almost zero):
{
Vector2 newPosition = Vector2.MoveTowards(rb.position, end, inverseMoveTime * Time.deltaTime); // Find a new position proportionally closer to the end, based on the moveTime
rb.AddForce(new Vector3(newPosition.x, newPosition.y), ForceMode2D.Force);
sqrRemainingDistance = (transform.position - end).sqrMagnitude; // Recalculate the remaining distance after moving.
yield return null; // Return and loop until sqrRemainingDistance is close enough to zero to end the function
}
rb.MovePosition(end);
}
which is very similar to the first one, changing the way the character moves within the coroutine. The thing is that results are pretty weird
- The character moves exactly AWAY from the target destination
- Adding each frame a force makes the character literally flying away each frame faster (I think I can easily solve this)
Basically my problem now is: how can I calculate the Vector2 to use withing the function AddForce(Vector2, ForceMode2D.Force), so that it simply leads my character towards the destination and then the character stops when the destination is reached? Moreover, it should reach the destination at a constant speed, instead of keeping accelerating (but as I was saying above, I think I can solve this easily).
Thanks again for the patience and for the next answer