Unity 2D场景中如何限制摄像机移动不超出地图范围?
Unity 2D摄像机响应式边界限制实现方案
我在Unity中创建了一个以Sprite(山丘)作为地图的2D世界,已经用下面的脚本实现了鼠标移到游戏窗口边缘时摄像机左右移动的功能,但现在需要添加逻辑,阻止摄像机移动超出地图范围。关键是游戏要做响应式适配,固定数值的限制方案行不通,自己之前的思路没跑通,网上找的方案要么晦涩要么没解释,求靠谱的解决办法。
原摄像机移动脚本:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class MoveCam : MonoBehaviour { public Camera Camera; //idk why i did this the component is parented to maincam public float Divider; //This is to reduce the move amount to reasonable numbers. void Start() { } void FixedUpdate() { Vector3 mousePos = Input.mousePosition; //The simple stuff. Getting the mouse position Debug.Log(mousePos.x); //Some debug stuff Debug.Log(mousePos.y); Debug.Log(Screen.width / 14); Debug.Log(Screen.width - (Screen.width / 14)); if (mousePos.x < Screen.width / 14) //The if statement to trigger the movement only when the mouse is in the calculated border radius. I use the example 49 < 700 / 14 = 49 < 50 { Camera.transform.Translate((mousePos.x - Screen.width / 14) / Divider, 0, 0); //Move the camera to the left by the calculated strength which is the distance between the mouse and the border radius end reduced to reasonable amounts by the Divider variable. It is set to 50 in the engine currently. The example is (49 - 700 / 14) / 50 = (49 - 50) / 50 = -1 / 50 = -0.02 Debug.Log((mousePos.x - Screen.width / 14) / Divider); //Debug stuff } else if (mousePos.x > Screen.width - (Screen.width / 14)) //If not, we'll check if the mouse is in the right. We calculate the right border radius by subtracting the full width of the game window by the calculated radius. 651 > 700 - (700 / 14) = 651 > 700 - 50 = 651 > 650 { Camera.transform.Translate((mousePos.x - (Screen.width - (Screen.width / 14))) / Divider, 0, 0); //The same, but we replace the left with right using the algorithm that's explained above. Debug.Log((mousePos.x - (Screen.width - (Screen.width / 14))) / Divider); //DEBUGGGG } } }
实现思路
核心是动态计算地图边界和摄像机可视范围,不管地图尺寸、屏幕分辨率怎么变,都能自动适配:
- 获取地图Sprite的世界空间边界(左右极限位置)
- 根据摄像机的正交大小和屏幕宽高比,算出摄像机可视范围的半宽度
- 每次摄像机移动后,把它的X轴位置限制在「地图左边界+摄像机半宽」到「地图右边界-摄像机半宽」之间
修改后的完整代码
using UnityEngine; public class MoveCam : MonoBehaviour { public Camera mainCamera; // 可直接拖入主摄像机,未赋值则自动获取 public float divider = 50f; // 移动速度系数,数值越大移动越慢 public SpriteRenderer mapRenderer; // 拖入地图的SpriteRenderer组件 private float mapLeftBound; private float mapRightBound; private float cameraHalfWidth; void Start() { // 自动获取主摄像机(如果未手动赋值) if (mainCamera == null) { mainCamera = Camera.main; } // 初始化计算地图边界 CalculateMapBounds(); // 初始化计算摄像机可视半宽 CalculateCameraHalfWidth(); } void FixedUpdate() { // 每帧重新计算(应对屏幕分辨率动态变化的情况) CalculateCameraHalfWidth(); Vector3 mousePos = Input.mousePosition; // 保留原有的边缘移动逻辑 if (mousePos.x < Screen.width / 14) { mainCamera.transform.Translate((mousePos.x - Screen.width / 14) / divider, 0, 0); } else if (mousePos.x > Screen.width - (Screen.width / 14)) { mainCamera.transform.Translate((mousePos.x - (Screen.width - (Screen.width / 14))) / divider, 0, 0); } // 执行摄像机位置限制 ClampCameraPosition(); } // 计算地图的左右边界(世界坐标) void CalculateMapBounds() { if (mapRenderer == null) { Debug.LogError("请给mapRenderer赋值地图的SpriteRenderer组件!"); return; } Bounds mapBounds = mapRenderer.bounds; mapLeftBound = mapBounds.center.x - mapBounds.extents.x; mapRightBound = mapBounds.center.x + mapBounds.extents.x; } // 计算摄像机可视范围的半宽度(世界坐标) void CalculateCameraHalfWidth() { // 正交摄像机可视高度=2*orthographicSize,宽度=高度*屏幕宽高比 cameraHalfWidth = mainCamera.orthographicSize * (Screen.width / (float)Screen.height); } // 限制摄像机位置,不让它超出地图可视范围 void ClampCameraPosition() { Vector3 newPos = mainCamera.transform.position; // 锁定X轴位置在允许区间内 newPos.x = Mathf.Clamp(newPos.x, mapLeftBound + cameraHalfWidth, mapRightBound - cameraHalfWidth); mainCamera.transform.position = newPos; } // 可选:如果地图尺寸在运行中会动态变化,取消注释后在地图更新时调用该方法 // public void UpdateMapBounds() // { // CalculateMapBounds(); // } }
使用说明
- 在Unity编辑器中,给脚本的
mapRenderer字段拖入地图的SpriteRenderer组件 - 将
mainCamera拖入主摄像机(或让脚本自动获取) - 调整
divider数值控制摄像机移动速度,数值越大移动越慢
关键细节解释
- 动态地图边界:通过SpriteRenderer的
bounds获取地图的世界空间尺寸,无论地图Sprite多大,都能准确拿到左右边界 - 响应式摄像机范围:根据屏幕宽高比和摄像机正交大小计算可视半宽,屏幕分辨率变化时自动适配
- 位置限制:用
Mathf.Clamp把摄像机X轴位置锁在允许区间,确保摄像机的左右边缘不会露出地图以外的区域
内容的提问来源于stack exchange,提问作者Viliam
相关产品推荐
相关产品推荐

