Reputation: 614
I'm trying to create MOB AI using rigidbody. I want to make the mob (GameObject) walk around the world using
mobrigid.AddForce((((goal - transform.position).normalized)*speed * Time.deltaTime));
(goal is a random place around mob).
here is where it gets complicated, some mobs fly up in the air at extreme speeds while others move normaly at slow speed. (And yes, I do make sure the goal.Y is a place on the ground and not air). I tried fixing it by changing the drag, but that leads to mobs walking on air and not falling with gravity.
I'm really lost, can't figure out how do I simply move a gameobject around with rigidbody without getting this odd behavior.
Logs of mobs (with Y of goal changed to 0):
my movement logic:
case MOBTYPE.EARTHMOB:
switch (currentstatus)
{
case MOBSTATUS.STANDING:
if (mobrigid.IsSleeping())
{
mobrigid.WakeUp();
}
goal = this.transform.position;
goal.x = Random.Range(goal.x - 150, goal.x + 150);
goal.z = Random.Range(goal.z -150, goal.z + 150);
goal.y = 0;
currentstatus = MOBSTATUS.WALKING;
// Debug.Log("Transform:"+this.transform.position+ "Goal:" + goal+ "goal-transform:" + (goal - transform.position));
break;
case MOBSTATUS.WALKING:
if (Random.Range(1, 100) == 5)
{
currentstatus = MOBSTATUS.STANDING;
}
if (mobrigid.IsSleeping())
{
mobrigid.WakeUp();
}
mobrigid.AddForce((((goal - transform.position).normalized) * 10000 * Time.deltaTime));
// transform.LookAt(goal);
var distance = Vector3.Distance(goal, gameObject.transform.position);
if (distance <=5)
{
currentstatus = MOBSTATUS.STANDING;
}
break;
}
break;
Upvotes: 1
Views: 143
Reputation: 125305
The Rigidbody.AddForce
function is used to add force to an Object along a direction. Since you have a position you need to move a Rigidbody
to, you have to use the Rigidbody.MovePosition
function. You may also want to mark the Rigidbody as kinematic.
A simple coroutine function to move a Rigidbody object to specific position:
IEnumerator MoveRigidbody(Rigidbody rb, Vector3 destination, float speed = 50f)
{
const float destThreshold = 0.4f;
while (true)
{
Vector3 direction = (destination - rb.position).normalized;
rb.MovePosition(rb.position + direction * speed * Time.deltaTime);
float dist = Vector3.Distance(rb.position, destination);
//Exit function if we are very close to the destination
if (dist <= destThreshold)
yield break;
yield return null;
//yield return new WaitForFixedUpdate();
}
}
It better to call this from another coorutine funtion so that you can yield or wait for it to finish then do other task like generating the random postion again and moving the Rigidbody there.
You want to generate new postion then move the Rigidbody
there, this is an example of how to call the function above:
IEnumerator StartMoveMent()
{
Rigidbody targetRb = GetComponent<Rigidbody>();
while (true)
{
//Generate random position
Vector3 destination = new Vector3();
destination.y = 0;
destination.x = UnityEngine.Random.Range(0, 50);
destination.z = UnityEngine.Random.Range(0, 50);
//Move and wait until the movement is done
yield return StartCoroutine(MoveRigidbody(targetRb, destination, 30f));
}
}
And to start the StartMoveMent
function:
void Start()
{
StartCoroutine(StartMoveMent());
}
While what I said above should work, I do recommend you use Unity's built in pathfinding system. Here is a tutorial for that. It simplifies finding paths to follow towards a destination with NavMesh
which can also be baked during run-time
.
Upvotes: 1