C# 统一-防止游戏对象碰撞到其他游戏对象

C# 统一-防止游戏对象碰撞到其他游戏对象,c#,unity3d,C#,Unity3d,我在Unity中制作了简单的巡逻NPC,一切正常,NPC有自己的速度(NPC可以移动到终点并停止一段时间,然后返回开始和停止一段时间,这将持续发生),我还使玩家可以在x轴水平移动(键盘中的a,d)和垂直移动(键盘中的w,s)在z轴上,玩家有自己的速度。但是,当我运行游戏并开始靠近NPC时,玩家和NPC会相互碰撞,导致NPC位置发生变化 以下是它的视频: 以下是NPC和Player中组件的图像: NPC: public class NPCManager : MonoBehaviour {

我在Unity中制作了简单的巡逻NPC,一切正常,NPC有自己的速度(NPC可以移动到终点并停止一段时间,然后返回开始和停止一段时间,这将持续发生),我还使玩家可以在x轴水平移动(键盘中的a,d)和垂直移动(键盘中的w,s)在z轴上,玩家有自己的速度。但是,当我运行游戏并开始靠近NPC时,玩家和NPC会相互碰撞,导致NPC位置发生变化

以下是它的视频:

以下是NPC和Player中组件的图像:

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

玩家

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

我试图通过冻结所有位置和旋转来改变NPC组件刚体中的约束,问题解决了。但当玩家站在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;
        }
    }
}
公共类NPCManager:MonoBehavior
{
私人玩家管理员(PlayerManager);;
private bool moveForward=false;
私人浮动移动速度=1.5f;
私人空间
{
_playerManager=GameObject.Find(“Player”).GetComponent();
}
私有void更新()
{
如果(向前移动)
{
transform.Translate(Vector3.forward*movementSpeed*Time.deltaTime);
}
其他的
{
start例程(Hold());
}
}
私有void OnGUI()
{
if(_playermanger.isOnChat)
{
GUI.Box(新的Rect(Screen.width/2,Screen.height/2250100),“Test.”);
}
}
专用空对撞机(对撞机列)
{
如果(col.gameObject.name==“第一点”)
{
向前移动=真;
}
else if(col.gameObject.name==“第二点”)
{
向前移动=错误;
}
}
私有IEnumerator Hold()
{
收益率返回新的WaitForSeconds(2.0f);
transform.Translate(-Vector3.forward*movementSpeed*Time.deltaTime);
}
}
玩家脚本

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;
        }
    }
}
[RequireComponent(typeof(CharacterController))]
公共类玩家管理者:单一行为
{
专用字符控制器;
专用矢量3移动方向=矢量3.0;
私人浮子重力=20.0f,速度=5.0f;
公共bool isOnChat=false;
私人空间
{
控制器=GetComponent();
}
私有void更新()
{
if(controller.isground)
{
gameObject.renderer.enabled=true;
moveDirection=新矢量3(Input.GetAxis(“水平”),0,Input.GetAxis(“垂直”);
moveDirection=transform.TransformDirection(moveDirection);
移动方向*=速度;
}
moveDirection.y-=重力*时间增量;
控制器移动(移动方向*时间增量);
}
专用空对撞机(对撞机列)
{
如果(col.gameObject.name==“NPC追随者”)
{
isOnChat=真;
}
}
私有void OnTriggerExit(对撞机列)
{
如果(col.gameObject.name==“NPC追随者”)
{
isOnChat=假;
}
}
}
我怎样才能解决这个问题

任何帮助都将不胜感激


非常感谢你

我怀疑
transform.Translate
绕过了碰撞检测。我建议您删除NPC上的刚体,并给您的NPC一个
CharacterController
。要移动NPC,请调用
characterController.move
。角色控制器自动检测碰撞

您不需要刚体,因为物理引擎不会自动更新NPC的位置,但非刚体和刚体之间的碰撞检测仍然适用(刚体会自动碰撞,但NPC不会移动)。 如果你想让你的NPC部分受物理控制,你可以试试
iskinetic

如果要在发生碰撞时停止移动,可以尝试
OnCollisionCenter/OnCollisionStay/OnCollisionExit
事件,或者在调用移动方法时使用
CollisionFlags

    if ((characterController.Move(...) & CollisionFlags.Sides) != CollisionFlags.None) {
        Debug.Log ("Collision sides, stop moving");
    }
我怀疑当发生碰撞时,会有细微的虫子停止移动。另一个解决方案是进行航向修正运动:如果NPC检测到它偏离了从“第一点”到“第二点”的直线,则应用运动保持航向。它涉及一些向量数学

这是我的密码:

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

}
private CharacterController CharacterController;
私人游戏对象第一点,第二点;
私人空间{
characterController=gameObject.GetComponent();
_playerManager=GameObject.Find(“Player”).GetComponent();
firstPoint=GameObject.Find(“第一点”);
secondPoint=GameObject.Find(“第二点”);
}
私有void更新(){
//从第一点到第二点的线
Vector3线=secondPoint.transform.position-firstPoint.transform.position;
Vector3 movement=-line.normalized*方向*移动速度*时间.deltaTime;
Vector3 v=transform.position-firstPoint.transform.position;
Vector3 perp=v-Vector3.项目(v,线);
移动-=20f*每小时*时间。延迟时间;//航向修正移动
characterController.Move(移动);
}
另见:

你能制作一个网络播放器吗?你可以把它放在Dropbox上。当然,这是.Unity3D文件和Web播放器:[Web播放器]()[.Unity3D文件](),似乎你需要发送Web播放器的zip文件。在Dropbox上托管html过去是可行的,但最近不行了。我找到了另一个解决方案,它可以应用移动来保持NPC的正常运行,即使第一和第二个点在对角线上,它也可以工作。请参阅我的编辑。(StackOverflow不允许长时间讨论评论)嗨,我