Unity - 防止游戏对象撞到其他游戏对象

时间:2015-02-22 08:11:24

标签: c# unity3d

我在Unity中做了简单的Patrol NPC,一切正常,NPC有自己的速度(NPC可以移动到终点并停一会儿,然后回去开始和停止一段时间,这将持续发生),我也让玩家可以在x轴上水平移动(键盘中的a,d),在z轴上移动垂直(键盘中的w,s),玩家可以自己移动速度。然而,当我运行游戏并开始向NPC靠拢时,玩家和NPC将相互撞击,导致NPC位置发生变化。

以下是视频:

Video Link

以下是NPC和播放器中组件的图像:

NPC

NPC Components

播放器

Player Components

我试图通过冻结所有位置和旋转来改变NPC组件的RigidBody中的约束,问题解决了。但是当玩家站在NPC面前时,NPC就会通过玩家,就像触发玩家的对手一样。

以下是我正在使用的代码:

NPC脚本

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);
    }
}

玩家脚本

[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;
        }
    }
}

我该如何解决这个问题?

非常感谢任何帮助!

非常感谢你!

1 个答案:

答案 0 :(得分:0)

我怀疑transform.Translate绕过了碰撞检测。我建议你删除NPC上的Rigidbody并给你的NPC CharacterController。要移动NPC,请致电characterController.Move。角色控制器自动检测碰撞。

你不需要Rigidbody,因为你的NPC的位置不会被物理引擎自动更新,但非刚体和刚体之间的碰撞检测仍然适用(Rigidbody会自动碰撞,但你的NPC没有#39; t move)。 如果您希望您的NPC部分受物理控制,您可以尝试isKinematic

如果您想停止碰撞,可以尝试OnCollisionEnter/OnCollisionStay/OnCollisionExit个事件,或者在调用Move方法时可以使用CollisionFlags

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

我怀疑在发生碰撞时停止移动的微妙错误。另一个解决方案是进行航向校正运动:如果NPC检测到它偏离了第一点&#34;到&#34;第二点&#34;然后应用运动以保持正常。它涉及一些矢量数学。

这是我的代码:

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);

}

另见: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