[Unity]在TileMap上控制Camera移动、缩放

环境:

  1. unity2021.3.14f1c1
  2. Camera类型Orthographic
  3. TileMap为XY方向摆放

功能:

  1. 单点触摸或鼠标操作移动Camera。
  2. 使用BoxCollider2D控制地图范围。
  3. 鼠标滚轮或多点触摸控制缩放。
  4. 缩放维持中心点在屏幕的固定位置。

代码:

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;}
}

参考:

  1. 【Unity触控】实现缩放和360度观察模型、单击、双击、滑动-阿里云开发者社区
  2. [Unity 3D]用鼠标滚轮实现镜头放大和缩放,并添加距离限制 - 伊凡晴天 - 博客园
  3. Unity 实现鼠标拖拽查看地图_鼠标控制地图移动 unity system-CSDN博客
  4. Unity3D 鼠标拖动地图实现_unity3d 鼠标移动ui界面地图-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/60679.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Unity3D 截图

使用 Unity3D 自带的截图接口&#xff0c;制作截图工具。 截图 有时候我们想对 Unity 的窗口进行截图&#xff0c;如果直接使用一些截图工具&#xff0c;很难截取到一张完整分辨率的图片&#xff08;例如&#xff0c;我们想要截取一张 1920 * 1080 的图片&#xff09;。 其实…

Mysql的加锁情况详解

最近在复习mysql的知识点&#xff0c;像索引、优化、主从复制这些很容易就激活了脑海里尘封的知识&#xff0c;但是在mysql锁的这一块真的是忘的一干二净&#xff0c;一点映像都没有&#xff0c;感觉也有点太难理解了&#xff0c;但是还是想把这块给啃下来&#xff0c;于是想通…

丹摩征文活动 | AI创新之路,DAMODEL助你一臂之力GPU

目录 前言—— DAMODEL&#xff08;丹摩智算&#xff09; 算力服务 直观的感受算力提供商的强大​ 平台功能介绍​ 镜像选择 云磁盘创建 总结 前言—— 只需轻点鼠标,开发者便可拥有属于自己的AI计算王国 - 从丰富的GPU实例选择,到高性能的云磁盘,再到预配置的深度学习…

Linux之日志

日志 在编写网络服务器, 各种软件时, 程序一定要打印一些日志信息. 1. 可以向显示器打印, 也可以向文件中写入. 2. 日志是软件在运行时记录的流水账, 用于排查服务进程挂掉的信息. 其中必须要有的是: 日志等级, 时间, 日志内容.可选的是文件名, 代码行数, 进程pid 等 日志…

IDEA指定Maven的settings不生效问题处理

文章目录 一、问题描述二、问题分析三、问题解决 一、问题描述 在Idea中手动指定了maven的settings配置文件&#xff0c;但是一直没生效。 如下图&#xff1a;设置加载settings-aliyun.xml文件&#xff0c;但是最后发现还是在加载settings.xml文件 二、问题分析 ‌在Intel…

【软考】数据库

1. 数据模型 1.1 概念数据模型 概念数据模型一般用 E-R 图表示&#xff0c;常用术语如下&#xff1a; 实体&#xff1a;客观存在的事物&#xff0c;如&#xff1a;一个单位、一个职工、一个部门、一个项目。属性&#xff1a;学生实体有学号、姓名、出生日期等属性。码&#…

oneplus6线刷、trwp、magisk(apatch)、LSPosed、Shamiko、Hide My Applist

oneplus6线刷android10.0.1 oneplus6线刷包(官方android10.0.1)下载、线刷教程&#xff1a; OnePlus6-brick-enchilada_22_K_52_210716_repack-HOS-10_0_11-zip 启用开发者模式 设置 / 连续点击6次版本号 : 启用开发者模式设置/开发者模式/{打开 usb调试, 打开 网络adb调试,…

ByteBuffer模拟拆包输出消息字符串

以下代码模拟网络编程中的粘包现象&#xff0c;用\n进行分割消息块 源码 public static void main(String[] args) {ByteBuffer byteBuffer1 ByteBuffer.allocate(60) ;byteBuffer1.put("Hello World\nWhat is you name?\nI am Licky!\nHo".getBytes());splice(byt…

成都睿明智科技有限公司怎么样可靠不?

在这个日新月异的数字时代&#xff0c;电商行业如同一股不可阻挡的洪流&#xff0c;席卷着每一个消费者的生活。而抖音&#xff0c;作为短视频与电商完美融合的典范&#xff0c;更是为无数商家开辟了一片全新的蓝海。在这片充满机遇与挑战的海洋中&#xff0c;成都睿明智科技有…

【计算机网络】多路转接之epoll

epoll也是一种linux中的多路转接方案(epoll也是只负责IO过程中的"等") 一、epoll相关接口的使用 1.epoll_create int epoll_create(int size); ​功能&#xff1a;创建一个epoll模型 ① int size&#xff1a;没意义了 >0就行 返回值&#xff1a;返回一个文件…

Linux高阶——1117—TCP客户端服务端

目录 1、sock.h socket常用函数 网络初始化函数 首次响应函数 测试IO处理函数 获取时间函数 总代码 2、sock.c SOCKET() ACCEPT()——服务端使用这个函数等待客户端连接 CONNECT()——客户端使用这个函数连接服务端 BIND()——一般只有服务端使用 LISTEN()——服务端…

【SVN和GIT】版本控制系统详细下载使用教程

文章目录 ** 参考文章一、什么是SVN和GIT二、软件使用介绍1 SVN安装1.1 服务端SVN下载地址1.2 客户端SVN下载地址2 SVN使用2.1 服务端SVN基础使用2.1.1 创建存储库和用户成员2.1.2 为存储库添加访问人员2.2 客户端SVN基础使用2.2.1 在本地下载库中的内容2.2.2 版本文件操作--更…

【含文档】基于django+Vue的荣誉证书管理系统(含源码+数据库+lw)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 主要技术: django,mysql,vue 2.视频演示地址 3.功能 系统定义了三个角色&#xff1a;管理员和学生和教师。 管理员进…

ros2学习日记_241124_ros相关链接

前言 提醒&#xff1a; 文章内容为方便作者自己后日复习与查阅而进行的书写与发布&#xff0c;其中引用内容都会使用链接表明出处&#xff08;如有侵权问题&#xff0c;请及时联系&#xff09;。 其中内容多为一次书写&#xff0c;缺少检查与订正&#xff0c;如有问题或其他拓展…

AIGC-------AIGC在社交媒体内容生成中的应用

AIGC在社交媒体内容生成中的应用 引言 随着人工智能生成内容&#xff08;AIGC&#xff09;的快速发展&#xff0c;社交媒体平台上的内容创作方式发生了巨大变化。AIGC使得内容创作的门槛大大降低&#xff0c;从而让更多的人能够参与到社交媒体内容的创作中&#xff0c;同时也使…

GWO-SVMD分解 | Matlab实现GWO-SVMD灰狼算法优化逐次变分模态分解

GWO-SVMD分解 | Matlab实现GWO-SVMD灰狼算法优化逐次变分模态分解 目录 GWO-SVMD分解 | Matlab实现GWO-SVMD灰狼算法优化逐次变分模态分解效果一览基本介绍程序设计参考资料 效果一览 基本介绍 GWO-SVMD灰狼算法优化逐次变分模态分解 内有15种用以优化svmd的适应度函数&#…

意识与人工智能:德国语言学家Joscha Bach的“梦境意识”理论探讨

引言 在人类的科学探索中&#xff0c;意识无疑是最深奥的未解之谜之一。尽管我们可以清晰地感知到自己的存在和思维&#xff0c;但意识究竟是什么&#xff1f;它从何而来&#xff1f;是否是物理世界的产物&#xff1f;以及人工智能是否能拥有意识&#xff1f;这些问题一直困扰…

Android Binder技术概览

Android中的Binder是一种基于远程过程调用&#xff08;Remote Procedure Call, RPC&#xff09;的轻量级通信机制&#xff0c;核心用于 Android 系统中的进程间通信&#xff08;Inter-Process Communication, IPC&#xff09;。Binder 是 Android 系统中不可或缺的一部分&#…

AI模型---安装cuda与cuDNN

1.安装cuda 先打开cmd 输入nvidia-smi 查看显卡支持cuda对应的版本&#xff1a; 然后去英伟达官网下载cuda&#xff08;外网多刷几次&#xff09; https://developer.nvidia.com/cuda-toolkit-archive 注意对应版本 安装过程中如果显示如下图&#xff1a; 请安装visual Stu…

ajax (一)

什么是 AJAX [ˈeɪdʒks] &#xff1f; 概念&#xff1a;AJAX是浏览器与服务器进行 数据通信 的技术&#xff0c;动态数据交互 怎么用AJAX? 1. 先使用 axios [k‘sio ʊ s] 库&#xff0c; 与服务器进行 数据通信 ⚫ 基于 XMLHttpRequest 封装、代码简单、月下载量在 1…