移动范围限制
有关正交摄像机的Size和实际渲染尺寸的关系:
https://atao-blast.github.io/2022/02/24/UnityBook/Unity-Book-Chapter6Part1/
在2D游戏中,只要我们设置的pixel per Unit是100,那么摄像机在世界坐标系下渲染的相对大小就能计算出来(Camera也提供了aspect属性)。
然后我们根据相机的RectTransform的位置和上面的相对大小,就能求得当前摄像机所渲染的世界坐标位置边界。然后根据这个边界限制飞机的飞行范围。
飞机本身的大小,可以根据SpriteRenderer
提供的bound属性求得,所有继承了Renderer
的组件都提供bound属性,可以计算对象的包围盒在世界空间中的位置,如果对象在世界空间中一直在运动,那么这个属性也是一直在变化的。
GameUtil
在里面提供获取当前摄像机视野边界的世界坐标的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| private static Vector2 _cameraSize = Vector2.zero; public static Vector2 GetCameraSize() { if (_cameraSize == Vector2.zero) { var camera = GetCamera(); var height = camera.orthographicSize * 2; var width = height * camera.aspect; _cameraSize = new Vector2(width, height); } return _cameraSize; } public static Vector2 GetCameraMin() { if (GetCamera() != null) { var pos = GetCamera().transform.position; var size = GetCameraSize(); return new Vector3(pos.x - size.x * 0.5f, pos.y - size.y * 0.5f, pos.z); } return Vector2.zero; } public static Vector2 GetCameraMax() { if (GetCamera() != null) { var pos = GetCamera().transform.position; var size = GetCameraSize(); return new Vector3(pos.x + size.x * 0.5f, pos.y + size.y * 0.5f, pos.z); } return Vector2.zero; } private static Camera _camera; public static Camera GetCamera() { if ( _camera == null) { _camera = GameObject.FindObjectOfType<Camera>(); if (_camera == null) Debug.LogError("当前场景没有Camera"); } return _camera; }
|
PlayerController
在里面提供判断当前飞机图片是否越过摄像机边界的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| void ReceiveW(params object[] args) { if(!JudgeUpBorder()) _moveCo.Move(Vector2.up); } void ReceiveS(params object[] args) { if(!JudgeDownBorder()) _moveCo.Move(Vector2.down); } void ReceiveA(params object[] args) { if(!JudgeLeftBorder()) _moveCo.Move(Vector2.left); } void ReceiveD(params object[] args) { if(!JudgeRightBorder()) _moveCo.Move(Vector2.right); } bool JudgeUpBorder() => _spriteRenderer.bounds.max.y >= GameUtil.GetCameraMax().y; bool JudgeDownBorder() => _spriteRenderer.bounds.min.y <= GameUtil.GetCameraMin().y; bool JudgeLeftBorder() => _spriteRenderer.bounds.min.x <= GameUtil.GetCameraMin().x; bool JudgeRightBorder() => _spriteRenderer.bounds.max.x >= GameUtil.GetCameraMax().x;
|
飞机拖动
先给Player的prefab挂载一个Box Collider 2D。注意修改它的大小,这个碰撞体也会作为受击碰撞体,不能太大,覆盖飞机的主体部分即可。
PlayerController
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| using UnityEngine;
public class PlayerController : MonoBehaviour { private Vector2 _offset; void Start() { InitData(); } private void InitData() { _offset = transform.position - _spriteRenderer.bounds.min; }
private void OnMouseDrag() { #if UNITY_EDITOR Drag(Input.mousePosition); #else if (Input.touchCount > 0) Drag(Input.touches[0].position); #endif if (JudgeUpBorder()) { ResetPosY(GameUtil.GetCameraMax(), Vector2.up); } else if (JudgeDownBorder()) { ResetPosY(GameUtil.GetCameraMin(), Vector2.down); }
if (JudgeLeftBorder()) { ResetPosX(GameUtil.GetCameraMin(), Vector2.left); } else if (JudgeRightBorder()) { ResetPosX(GameUtil.GetCameraMax(), Vector2.right); } } private void ResetPosX(Vector2 border, Vector2 direction) { var pos = transform.position; pos.x = border.x - Vector2.Dot(_offset,direction); transform.position = pos; } private void ResetPosY(Vector2 border, Vector2 direction) { var pos = transform.position; pos.y = border.y - Vector2.Dot(_offset, direction); transform.position = pos; } private void Drag(Vector3 screenPos) { var pos = Camera.main.ScreenToWorldPoint(screenPos); pos.z = 0; transform.localposition = pos; } }
|
修改PlayerController
记录一下另外一个修正Player边界位置的方法
1 2 3 4 5 6 7 8 9 10
| private void ResetPos(Vector2 border, Vector2 direction) { Vector2 pos = transform.position; pos -= Vector2.Dot(pos, direction) * direction; pos += Vector2.Dot(border, direction) * direction - Vector2.Dot(_offset, direction) * direction; transform.position = pos; }
|