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