Unity | Tilemap系统
目录
一、准备工作
1.插件导入
2.资源导入
二、相关组件介绍
1.Grid组件
2.Tilemap组件
3.Tile
4.Tile Palette
5.Brushes
三、动态创建地图
四、其他功能
1.移动网格上物体
2.拖拽缩放地图
Unity Tilemap系统为2D游戏开发提供了一个直观且功能强大的平台,使得创建复杂且美观的游戏世界变得更加容易,Unity的Tilemap系统经过优化,能够高效地处理大量Tiles,确保游戏在各种设备上都能流畅运行。
一、准备工作
1.插件导入

2.资源导入
提供一个我找了半天才找到的tile图像资源。因为我要做等距透视地图,所以需要是菱形,并且图片长=宽。
![]()
当最终绘制的地图不合适时,可以调整图像的Pivot:

二、相关组件介绍
1.Grid组件
Grid组件是Unity中用于创建和管理网格(Grid)的基础组件,特别适用于2D游戏开发中的Tilemap系统。网格布局可以是矩形、六边形等。

- Cell Size
开发者可以定义每个网格单元的大小。这对于确保Tiles和其他元素在正确的位置上显示非常重要。
- Cell Gap
允许开发者在网格单元之间设置间隙,从而调整元素之间的距离。这样可以创建更复杂的布局效果。
- CellLayout
枚举包括以下几种布局类型:
- Rectangle:矩形布局。单元格以矩形的形式排列,这是最常见的一种布局方式。
- Hexagon:六边形布局。单元格以六边形的形式排列,通常用于需要六边形网格的游戏或应用。
- Isometric:等距菱形布局。单元格以等距(菱形)的形式排列,常用于等距视角的游戏,例如模拟类游戏。
- IsometricZAsY:等距Z轴作为Y轴布局。这种布局类似于等距布局,但Z轴值将被添加为Y值。这种布局通常用于需要特殊等距视角效果的场景。
- cellSwizzle
用于重新排列网格单元格的坐标。具体来说, 允许将默认的 XYZ 单元格坐标重新排序为不同的排列方式。以下是一些可能的重排选项:
- XYZ:保持单元格位置不变。
- XZY:将单元格位置从 XYZ 重排为 XZY。
- YXZ:将单元格位置从 XYZ 重排为 YXZ。
- YZX:将单元格位置从 XYZ 重排为 YZX。
- ZXY:将单元格位置从 XYZ 重排为 ZXY。
- ZYX:将单元格位置从 XYZ 重排为 ZYX。
Grid组件通常与Tilemap组件一起使用,以实现复杂的2D场景设计。Tilemap会自动对齐到Grid定义的网格上,使得绘制和管理Tiles变得更加容易。Grid组件提供了一些方便的方法,用于在世界坐标、局部坐标和网格坐标之间进行转换。这使得在网格上定位对象变得更加简单和直观。
总结来说,Grid组件为Unity中的2D游戏开发提供了一个强大且灵活的基础结构,使得创建和管理基于网格的场景变得更加简单和高效。
2.Tilemap组件
Unity的Tilemap系统是一个强大的工具,用于在2D游戏开发中创建和管理网格化的游戏世界。Tilemap组件是用于在场景中绘制瓦片(Tiles)的基础组件。它可以与Grid组件一起使用,以定义网格的大小和形状。

3.Tile
Tilemap系统中的基本构建块。每个Tile代表一个小的图像或动画,可以重复使用来创建更大的图案或场景。Tiles可以包含碰撞信息、颜色等属性。

4.Tile Palette
一个用户界面工具,允许开发者创建、编辑和管理Tiles。开发者可以将Tiles拖放到Tile Palette中,然后使用画笔工具将它们绘制到Tilemap上。

5.Brushes
Brushes是用于在Tilemap上绘制Tiles的工具。Unity提供了多种预定义的Brushes,例如普通画笔、随机画笔等,开发者也可以创建自定义Brushes以满足特定需求。

- Default Brush:默认的绘画刷,用于基本的Tile绘制操作。
- GameObject Brush:用于在Tilemap上绘制GameObjects,而不仅仅是Tiles。
- Group Brush:允许用户将多个Tiles组合在一起,并作为一个整体进行绘制。
- Random Brush:可以随机选择预定义的Tiles进行绘制,适合创建更自然和多样化的Tilemap。
- Line Brush:用于绘制直线形状的Tiles,方便创建路径或直线结构。
总之,Unity Tilemap系统为2D游戏开发提供了一个直观且功能强大的平台,使得创建复杂且美观的游戏世界变得更加容易,Unity的Tilemap系统经过优化,能够高效地处理大量Tiles,确保游戏在各种设备上都能流畅运行。
三、动态创建地图
1.创建空物体Grid,添加Grid组件。

2.创建Grid的子物体Tilemap,添加Tilemap及Tilemap Renderer组件。

3.代码展示。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;public class CreatTail : MonoBehaviour
{public Tilemap tilemap;public TileBase[] tiles; // 一个包含多个不同类型瓦片的数组int tileIndex = 0;private void Start(){GenerateMap();}void GenerateMap(){for (int x = 0; x < 20; x++){for (int y = 0; y < 21; y++){tileIndex = tileIndex == 0 ? 1 : 0;SetTile(new Vector3Int(x - 10, -y + 10, 0), tiles[tileIndex]);}}#if UNITY_EDITORstring prefabPath = "Assets/Prefabs/Tilemap.prefab";//动态制作预制体UnityEditor.PrefabUtility.SaveAsPrefabAsset(tilemap.gameObject, prefabPath);#endif}void SetTile(Vector3Int position, TileBase tile){tilemap.SetTile(position, tile);}
}
4.效果展示

四、其他功能
1.移动网格上物体
可移动的物体设置layer为第7层,并将下方代码拖到该物体身上。当移动物体时,如果目标格子有物体,则不能放置。
using UnityEngine;
using UnityEngine.Tilemaps;public class DragManager : MonoBehaviour
{private bool isDragging = false;private Vector3 offset;private Camera mainCamera;private Vector3 lastPos;void Start(){mainCamera = Camera.main;}void OnMouseDown(){isDragging = true;offset = transform.position - GetMouseWorldPosition();lastPos=transform.position;}void OnMouseUp(){isDragging = false;// 获取鼠标位置对应的Tilemap位置Tilemap tilemap = FindObjectOfType<Tilemap>();Vector3Int cellPosition = tilemap.WorldToCell(GetMouseWorldPosition());// 将物体放置到格子中心//transform.position = tilemap.GetCellCenterWorld(cellPosition);//transform.position=new Vector3 (transform.position.x,transform.position.y,0);Vector3 targetPosition = tilemap.GetCellCenterWorld(cellPosition);targetPosition.z = 0;Collider2D[] hitCollider = Physics2D.OverlapPointAll((Vector2)targetPosition);if (hitCollider.Length<=0){transform.position = targetPosition;}else{Debug.Log("Target position already occupied by another object.");foreach (var item in hitCollider){Debug.Log(item.name);}if (hitCollider.Length==1&& hitCollider[0].name==transform.name){transform.position = targetPosition;}else{transform.position = lastPos;}}}void Update(){if (isDragging){Vector3 targetPosition = GetMouseWorldPosition() + offset;targetPosition.z = -1;transform.position = targetPosition;}}private Vector3 GetMouseWorldPosition(){Vector3 mouseScreenPosition = Input.mousePosition;mouseScreenPosition.z = -9;// mainCamera.nearClipPlane; // 确保z轴值正确return mainCamera.ScreenToWorldPoint(mouseScreenPosition);}
}
2.拖拽缩放地图
拖拽地图时,如果焦点在物体身上,则不拖拽。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class GameController : MonoBehaviour
{public float zoomSpeed = 0.1f; // 缩放速度public float minZoom = 1f; // 最小缩放值public float maxZoom = 3f; // 最大缩放值private Vector2 dragOrigin;private Camera mainCamera;public bool drag;public float mapLength = 10f; public float mapWidth = 10f;private void Start(){mainCamera = Camera.main;maxZoom = mainCamera.orthographicSize;}void Update(){
#if UNITY_EDITOR || UNITY_STANDALONEHandleMouseInput();
#elif UNITY_ANDROID || UNITY_IOSHandleTouchInput();
#endif}#if UNITY_EDITOR || UNITY_STANDALONEprivate void HandleMouseInput(){// 放大/缩小if (Input.mouseScrollDelta.y != 0){//Debug.Log(Input.mouseScrollDelta.y);Zoom(Input.mouseScrollDelta.y * zoomSpeed);}// 拖拽屏幕if (Input.GetMouseButtonDown(0)){Vector3 ray = Camera.main.ScreenToWorldPoint(Input.mousePosition);RaycastHit2D hit = Physics2D.Raycast(ray, Vector2.zero, 100, 1 << 7);// 检查是否有物体被射线击中if (hit.collider != null){Debug.Log("Hit " + hit.collider.gameObject.name);}else{dragOrigin = Input.mousePosition;drag = true;}return;}//if (Input.GetMouseButtonDown(0))//{// dragOrigin = Input.mousePosition;// return;//}if (!Input.GetMouseButton(0)) { drag = false;return; }if (drag){Vector3 difference = mainCamera.ScreenToViewportPoint((Vector2)Input.mousePosition - dragOrigin);Vector3 move = new Vector3(difference.x * mainCamera.orthographicSize, difference.y * mainCamera.orthographicSize, 0);mainCamera.transform.Translate(-move, Space.World);dragOrigin = Input.mousePosition;}}
#endif#if UNITY_ANDROID || UNITY_IOSprivate void HandleTouchInput(){if (Input.touchCount == 2){Touch touchZero = Input.GetTouch(0);Touch touchOne = Input.GetTouch(1);Vector2 touchZeroPrevPos = touchZero.position - touchZero.deltaPosition;Vector2 touchOnePrevPos = touchOne.position - touchOne.deltaPosition;float prevMagnitude = (touchZeroPrevPos - touchOnePrevPos).magnitude;float currentMagnitude = (touchZero.position - touchOne.position).magnitude;float difference = currentMagnitude - prevMagnitude;Zoom(difference * zoomSpeed);}if (Input.touchCount == 1){Touch touch = Input.GetTouch(0);if (touch.phase == TouchPhase.Began){Vector3 ray = Camera.main.ScreenToWorldPoint(Input.mousePosition);RaycastHit2D hit = Physics2D.Raycast(ray, Vector2.zero, 100, 1 << 7);//只检测可拖拽的物体层if (hit.collider != null){Debug.Log("Hit " + hit.collider.gameObject.name);}else //没有点击到物体,则拖拽屏幕{dragOrigin = touch.position;drag = true;}return;}if (touch.phase != TouchPhase.Moved){drag = false;return;}if (drag){Vector3 difference = mainCamera.ScreenToViewportPoint(touch.position - dragOrigin);Vector3 move = new Vector3(difference.x * mainCamera.orthographicSize, difference.y * Camera.main.orthographicSize, 0);mainCamera.transform.Translate(-move, Space.World);dragOrigin = touch.position;}}}
#endifprivate void Zoom(float increment){
#if UNITY_EDITOR || UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOSCamera.main.orthographicSize = Mathf.Clamp(mainCamera.orthographicSize - increment, minZoom, maxZoom);
#endif}
}
相关文章:
Unity | Tilemap系统
目录 一、准备工作 1.插件导入 2.资源导入 二、相关组件介绍 1.Grid组件 2.Tilemap组件 3.Tile 4.Tile Palette 5.Brushes 三、动态创建地图 四、其他功能 1.移动网格上物体 2.拖拽缩放地图 Unity Tilemap系统为2D游戏开发提供了一个直观且功能强大的平台ÿ…...
CSS选择符和可继承属性
属性选择符: 示例:a[target"_blank"] { text-decoration: none; }(选择所有target"_blank"的<a>元素) /* 选择所有具有class属性的h1元素 */ h1[class] { color: silver; } /* 选择所有具有hre…...
C++升级软件时删除老版本软件的桌面快捷方式(附源码)
删除桌面快捷方式其实是删除桌面上的快捷方式文件,那我们如何去删除桌面快捷方式文件呢?软件可能已经发布过多个版本,其中的一些版本的快捷方式文件名称可能做了多次改动,程序中不可能记录每个版本的快捷方式名称,没法直接去删除快捷方式文件。本文就给出一种有效的处理办…...
github国内加速访问有效方法
这里只介绍实测最有效的一种方法,修改主机的Hosts文件,如果访问github网站慢或者根本无法访问的时候可以采用下面方法进行解决。 1、搜索一个IP查询网站 首先百度搜索选择一个IP查询的网站,这里我用下面这个网站(如果该网站失效…...
如何处理JavaScript中的浮点数精度问题
在开发过程中,特别是涉及到金额计算或需要精确比较的场景,浮点数精度问题是一个常见而重要的挑战。本文将介绍在JavaScript中如何识别、理解和解决这些问题,并提供一些实用的技巧和建议。 1. 问题背景 JavaScript中的浮点数采用IEEE 754标准…...
ASPICE标准与ASPICE认证:提升汽车软件开发质量与效率的关键途径
在当今日新月异的科技时代,软件产品的质量和可靠性成为了企业赢得市场的关键。而ASPICE(Automotive SPICE)标准,作为汽车行业中软件过程评估的国际通用标准,正逐渐引起行业的广泛关注。那么,ASPICE标准究竟…...
easyexcel的简单使用(execl模板导出)
模板支持功能点 支持列表支持自定义头名称支持自定义fileName支持汇总 模板示例 操作 pom引入 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>${easyexcel.version}</version></dep…...
代码随想录算法训练营第39天|● 62.不同路径 ●63. 不同路径 II
不同路径 62. 不同路径 - 力扣(LeetCode) 1.确定dp数组(dp table)以及下标的含义 dp[i][j] :表示从(0 ,0)出发,到(i, j) 有dp[i][j]条不同的路径。 2.确定递推公式 …...
【DevOps】 什么是容器 - 一种全新的软件部署方式
目录 引言 一、什么是容器 二、容器的工作原理 三、容器的主要特性 四、容器技术带来的变革 五、容器技术的主要应用场景 六、容器技术的主要挑战 七、容器技术的发展趋势 引言 在过去的几十年里,软件行业经历了飞速的发展。从最初的大型机时代,到后来的个人电脑时代,…...
使用pnpm创建vue3项目
https://pnpm.io/zh/ 全局安装: npm install -g pnpm 检查版本: pnpm -v 创建vue3项目: pnpm create vuelatest 项目装包: pnpm install 运行项目: pnpm dev 命令行: https://pnpm.io/zh/pnpm-cli pnpm …...
【软件测试】43个功能测试点总结
🍅 视频学习:文末有免费的配套视频可观看 🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快 功能测试就是对产品的各功能进行验证,根据功能测试用例,逐项测试…...
Python — — GPU编程
Python — — GPU编程 要想将Python程序运行在GPU上,我们可以使用numba库或者使用cupy库来实现GPU编程。 壹、numba Numba 是一个开源的 JIT (Just-In-Time) 编译器,它可以将 Python 代码转换成机器代码以提高性能。Numba 特别适用于需要高性能计算的…...
C#中的枚举类-自定义属性
在实际开发过程中,我们常常会用到枚举类,使用枚举的时候往往有着各种使用条件,如何给枚举加入使用条件呢? 答案就是我们的——自定义属性 废话不多说,上代码 枚举类 首先我们要有一个枚举类 public enum XXXX枚举…...
多态深度剖析
前言 继承是多态的基础, 如果对于继承的知识还不够了解, 可以去阅读上一篇文章 继承深度剖析 基本概念与定义 概念: 通俗来说,就是多种形态。具体点就是去完成某个行为, 当不同的对象去完成时会产生出不同的状…...
OSPF被动接口配置(华为)
#交换设备 OSPF被动接口配置 一、基本概念 OSPF被动接口,也称为抑制接口,即将路由器某一接口配置为被动接口后,该接口不会再接受和发送OSPF报文 二、使用场景 在路由器与终端相近或者直接相连的一侧配置被动接口 因为OSPF会定期发送报文…...
Android --- 异步操作
同步和异步的差异 同步:在发生某件事后什么也不做,直到该事件完成后,再继续进行 异步:在某件事发生后,可以在等待他完成的时候去处理其他事件,等到该事件发生完成后,再回过头来处理它。 异步…...
(55)MOS管专题--->(10)MOS管的封装
(10)MOS管的封装 1 目录 (a)IC简介 (b)数字IC设计流程 (c)Verilog简介 (d)MOS管的封装 (e)结束 1 IC简介 (a)在IC设计中,设计师使用电路设计工具(如EDA软件)来设计和模拟各种电路,例如逻辑电路、模拟电路、数字信号处理电路等。然后,根据设计电路的…...
超高清图像生成新SOTA!清华唐杰教授团队提出Inf-DiT:生成4096图像比UNet节省5倍内存。
清华大学唐杰教授团队最近在生成超高清图像方面的新工作:Inf-DiT,通过提出一种单向块注意力机制,能够在推理过程中自适应调整内存开销并处理全局依赖关系。基于此模块,该模型采用了 DiT 结构进行上采样,并开发了一种能…...
网络安全 - DNS劫持原理 + 实验
DNS 劫持 什么是 DNS 为什么需要 DNS D N S \color{cyan}{DNS} DNS(Domain Name System)即域名系统。我们常说的 DNS 是域名解析协议。 DNS 协议提供域名到 IP 地址之间的解析服务。计算机既可以被赋予 IP 地址,也可以被赋予主机名和域名。用…...
MyBatis的运行原理
目录 1、目的:梳理一下MyBatis运行时的几个对象,我们需要搞清楚他们的作用,进而需要理解mybatis的整个工作流程和执行原理。 2、简要概括各个类 2.1 Resources 作用:编写资源加载类,使用类加载器加载 配置文件(myb…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...
OkHttp 中实现断点续传 demo
在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...
ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
优选算法第十二讲:队列 + 宽搜 优先级队列
优选算法第十二讲:队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.
ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #:…...
