Unity中如何让待放置GameObject与已放置对象产生碰撞?
解决方案
1. 分阶段控制Collider与碰撞检测
- 预览阶段:保持待放置对象的Box Collider禁用,避免射线检测时打到自身导致位置偏移。如果需要提前检测是否与已放置对象重叠,可以给对象额外添加一个勾选Is Trigger的Collider(比如独立的Box Collider组件),用
OnTriggerEnter/Stay判断重叠状态,提示用户是否可放置。 - 放置确认阶段(比如点击鼠标左键):
- 禁用触发Collider(如果使用了的话)
- 启用原本的Box Collider
- 若需要物理交互,添加Rigidbody并设置参数:
- 勾选
Is Kinematic(避免物理引擎自动推动对象,解决上浮问题) - 根据需求选择是否关闭
Use Gravity
- 勾选
2. 优化射线检测,排除自身对象
如果不想额外加触发Collider,可以通过层掩码让射线忽略待放置对象,这样就能在预览时激活Box Collider:
- 给待放置对象单独创建一个层(比如
PlaceablePreview) - 修改射线检测逻辑,排除该层:
private LayerMask previewLayerMask; private void Start() { // 获取预览层的掩码并取反,让射线检测时忽略该层 previewLayerMask = ~LayerMask.GetMask("PlaceablePreview"); } private void MoveCurrentPlaceableHouseToMouse() { Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hitInfo; // 传入层掩码,确保射线只检测地面和已放置对象 if (Physics.Raycast(ray, out hitInfo, Mathf.Infinity, previewLayerMask)) { currentPlaceableHouse.transform.position = hitInfo.point; currentPlaceableHouse.transform.rotation = Quaternion.FromToRotation(Vector3.up, hitInfo.normal); } }
3. 放置完成后的碰撞生效处理
添加放置确认的逻辑,确保碰撞组件正确激活:
private void Update() { if (Input.GetMouseButtonDown(0) && currentPlaceableHouse != null) { // 启用Box Collider BoxCollider collider = currentPlaceableHouse.GetComponent<BoxCollider>(); if (collider != null) collider.enabled = true; // 添加并配置Rigidbody(按需选择) Rigidbody rb = currentPlaceableHouse.GetComponent<Rigidbody>(); if (rb == null) rb = currentPlaceableHouse.AddComponent<Rigidbody>(); rb.isKinematic = true; // 静态碰撞设为true,需要物理交互设为false rb.useGravity = false; // 静态物体可关闭重力 rb.freezeRotation = true; // 防止不必要的旋转 // 完成放置,清空当前对象 currentPlaceableHouse = null; } }
如果仅需要静态碰撞(不需要物理交互),无需添加Rigidbody,只要确保Collider启用并勾选对象的Static选项即可。
4. 解决Rigidbody上浮问题
之前添加无重力Rigidbody后上浮,本质是对象Collider与地面/已放置对象的Collider重叠,物理引擎为分离碰撞体自动推动对象。解决方式:
- 预览阶段用触发Collider检测重叠,禁止在重叠位置放置
- 给Rigidbody设置
Is Kinematic = true,让物理引擎不控制对象移动,但仍保留碰撞检测能力
内容的提问来源于stack exchange,提问作者unityfan
相关产品推荐
相关产品推荐

