我在Unity中做了简单的Patrol NPC,一切正常,NPC有自己的速度(NPC可以移动到终点并停一会儿,然后回去开始和停止一段时间,这将持续发生),我也让玩家可以在x轴上水平移动(键盘中的a,d),在z轴上移动垂直(键盘中的w,s),玩家可以自己移动速度。然而,当我运行游戏并开始向NPC靠拢时,玩家和NPC将相互撞击,导致NPC位置发生变化。
以下是视频:
以下是NPC和播放器中组件的图像:
NPC :
播放器:
我试图通过冻结所有位置和旋转来改变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;
}
}
}
我该如何解决这个问题?
非常感谢任何帮助!
非常感谢你!
答案 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