[Unity]在TileMap上控制Camera移动、缩放
环境:
- 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;
// 双触点初始镜头size
private 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;
// touch
UpdateTouch();
// mouse
UpdateMouse();
}
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博客
原文地址:https://blog.csdn.net/GrimRaider/article/details/143919354
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!