Unity2D 2021.3.15f1:如何适配分辨率拉伸GameObject并实现屏幕边缘碰撞检测?
2D游戏分辨率适配与屏幕边缘碰撞解决方案
一、GameObject自适应分辨率拉伸
无需绑定固定16:9比例,直接基于相机视口动态计算缩放值,适配任意屏幕尺寸:
1. 初始化缩放计算(正交相机)
在GameObject的脚本中,通过相机正交尺寸和宽高比,算出适配当前屏幕的缩放比例:
void Start() { Camera mainCam = Camera.main; // 获取相机覆盖的世界空间高度、宽度 float worldHeight = mainCam.orthographicSize * 2f; float worldWidth = worldHeight * mainCam.aspect; // 替换为你设计时的参考宽度(比如16:9下GameObject的宽度) float referenceWidth = 10f; float scaleFactor = worldWidth / referenceWidth; // 应用缩放,保持宽高比一致 transform.localScale = new Vector3(scaleFactor, scaleFactor, 1f); }
2. 监听屏幕尺寸变化,实时更新缩放
添加屏幕尺寸变化监听,确保窗口或设备分辨率改变时,GameObject自动适配:
void OnEnable() { Screen.onSizeChanged += UpdateObjectScale; } void OnDisable() { Screen.onSizeChanged -= UpdateObjectScale; } void UpdateObjectScale(int width, int height) { Camera mainCam = Camera.main; float worldHeight = mainCam.orthographicSize * 2f; float worldWidth = worldHeight * mainCam.aspect; float referenceWidth = 10f; float scaleFactor = worldWidth / referenceWidth; transform.localScale = new Vector3(scaleFactor, scaleFactor, 1f); }
二、屏幕边缘碰撞检测与反弹
放弃相机外的灰色矩形碰撞体,直接通过世界坐标计算屏幕边缘,高效实现碰撞检测和反弹:
1. 计算屏幕边缘的世界坐标
根据相机类型(正交/透视),获取屏幕四个边缘对应的世界位置:
// 正交相机用此方法 private Vector2 GetOrthographicScreenEdges() { Camera mainCam = Camera.main; float halfHeight = mainCam.orthographicSize; float halfWidth = halfHeight * mainCam.aspect; return new Vector2(halfWidth, halfHeight); } // 透视相机用此方法 private Vector2 GetPerspectiveScreenEdges() { Camera mainCam = Camera.main; Vector3 bottomRightWorld = mainCam.ScreenToWorldPoint(new Vector3(Screen.width, Screen.height, mainCam.nearClipPlane)); return new Vector2(Mathf.Abs(bottomRightWorld.x), Mathf.Abs(bottomRightWorld.y)); }
2. 碰撞检测与反弹逻辑
在FixedUpdate中检测GameObject位置是否超出边缘,触发反弹和自定义碰撞事件:
public float moveSpeed = 5f; private Vector2 moveDirection = new Vector2(1, 1); void FixedUpdate() { // 根据相机类型选择对应的边缘计算方法 Vector2 screenEdges = GetOrthographicScreenEdges(); Vector2 currentPos = transform.position; // 左右边缘碰撞检测与反弹 if (currentPos.x > screenEdges.x || currentPos.x < -screenEdges.x) { moveDirection.x *= -1; OnEdgeCollision(ScreenEdgeType.LeftRight); // 修正位置,避免物体卡在边缘外 currentPos.x = Mathf.Clamp(currentPos.x, -screenEdges.x, screenEdges.x); transform.position = currentPos; } // 上下边缘碰撞检测与反弹 if (currentPos.y > screenEdges.y || currentPos.y < -screenEdges.y) { moveDirection.y *= -1; OnEdgeCollision(ScreenEdgeType.TopBottom); currentPos.y = Mathf.Clamp(currentPos.y, -screenEdges.y, screenEdges.y); transform.position = currentPos; } // 应用移动 transform.Translate(moveDirection * moveSpeed * Time.fixedDeltaTime); } // 自定义碰撞事件处理 void OnEdgeCollision(ScreenEdgeType edgeType) { // 这里添加你的业务逻辑,比如播放音效、更新分数等 Debug.Log($"碰撞到屏幕边缘: {edgeType}"); } // 边缘类型枚举 enum ScreenEdgeType { LeftRight, TopBottom }
3. 注意事项
- 若GameObject带有Collider2D,无需额外添加边缘碰撞体,直接用坐标计算更高效
- 透视相机的边缘计算需注意近裁剪面设置,避免坐标偏差
内容的提问来源于stack exchange,提问作者cuenta microsoft
相关产品推荐
相关产品推荐

