环境:
- unity2021.3.14f1c1
- Camera类型Orthographic
- TileMap为XY方向摆放
功能:
- 单点触摸或鼠标操作移动Camera。
- 使用BoxCollider2D控制地图范围。
- 鼠标滚轮或多点触摸控制缩放。
- 缩放维持中心点在屏幕的固定位置。
代码:
using System;
using UnityEngine;public class TileMapCameraController : MonoBehaviour
{[SerializeField]GameObject targetMap;[SerializeField]Camera targetCam;private bool enableControl = true;private float camInitSize = 20;private float camMinSize = 5;private float camMaxSize = 30;private float camSizeScrollWheelV = 10;private Vector2 firstTouchPos;private Vector2 cameraFirstPos;private bool isMoving = false;private bool isBegan = false;private bool isOnScale = false;private float camOriginZ = 0;private Vector3 mapMin;private Vector3 mapMax;private Vector3 camNewPos = new Vector3();// 双触点初始距离private float baseDis;// 双触点初始中心private Vector2 baseMidScreen;// 双触点初始中心private Vector3 baseMidWorld;// 双触点初始镜头sizeprivate float baseSize;private float baseScale = 1;void Awake(){Init();}private void Init(){if (targetMap){var bounds = targetMap.GetComponent<BoxCollider2D>().bounds;mapMax = bounds.max;mapMin = bounds.min;}if (targetCam){targetCam.orthographicSize = camInitSize;camOriginZ = targetCam.transform.position.z;}}public void Init(GameObject map, Camera cam){targetMap = map;targetCam = cam;Init();}void Update(){if (!enableControl || !targetCam) return;// touchUpdateTouch();// mouseUpdateMouse();}private void UpdateTouch(){if (Input.touchCount == 1){Touch t = Input.touches[0];if (t.phase == TouchPhase.Began){isBegan = true;firstTouchPos = t.position;cameraFirstPos = targetCam.transform.position;}else if (t.phase == TouchPhase.Moved){if (isBegan){isMoving = true;MoveCam(firstTouchPos, t.position);}}else if (t.phase == TouchPhase.Ended || t.phase == TouchPhase.Canceled){if (isBegan){isBegan = false;isMoving = false;MoveCam(firstTouchPos, t.position);}}}else if (Input.touchCount > 1){isOnScale = true;Touch t1 = Input.touches[0];Touch t2 = Input.touches[1];if (t1.phase == TouchPhase.Canceled || t2.phase == TouchPhase.Canceled || t1.phase == TouchPhase.Ended || t2.phase == TouchPhase.Ended){isOnScale = false;return;}bool isNew = t1.phase == TouchPhase.Began || t2.phase == TouchPhase.Began;if (isNew)//两个触控点中任意一个刚按下时{baseDis = Vector2.Distance(t1.position, t2.position);// 焦点baseMidScreen = (t1.position + t2.position) / 2;baseMidWorld = targetCam.ScreenToWorldPoint(baseMidScreen);baseSize = targetCam.orthographicSize;}else{isBegan = false;//两个触控点 任意一个移动时if (t1.phase == TouchPhase.Moved || t2.phase == TouchPhase.Moved){//当前的两个触控点的距离float nowDis = Vector2.Distance(t1.position, t2.position);//根据两个触控点的当前距离和初始距离的比值等比例改变缩放值float size = baseDis / nowDis * baseSize;float delta = (size - baseSize) * baseScale;size = baseSize + delta;SetCamSize(size);Vector3 mid = targetCam.ScreenToWorldPoint(baseMidScreen);Vector3 adjust = baseMidWorld - mid;FocusTo(targetCam.transform.position + adjust);}}}}private void UpdateMouse(){if (isOnScale) return;float mouseCenter = Input.GetAxis("Mouse ScrollWheel");if (mouseCenter < 0){// Debug.Log("缩小");SetCamSizeByDelta(-camSizeScrollWheelV * mouseCenter);}else if (mouseCenter > 0){// Debug.Log("放大");SetCamSizeByDelta(-camSizeScrollWheelV * mouseCenter);}if (Input.GetMouseButtonDown(0)){isBegan = true;firstTouchPos = Input.mousePosition;cameraFirstPos = targetCam.transform.position;}if (Input.GetMouseButtonUp(0)){if (isBegan){isBegan = false;isMoving = false;MoveCam(firstTouchPos, Input.mousePosition);}}if (Input.GetMouseButton(0)){if (isBegan){MoveCam(firstTouchPos, Input.mousePosition);}}}private void SetCamSizeByDelta(float delta){float srcSize = targetCam.orthographicSize;float size = srcSize + delta;SetCamSize(size);}private void SetCamSize(float size){size = Math.Max(camMinSize, size);size = Math.Min(camMaxSize, size);targetCam.orthographicSize = size;CheckCam();}private void MoveCam(Vector2 fromScreenPos, Vector2 toScreenPos){Vector2 delta = targetCam.ScreenToWorldPoint(fromScreenPos) - targetCam.ScreenToWorldPoint(toScreenPos);var newPos = cameraFirstPos + delta;camNewPos.x = newPos.x;camNewPos.y = newPos.y;camNewPos.z = camOriginZ;FocusTo(camNewPos);}private void FocusTo(Vector3 worldPos){targetCam.transform.position = worldPos;CheckCam();}private void CheckCam(){var cameraHalfWidth = targetCam.orthographicSize * ((float)Screen.width / Screen.height);var cameraHalfHeight = targetCam.orthographicSize;//保证不会移除包围盒var pos = targetCam.transform.position;camNewPos.x = Mathf.Clamp(pos.x, mapMin.x + cameraHalfWidth, mapMax.x - cameraHalfWidth);camNewPos.y = Mathf.Clamp(pos.y, mapMin.y + cameraHalfHeight, mapMax.y - cameraHalfHeight);camNewPos.z = camOriginZ;targetCam.transform.position = camNewPos;}
}
参考:
- 【Unity触控】实现缩放和360度观察模型、单击、双击、滑动-阿里云开发者社区
- [Unity 3D]用鼠标滚轮实现镜头放大和缩放,并添加距离限制 - 伊凡晴天 - 博客园
- Unity 实现鼠标拖拽查看地图_鼠标控制地图移动 unity system-CSDN博客
- Unity3D 鼠标拖动地图实现_unity3d 鼠标移动ui界面地图-CSDN博客