SpoocyCrep
SpoocyCrep

Reputation: 614

Moving around GameObject

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): enter image description here

Edit:
Image of the mob:
enter image description here

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;

Terrain Image: enter image description here

Upvotes: 1

Views: 143

Answers (1)

Programmer
Programmer

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

Related Questions