How to use Rigidbody2D.MovePosition to move a kinematic object around looping waypoints?
Hello, I'm trying to make a gameObject move around a fixed set of waypoints continuously. I'm using Rigidbody2D.MovePosition to move the gameobject around the waypoints which works. But the object slows down when approaching a waypoint and stops for about 1 second and then starts to move to the next waypoint and it stops and this continues for all the waypoints. I tried to use AddForce to move the object but it doesn't move at all.
void walk(){
rb2d = GetComponent<Rigidbody2D>();
// move towards the next waypoint
Vector2 dir = (targetWayPoint.position - transform.position); //This gives me the direction of the next waypoint
//i tried using AddForce and the object didn't move at all.
//rb2d.AddForce(dir * speed * Time.deltaTime);
rb2d.MovePosition(new Vector2(transform.position.x,transform.position.y) + dir * speed / 5 * Time.fixedDeltaTime);
//I also tried:
//rb2d.MovePosition(new Vector2(transform.position.x,transform.position.y) + dir * speed / 5);
//and also:
//rb2d.MovePosition(new Vector2(transform.position.x,transform.position.y) + dir * Time.fixedDeltaTime);
if(transform.position == targetWayPoint.position) //if it reaches the waypoint
{
currentWayPoint ++ ;
targetWayPoint = wayPointList[currentWayPoint];
Debug.Log("Added the next waypoint(" + currentWayPoint + "). Object: " + gameObject.name);
}
if (currentWayPoint == wayPointList.Length-1) currentWayPoint = -1; //keep going around the waypoints
}
If this kind of question was already answered please post the link. I couldn't find any question solving my problem.
Answer by OncaLupe · Jan 03, 2016 at 07:37 PM
Two things I see that are causing this:
You're aren't normalizing the 'dir' vector you get, so the closer to the target, the slower the speed.
You're testing equality to see if you reached the target, which is discouraged due to floats/vectors rarely being exactly equal.
Also, you should be storing the reference to the rigidbody instead of getting it every frame. GetComponent is a slow operation.
using UnityEngine;
using System.Collections;
public class WaypointMover : MonoBehaviour
{
Rigidbody2D rb2d;
public Transform[] wayPointList;
Transform targetWayPoint;
public float speed = 5f;
int currentWayPoint = 0;
public float arrivalDistance = 0.1f;
float lastDistanceToTarget = 0f;
void Awake()
{
//Store reference so it's not run every frame
rb2d = GetComponent<Rigidbody2D>();
//Get first waypoint
targetWayPoint = wayPointList[currentWayPoint];
lastDistanceToTarget = Vector3.Distance(transform.position, targetWayPoint.position);
}
void FixedUpdate()
{
walk();
}
void walk()
{
//If we're close to target, or overshot it, get next waypoint;
float distanceToTarget = Vector3.Distance(transform.position, targetWayPoint.position);
if((distanceToTarget < arrivalDistance) || (distanceToTarget > lastDistanceToTarget))
{
currentWayPoint++;
if(currentWayPoint >= wayPointList.Length)
currentWayPoint = 0;
targetWayPoint = wayPointList[currentWayPoint];
lastDistanceToTarget = Vector3.Distance(transform.position, targetWayPoint.position);
Debug.Log("Added the next waypoint(" + currentWayPoint + "). Object: " + gameObject.name);
}else{
lastDistanceToTarget = distanceToTarget;
}
//Get direction to the waypoint.
//Normalize so it doesn't change with distance.
Vector3 dir = (targetWayPoint.position - transform.position).normalized;
//(speed * Time.fixedDeltaTime) makes the object move by 'speed' units per second, framerate independent
rb2d.MovePosition(transform.position + dir * (speed * Time.fixedDeltaTime));
}
}
The movement is after the distance check, as MovePosition() doesn't take effect until the physics engine step near end of frame. Added an overshoot check so the object doesn't get stuck if arrivalDistance is smaller than movement amount.
Thank you. This actually worked. I used .normalized but it messed it up and i thought i shouldn't use it. Now i actually understand what is does. Thanks again :)