0
votes

I have made simple Patrol NPC in Unity and everything works fine and NPC has it is own speed (NPC could move to the end point and stop for a while, and goes back to start and stop for a while, this will continuously happen), and I also make the player could move horizontal (a, d in the keyboard) in x axis and vertical (w, s in the keyboard) in z axis and the player has it is own speed. However, when I run the game and starts to move closer to the NPC, the player and NPC will bump into each other, resulting NPC position changes.

Here is the video of it:

Video Link

Here is the image of components in NPC and Player:

NPC:

NPC Components

Player:

Player Components

I have tried to change the constraints in the RigidBody of the NPC components by freeze all position and rotation, the problem solved. But when the Player stand in front of the NPC, the NPC just go through the Player, like the collider of the Player is triggered.

Here is the code that I am using:

NPC Script:

public class NPCManager : MonoBehaviour 
{
    private PlayerManager _playerManager;

    private bool moveForward = false;

    private float movementSpeed = 1.5f;

    private void Awake()
    {
        _playerManager = GameObject.Find("Player").GetComponent<PlayerManager>();
    }

    private void Update()
    {
        if (moveForward)
        {
            transform.Translate(Vector3.forward * movementSpeed * Time.deltaTime);
        }

        else
        {
            StartCoroutine(Hold());
        }
    }

    private void OnGUI()
    {
        if (_playerManager.isOnChat)
        {
            GUI.Box(new Rect(Screen.width / 2, Screen.height / 2, 250, 100), "Test.");
        }
    }

    private void OnTriggerEnter(Collider col)
    {
        if (col.gameObject.name == "First Point")
        {
            moveForward = true;
        }

        else if (col.gameObject.name == "Second Point")
        {
            moveForward = false;
        }
    }

    private IEnumerator Hold()
    {
        yield return new WaitForSeconds(2.0f);

        transform.Translate(-Vector3.forward * movementSpeed * Time.deltaTime);
    }
}

Player Script:

[RequireComponent(typeof(CharacterController))]
public class PlayerManager : MonoBehaviour 
{
    private CharacterController controller;

    private Vector3 moveDirection = Vector3.zero;

    private float gravity = 20.0f, speed = 5.0f;

    public bool isOnChat = false;

    private void Awake()
    {
        controller = GetComponent<CharacterController>();
    }

    private void Update()
    {
        if (controller.isGrounded)
        {
            gameObject.renderer.enabled = true;

            moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));

            moveDirection = transform.TransformDirection(moveDirection);

            moveDirection *= speed;
        }

        moveDirection.y -= gravity * Time.deltaTime;

        controller.Move(moveDirection * Time.deltaTime);
    }

    private void OnTriggerEnter(Collider col)
    {
        if (col.gameObject.name == "NPC Follower")
        {
            isOnChat = true;
        }
    }

    private void OnTriggerExit(Collider col)
    {
        if (col.gameObject.name == "NPC Follower")
        {
            isOnChat = false;
        }
    }
}

How can I solve this?

Any help will be much appreciated!

Thank you so much!

1
Can you build a Web Player? You can put it on Dropbox.Ming-Tang
Sure, here is the .Unity3D File and Web Player: [Web Player] (dropbox.com/s/atszlwy1kazkb54/Setup.html?dl=0) [.Unity3d File] (dropbox.com/s/xdfh1jgjft32i3z/Setup.unity3d?dl=0)Yunnan
It seems you need to send the zip of the Web player. Hosting html on Dropbox used to work, but it doesn't recently.Ming-Tang
I found another solution that apply movement to keep the NPC on-course, and it works even if First and Second points are on diagonal. See my edit. (StackOverflow doesn't allow long discussions on comments)Ming-Tang

1 Answers

0
votes

I suspect that transform.Translate bypasses collision detection. I suggest you to remove the Rigidbody on the NPC and give your NPC a CharacterController. To move the NPC, call characterController.Move. Character controllers detect collision automatically.

You don't need Rigidbody because your NPC's position is not updated automatically by the physics engine, but collision detection between non-Rigidbodies and Rigidbodies still apply (the Rigidbody get bumped automatically, but your NPC doesn't move). If you want your NPC to be partly under control by physics, you can try isKinematic.

If you want to stop moving on collision, you can try OnCollisionEnter/OnCollisionStay/OnCollisionExit events, or you can use CollisionFlags when calling the Move method:

    if ((characterController.Move(...) & CollisionFlags.Sides) != CollisionFlags.None) {
        Debug.Log ("Collision sides, stop moving");
    }

I suspect subtle bugs for stopping moving when there is a collision. Another solution is to make course correction movements: If the NPC detects it's deviated from the line from "First Point" to "Second Point", then apply movement to stay on course. It involves some vector math.

Here is my code:

private CharacterController characterController;

private GameObject firstPoint, secondPoint;
private void Awake() {
  characterController = gameObject.GetComponent<CharacterController>();
  _playerManager = GameObject.Find("Player").GetComponent<PlayerManager>();
  firstPoint = GameObject.Find("First Point");
  secondPoint = GameObject.Find("Second Point");
}

private void Update() {
  // the line from firstPoint to secondPoint
  Vector3 line = secondPoint.transform.position - firstPoint.transform.position;

  Vector3 movement = -line.normalized * direction * movementSpeed * Time.deltaTime;

  Vector3 v = transform.position - firstPoint.transform.position;
  Vector3 perp = v - Vector3.Project(v, line);

  movement -= 20f * perp * Time.deltaTime; // course correction movement

  characterController.Move(movement);

}

See also: http://answers.unity3d.com/questions/433472/objects-passing-through-collision-because-of-trans.html http://answers.unity3d.com/questions/7671/guidelines-for-using-rigidbody-collider-characterc.html