Unity 3D FPS视角下物体放置防嵌入的计算方法求助
解决Unity物体放置嵌入问题的方法
问题核心是你把物体的轴心点直接放在了射线碰撞点上,导致物体下半部分嵌入到被碰撞的物体里。要让物体刚好贴在表面,得沿着碰撞面的法线方向,把物体往法线方向偏移一段距离——这段距离是物体底部到自身轴心的距离。
具体步骤
- 获取物体的包围盒信息:用
Renderer.bounds或Collider.bounds拿到物体的局部空间包围盒,以此算出轴心到物体底部的距离。 - 计算偏移量:如果物体轴心在中心,偏移量就是包围盒的半高;如果轴心不在中心,用
-bounds.min.y更准确(bounds.min.y是局部空间里包围盒的最低点y值,取反就是轴心到最低点的距离)。 - 应用偏移到位置:把碰撞点
hit.point加上hit.normal * 偏移量,就是物体的正确放置位置。
修改后的代码
首先在类里加个变量缓存包围盒:
private Bounds placeableBounds;
然后修改HandeNewObjectHotkey方法,实例化时获取包围盒:
private void HandeNewObjectHotkey() { if (Input.GetKeyDown(newObjectHotkey)) { if(currentPlaceableObject == null) { currentPlaceableObject = Instantiate(placeableObjectPrefab); // 用Renderer的包围盒(如果依赖碰撞体判断就用GetComponent<Collider>().bounds) placeableBounds = currentPlaceableObject.GetComponent<Renderer>().bounds; } else { Destroy(currentPlaceableObject); currentPlaceableObject = null; // 置空避免后续空引用 } } }
最后修改MovePlaceableObject里的位置计算:
private void MovePlaceableObject() { if (currentPlaceableObject == null) return; // 没有物体时直接返回 Ray ray = new Ray(Camera.main.transform.position, Camera.main.transform.forward); Debug.DrawRay(ray.origin, ray.direction * 20f); RaycastHit hit; if(Physics.Raycast(ray, out hit, 15f)) { // 计算轴心到物体底部的距离 float offset = -placeableBounds.min.y; // 沿着碰撞法线方向偏移,得到贴合表面的位置 Vector3 newPosition = hit.point + hit.normal * offset; currentPlaceableObject.transform.position = newPosition; currentPlaceableObject.transform.rotation = Quaternion.FromToRotation(Vector3.up, hit.normal); } }
补充说明
- 之前直接加x/y/z尺寸没用,是因为碰撞面不一定是水平的,必须沿着碰撞面的法线方向偏移,而非固定的竖直方向。
- 如果物体有多个子物体,用
GetComponentInChildren<Renderer>().bounds获取整体包围盒。 - 如果物体支持缩放,要在缩放后重新计算包围盒,或者每次射线检测时重新获取。
内容的提问来源于stack exchange,提问作者gabe
相关产品推荐
相关产品推荐

