Unity运行时双击墙创建正交相机并聚焦选中墙的技术问题
问题描述
我有一个包含房间设计的场景和一台正交相机,希望双击特定墙体时,相机缩放并仅显示被选中的墙体(点击绿圈标记的墙后,期望效果如附图所示)。请问如何通过脚本定位相机?我尝试编写了以下MakeCamera函数,传入选中墙体作为targetObject,创建新的正交相机并尝试将其置于墙前看向墙体,但该函数在不同朝向的墙体上均无法正常工作:相机未朝向墙体,且不同方位(左、右、前、后)墙体的相机位置设置错误(例如右侧墙体的相机本该位于墙左侧看向墙体,实际却朝向正前方)。
原代码:
private void MakeCamera(GameObject targetObject, Vector3 normal) { if (targetObject == null) { Debug.LogError("Target object is not assigned."); return; } if(normal == new Vector3(1,0,0)) { Debug.Log("right"); //right } else if(normal == new Vector3(-1, 0, 0)) { Debug.Log("Left"); //left } else if(normal == new Vector3(0,0,-1)) { Debug.Log("backward"); //backward } else if(normal == new Vector3(0,0,1)) { Debug.Log("forward"); //forward } // Create a new GameObject for the camera GameObject cameraGameObject = new GameObject("OrthographicCamera"); // Add a Camera component Camera camera = cameraGameObject.AddComponent<Camera>(); // Set the camera to orthographic mode camera.orthographic = true; // Set the orthographic size camera.orthographicSize = 5; // Position the camera with the given offset camera.transform.position = targetObject.GetComponent<Collider>().bounds.center + offset ; // Make the camera look at the target object camera.transform.LookAt(targetObject.GetComponent<Collider>().bounds.center); Debug.Log("Orthographic camera created and positioned."); }
问题分析与解决方案
核心问题点
- 向量比较精度误差:直接用
==比较Vector3会因为浮点数精度问题导致判断失效,比如模型缩放、导入误差会让法线向量出现微小偏差。 - 相机位置计算逻辑错误:仅给墙体中心加固定偏移,没有结合墙体法线方向,导致相机无法精准处于墙的正前方。
- 朝向设置不准确:
LookAt虽然能让相机看向目标,但正交相机更适合直接设置forward方向,避免不必要的旋转偏差。 - 固定正交尺寸不合理:固定
orthographicSize = 5无法适配不同大小的墙体,会出现墙体显示不全或留白过多的问题。
修正后的代码
private void MakeCamera(GameObject targetObject, Vector3 normal) { if (targetObject == null) { Debug.LogError("未指定目标物体。"); return; } // 归一化法线向量,避免模型缩放导致的长度异常 normal = normal.normalized; // 获取墙体碰撞体的边界信息 Bounds wallBounds = targetObject.GetComponent<Collider>().bounds; Vector3 wallCenter = wallBounds.center; // 相机与墙体的距离,可根据需求调整 float cameraOffsetDistance = 5f; // 计算相机位置:从墙体中心沿法线反方向移动指定距离,确保在墙的正前方 Vector3 cameraPosition = wallCenter - normal * cameraOffsetDistance; // 创建相机对象 GameObject cameraGameObject = new GameObject("OrthographicCamera"); Camera camera = cameraGameObject.AddComponent<Camera>(); // 设置为正交模式 camera.orthographic = true; // 动态计算正交尺寸,适配不同大小的墙体 Vector3 localWallSize = cameraGameObject.transform.InverseTransformVector(wallBounds.size); // 取宽高中较大值,留10%余量避免边缘裁切 camera.orthographicSize = Mathf.Max(localWallSize.y, localWallSize.x) / 2f * 1.1f; // 设置相机位置与朝向 camera.transform.position = cameraPosition; // 让相机朝向墙体,forward方向与法线方向一致 camera.transform.forward = normal; Debug.Log("正交相机已创建并定位完成。"); }
关键优化说明
- 法线归一化:确保法线向量长度为1,避免因模型缩放导致的位置计算偏差。
- 精准位置计算:通过
wallCenter - normal * cameraOffsetDistance让相机始终处于墙体正前方,适配任意朝向的墙体。 - 动态尺寸适配:根据墙体实际大小计算正交尺寸,保证墙体完整显示在相机视野内。
- 直接设置朝向:用
transform.forward = normal代替LookAt,避免多余旋转,确保相机朝向精准。
额外建议
- 若需隐藏其他物体,可给目标墙体单独设置图层,修改相机的
cullingMask只渲染该图层。 - 可预先创建相机对象池,避免频繁创建销毁相机带来的性能损耗。
内容的提问来源于stack exchange,提问作者Ajay Gediya
相关产品推荐
相关产品推荐

