2
\$\begingroup\$

I'm working on my enemy AI scripts and I'm using a rigidbody to have the enemies chase the player when the player gets into its aggro distance.

Two of the main problems I'm having:

  1. When the game starts, all the enemies are floating in the air
  2. Even when the player is outside the enemie's aggro distance, the enemy still chases the player

Code:

using UnityEngine;
using System.Collections;

public class EnemyAI : MonoBehaviour {
    public Transform target;
    public int moveSpeed;
    public int rotationSpeed;
    public int attackSpeed; 
    public int maxDistance;
    public int aggroDistance;

    private Transform myTransform;
    public Rigidbody rb;
    private Vector3 dir;

    void Awake() {
        myTransform = transform;
        rb = GetComponent<Rigidbody>();
    }

    void Start () {
        character = GetComponent<CharacterController>();
        //Find playerS
        GameObject go = GameObject.FindGameObjectWithTag("Player");
        //Set player as target
        target = go.transform;

        maxDistance = 2;
        aggroDistance = 10;
    }

    void Update() {
        dir = target.position - rb.position;
        dir.Normalize();
        transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(dir), rotationSpeed * Time.deltaTime);

        if (Vector3.Distance(target.position, myTransform.position) < aggroDistance) {
            if (Vector3.Distance(target.position, myTransform.position) > maxDistance) {
                rb.MovePosition(transform.position + transform.forward * moveSpeed * Time.deltaTime); 
            }
        }
    }

    void FixedUpdate () {
        rb.AddForce (dir * rotationSpeed);
    }
}

Enemy Properties:
enter image description here

\$\endgroup\$
  • \$\begingroup\$ About the aggro, have you tried to output the console the different values involved in your checks? Then to use a step-by-step debugger to determine why your values are not as you expected? You should also try to add comments your parameters so that we know what they are. It's difficult to know what maxDistance is exactly and what is supposed to do. \$\endgroup\$ – Vaillancourt Jun 6 '15 at 0:35
1
\$\begingroup\$

You are manipulating your GameObject's RigidBody as well as its Transform. This is a no-no.

From the Official Unity Documentation: http://docs.unity3d.com/Manual/class-Rigidbody.html

Rigidbodies allow your GameObjects to act under control of the physics engine. This opens the gateway to realistic collisions, varied types of joints, and other very cool behaviors. Manipulating your GameObjects by adding forces to a Rigidbody creates a very different feel and look than adjusting the Transform Component directly. Generally, you shouldn’t manipulate the Rigidbody and the Transform of the same GameObject - only one or the other.

However, sometimes you will want to have objects within your game world that can react to physics at certain times, just not all the time. For example you may want your enemies to be controlled manually by your script when they are alive, but when they die they could become ragdolls and fall to the floor convincingly.

The way you do this is by using the isKinematic property on the RigidBody. When set to true, your GameObject will not react to physics events, however it can still cause physics events on other objects that have a RigidBody. So you can directly manipulate the Transform of an object marked isKinematic. This property can be manually turned on/off in your scripts.

More info on isKinematic here: http://docs.unity3d.com/ScriptReference/Rigidbody-isKinematic.html


What you need to do:

  • On your Enemy's RigidBody, set isKinematic to true.
  • Manipulate the transform but not the rigidbody.

When you need to, you can make your Enemy react to physics again by doing:

rb.isKinematic = false;

Now you can manipulate the rigidbody but not the transform.

In your code you should change

rb.MovePosition(transform.position + transform.forward * moveSpeed * Time.deltaTime);

to

transform.position = Vector3.MoveTowards(transform.position, target.position, moveSpeed * Time.deltaTime);

and you should remove the code from FixedUpdate().

I hope this helps you solve your problem :)

\$\endgroup\$
0
\$\begingroup\$

Remove the FixedUpdate. Each frame you set "dir" to point towards the player and then apply a force in that direction regardless of the distance, so your rigidbody is always going to move towards the player. And you are already rotating and changing the position of the enemy in Update, so the FixedUpdate isn't needed.

\$\endgroup\$
  • 1
    \$\begingroup\$ He is right by doing physics stuff like forces in fixed update \$\endgroup\$ – Daniel Holst Jun 14 '15 at 12:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.