Cocos Creator地图分块可视化编辑器,拖拽设置通行区域并导出JSON 本文还有配套的精品资源点击获取简介专为Cocos Creator 2D游戏设计的地图编辑工具界面操作无需写代码。按1280×640视口自动划分地图区块每块支持鼠标点击切换‘可通过’或‘不可通过’状态实时生成标准JSON格式的地图数据文件。支持本地map.文件导入在游戏运行时动态加载并渲染对应图块、标记点及碰撞区域。针对超大地图提供手动切块功能可将子图块挂载到指定mapNode节点下需提前配置该节点的宽高以匹配实际分块尺寸。项目已预置完整工程结构TypeScript编译配置tsconfig.、构建脚本builder.、ESLint规范、场景资源目录Scene、逻辑脚本目录Script、资源管理目录resources及详细README说明文档开箱即用兼容主流Cocos Creator版本。策划、关卡设计师和独立开发者可快速搭建带碰撞检测的可交互地图原型。1. 项目概述为什么我们需要一个“看得见、摸得着”的地图编辑器在Cocos Creator做2D游戏开发时我几乎每次搭新项目都会卡在同一个地方地图数据怎么来策划扔过来一个Excel表格列着“x,y,canPass”我得手动转成JSON美术给一张大图我要用PS切块、命名、拖进资源管理器再写脚本遍历生成TileMap更别提碰撞区域——要么硬编码一堆Rect要么靠调试器反复试坐标改一次跑三遍。这种“数据看不见、状态摸不着、改完不敢信”的工作流不是在写代码是在猜谜。这个编辑器就是为解决这个问题而生的。它不是一个抽象的数据生成器而是一个所见即所得的地图操作台你看到的每一块灰色方格就是运行时地图上的一个逻辑单元你鼠标点一下变绿游戏里角色就能走过去再点一下变红角色就会被挡住——整个过程没有中间层没有转换脚本没有魔法变量。核心关键词就三个Cocos Creator、地图分块、JSON地图编辑但背后是整套面向实际生产的设计哲学。它默认按1280×640视口尺寸进行自动分块这不是随便定的数字。我实测过十几款主流2D游戏横版动作、RPG俯视角、策略塔防这个分辨率刚好能覆盖中等复杂度关卡的可视范围既不会因单块太小导致渲染开销飙升比如切成64×64会生成上千个节点也不会因单块太大而丧失编辑精度比如整张4096×4096图只分4块根本没法精细控制路径。每块独立开关通行状态本质是在构建一张二值化导航网格Navigation Mesh的简化形态——没有A*寻路那么重但足够支撑角色移动、障碍判断、区域触发等90%的日常需求。更重要的是它彻底剥离了“编辑”和“运行”的边界。你导出的JSON不是静态配置文件而是可直接被Cocos Creator原生加载的结构化数据包含blocks数组每个元素含x,y,width,height,canPass、mapSize总宽高、blockSize单块尺寸三大核心字段连字段名都和Cocos官方TileMap组件的API对齐。这意味着策划在办公室拖拽完发个JSON文件给你你两行代码就能cc.loader.loadRes(maps/level1, cc.JsonAsset, (err, json) { ... })然后调用this.generateCollisionFromJson(json)——整个流程像插USB一样即插即用。它不替代美术工具也不取代程序逻辑而是稳稳卡在策划与程序员之间的那个“可信交接点”。2. 整体设计思路从“画布思维”到“运行时映射”的闭环构建2.1 分块逻辑的本质不是切割图像而是定义空间语义很多人第一反应是“这不就是把大图切成小图吗”其实完全相反。这个编辑器根本不处理图像像素它操作的对象是纯粹的空间坐标系。当你设置视口为1280×640系统做的第一件事是计算逻辑分块数const VIEW_WIDTH 1280; const VIEW_HEIGHT 640; const BLOCK_SIZE 64; // 默认单块64×64可配置 const COLS Math.ceil(VIEW_WIDTH / BLOCK_SIZE); // 20列 const ROWS Math.ceil(VIEW_HEIGHT / BLOCK_SIZE); // 10行注意这里COLS和ROWS是逻辑格子数不是像素数。每个格子对应一个{x, y, width, height, canPass}对象其中x和y是该格子左下角在世界坐标系中的位置单位像素width和height固定为BLOCK_SIZE。这意味着- 编辑器里你看到的“第3行第5列”方块在JSON里就是{x: 320, y: 384, width: 64, height: 64, canPass: true}- 游戏运行时你用cc.rect(x, y, width, height)创建碰撞矩形坐标值和JSON字段完全一致无需任何换算- 即使你后期把BLOCK_SIZE改成32只要保持VIEW_WIDTH/HEIGHT不变逻辑格子总数翻倍但每个格子的坐标依然自洽——这是保证“编辑即运行”的数学基础。为什么坚持用固定尺寸分块而非自由缩放我踩过坑。早期版本支持拖拽调整块大小结果策划把一块拉成128×128另一块缩成16×16导出JSON里width/height字段全乱了。程序加载时得额外做归一化处理稍有疏忽就出现“明明标了可通过角色却卡住”的诡异问题。后来砍掉所有自由缩放强制统一尺寸反而让整个流程稳定得像钟表——约束不是限制而是信任的锚点。2.2 可视化交互的核心状态驱动而非事件驱动传统编辑器常犯一个错误把点击事件当成核心逻辑。比如“点击方块→触发onBlockClick→更新状态→重绘”。这套逻辑在小规模场景没问题但当格子数超过200个即10×20以上频繁重绘会导致UI卡顿尤其在低配笔记本上。这个编辑器采用状态快照增量渲染模式所有格子状态存储在纯内存数组this._gridState: boolean[][]中初始全true可通过鼠标按下时只记录起始坐标(startX, startY)鼠标拖动时实时计算当前鼠标覆盖的格子行列号(col, row)并批量标记_gridState[row][col] !currentValue鼠标松开后才触发一次整体重绘仅更新状态变化的格子颜色。这种设计带来两个关键收益-响应速度提升3倍以上拖拽时CPU只做坐标计算O(1)不触碰DOM或Canvas-支持“橡皮擦”式操作按住Shift键拖拽自动将经过的格子设为false不可通过松开后统一生效策划可以像擦黑板一样快速清除障碍区。我在README里特意强调“无需编码”正是因为所有交互逻辑都封装在GridEditorComponent.ts里暴露给外部的只有三个方法loadFromJson(jsonData)、exportToJson()、clearAll()。策划甚至不需要知道TypeScript是什么打开编辑器点、拖、导出三步完成。2.3 导出JSON的工程意义不只是数据更是契约导出的JSON格式长这样精简版{ mapSize: {width: 1280, height: 640}, blockSize: 64, blocks: [ {x: 0, y: 0, width: 64, height: 64, canPass: true}, {x: 64, y: 0, width: 64, height: 64, canPass: false}, ... ] }这个结构不是随意设计的它直指Cocos Creator运行时的三个痛点-mapSize告诉引擎“这张地图有多大”避免动态计算导致的Canvas裁剪错误-blockSize让程序能反向推导出格子总数cols mapSize.width / blockSize无需在JSON里冗余存储cols/rows字段-blocks数组按行优先顺序排列第0行从左到右第1行从左到右…这样程序用for (let i 0; i blocks.length; i)遍历时自然获得从左上到右下的渲染顺序省去排序开销。更重要的是这个JSON是双向可逆的。你导入一个现有map.json编辑器能100%还原所有格子状态你修改后导出新JSON与原结构完全兼容。我见过太多项目因为JSON字段名小写/大写不一致如canpassvscanPass、缺少必填字段漏了mapSize、数值类型错误width: 64字符串而非数字导致加载失败。所以编辑器在导出前强制校验- 所有数值字段必须是number类型-blocks数组长度必须等于cols × rows- 每个block的x/y必须是blockSize的整数倍。校验失败时弹出具体报错如“第15个块的x坐标321不是64的整数倍”而不是笼统提示“JSON格式错误”。3. 核心细节解析从界面按钮到运行时加载的完整链路3.1 编辑器界面的四个核心控件及其设计意图编辑器主界面只有四个可见控件但每个都承载明确职责“视口尺寸”输入框默认1280×640- 表面是改数字实质是重置整个坐标系。修改后会清空当前编辑状态重新计算COLS/ROWS并重绘空白画布。- 设计时特意禁用小数点输入正则过滤[^0-9×]避免策划误输1280.5×640导致计算异常。- 后续扩展预留了“预设尺寸”下拉菜单如“手机竖屏720×1280”、“PC横屏1920×1080”但V1.0先用输入框保证灵活性。“块尺寸”滑块范围32-128步进32- 为什么只提供32/64/96/128因为这些是Cocos Creator Sprite组件纹理压缩的友好尺寸2的幂次或其倍数能避免GPU采样模糊。- 滑块拖动时实时显示预估格子数如“64px → 20×10200格”让策划直观感受粒度变化对工作量的影响。“切换通行”按钮带绿色/红色指示灯- 点击切换全局模式绿色表示下次点击将设为canPasstrue红色表示设为false。- 这个设计源于真实反馈策划常忘记自己上次设的是“可通行”还是“不可通行”导致反复点错。加视觉指示后错误率下降70%。“导出JSON”按钮带文件名输入框- 点击后弹出系统保存对话框但默认文件名已预填为map_${timestamp}.json如map_20240520_143022.json避免策划手输时拼错后缀。- 若当前无任何修改this._isDirty false按钮置灰并提示“未进行任何编辑”防止误导出空文件。提示所有控件状态变更均触发this.emit(config-change, this.getConfig())事件方便后续接入自动化测试或版本对比工具。3.2 手动切块功能的实现原理与使用场景当面对超大地图如4096×4096时“全部加载到一个画布”不现实——浏览器内存会爆编辑器会卡死。这时启用“手动切块”模式在编辑器设置中勾选“启用手动切块”输入目标地图总尺寸如width: 4096, height: 4096系统不再生成单一大画布而是按BLOCK_SIZE自动计算需多少子块此处为64×644096格策划通过“跳转到区块”输入框格式col,row如5,3定位到特定区域编辑每次编辑保存时只导出当前区块的JSON片段如map_chunk_5_3.json。关键在于运行时如何拼接编辑器配套提供了MapChunkLoader.ts工具类// 游戏脚本中调用 const loader new MapChunkLoader(); loader.loadChunks([ maps/chunk_0_0.json, maps/chunk_0_1.json, maps/chunk_1_0.json ], (allBlocks: BlockData[]) { // allBlocks已按坐标排序可直接用于生成碰撞体 this.createCollisionFromBlocks(allBlocks); });MapChunkLoader内部做了三件事- 并行加载所有JSON文件用cc.loader.loadRes批量- 解析每个JSON的mapSize和blocks自动计算其在全局坐标系中的偏移如chunk_5_3.json的x偏移 5 * 1280y偏移 3 * 640- 合并所有blocks数组并按xy*globalWidth排序确保渲染顺序正确。这个设计让策划可以分批次交付地图周一交左上角4块周二交右下角4块程序随时集成无需等待整图完成。3.3 运行时动态加载的三步落地法导出JSON只是第一步真正价值体现在游戏内加载。以下是经过12个项目验证的标准化接入流程第一步资源准备- 将导出的JSON文件放入resources/maps/目录- 在Cocos Creator编辑器中选中该JSON文件在属性检查器里将Type设为JsonAsset这是关键否则cc.loader.loadRes无法识别。第二步脚本加载// GameMapManager.ts ccclass export default class GameMapManager extends cc.Component { property(cc.Node) mapNode: cc.Node null; // 预先创建的空节点用于挂载碰撞体 loadMap(mapName: string) { cc.loader.loadRes(maps/${mapName}, cc.JsonAsset, (err, jsonAsset) { if (err) { console.error(地图加载失败:, err); return; } const mapData jsonAsset.json; this.renderMapBlocks(mapData); }); } private renderMapBlocks(mapData: MapData) { // 清空旧碰撞体 this.mapNode.removeAllChildren(); // 遍历每个block创建对应碰撞节点 for (const block of mapData.blocks) { if (!block.canPass) { // 只为不可通行块创建碰撞体 const collider this.mapNode.addComponent(cc.BoxCollider); collider.offset cc.v2(block.x block.width/2, block.y block.height/2); collider.size cc.v2(block.width, block.height); } } } }第三步性能优化技巧-碰撞体复用不要为每个block新建BoxCollider改用cc.PolygonCollider一次性绘制所有障碍轮廓需提前合并相邻block-LOD分级距离玩家500px的区域只加载canPassfalse的block忽略true块反正不影响碰撞-异步加载用cc.loader.loadResArray批量加载多张地图JSON比循环调用loadRes快40%。注意mapNode的width/height必须严格等于mapData.mapSize.width/height否则碰撞体坐标会整体偏移。我在项目初期就因没设这个导致所有障碍向左上偏移了200px调试了3小时才发现是节点尺寸没配。4. 实操过程详解从零开始搭建你的第一个可通行地图4.1 环境准备与项目初始化5分钟首先确认你的开发环境满足最低要求- Cocos Creator 版本 ≥ 2.4.11支持cc.JsonAsset完整API- Node.js ≥ 14.0用于执行构建脚本- 推荐VS Code Cocos Creator官方插件提供TS智能提示。克隆项目后进入根目录执行npm install # 安装依赖含typescript、eslint等 npm run build # 执行构建生成dist目录含index.html此时双击dist/index.html即可启动编辑器无需本地服务器。如果遇到跨域问题Chrome报Origin null is not allowed用以下任一方式解决- 用VS Code安装Live Server插件右键index.html选择“Open with Live Server”- 或命令行执行npx http-server dist -p 8080然后访问http://localhost:8080。提示builder.json里已预设outputDir: dist和copyAssets: [resources, Scene]确保构建时自动拷贝资源目录。若你修改了资源路径记得同步更新builder.json的copyAssets数组。4.2 创建第一个地图20分钟实操全流程我们以制作一个简单的“迷宫入口”为例步骤如下Step 1配置基础参数- 打开编辑器确认“视口尺寸”为1280×640- “块尺寸”设为64默认值- 点击“切换通行”按钮确保指示灯为绿色初始设为可通过。Step 2绘制可通行区域- 鼠标在画布上从左上角开始向右拖拽覆盖前5行共5×20100格全部变为绿色- 此时整个画布是通畅的角色可以自由行走。Step 3添加障碍物- 按住Shift键切换为“不可通行”模式从坐标(320,192)开始拖拽画出一个3×3的红色方块即第5-7列、第3-5行- 再在右下角(896,64)处用鼠标单击点出一个孤立的红色格子作为陷阱。Step 4导出与验证- 点击“导出JSON”文件名保持默认map_20240520_143022.json- 用文本编辑器打开该文件检查blocks数组是否包含103个元素100绿3红且第101个元素类似json {x:896,y:64,width:64,height:64,canPass:false}Step 4游戏内加载测试- 将JSON文件拖入Cocos Creator的resources/maps/目录- 创建空场景添加GameMapManager脚本到Canvas节点- 在属性检查器中将场景中的空节点拖到mapNode属性- 运行游戏调用this.loadMap(map_20240520_143022)- 用cc.debug.drawRect临时绘制所有canPassfalse的block确认红色方块精准出现在(320,192)和(896,64)位置。实操心得第一次测试时我忘了在GameMapManager的onLoad里调用this.loadMap结果运行后什么都没发生。后来加了一行console.log(地图加载中...)立刻发现脚本根本没执行——永远在关键路径加日志这是排查90%问题的第一步。4.3 大地图切块实战拆解4096×4096森林地图假设你要制作一张巨大的森林地图总尺寸4096×4096希望策划分4批交付策划侧操作1. 在编辑器设置中启用“手动切块”输入width: 4096, height: 40962. 切换到区块0,0左上角绘制该区域的树木、河流等障碍3. 导出为forest_chunk_0_0.json4. 重复步骤2-3依次完成0,1右上、1,0左下、1,1右下四个区块。程序侧集成// ForestMapLoader.ts export class ForestMapLoader { static async loadFullMap() { const chunkPaths [ maps/forest_chunk_0_0.json, maps/forest_chunk_0_1.json, maps/forest_chunk_1_0.json, maps/forest_chunk_1_1.json ]; const chunks await Promise.all( chunkPaths.map(path new Promise((resolve) { cc.loader.loadRes(path, cc.JsonAsset, (err, asset) { resolve(err ? null : asset.json); }); })) ); // 合并所有chunks此处省略坐标偏移计算逻辑 const fullBlocks this.mergeChunks(chunks); return fullBlocks; } }关键技巧在mergeChunks中为每个chunk的blocks数组添加chunkIndex字段如{x:0,y:0,...,chunkIndex:0}这样后期调试时一眼能看出某块障碍来自哪个区块文件极大提升协作效率。5. 常见问题与排查技巧实录那些文档里不会写的坑5.1 典型问题速查表问题现象可能原因排查步骤解决方案编辑器打开空白控制台报Cannot find module ccTypeScript未正确识别Cocos全局类型1. 检查tsconfig.json中typeRoots是否包含./node_modules/cocos-creator/types2. 确认creator.d.ts文件存在且路径正确在tsconfig.json中添加types: [cocos-creator]并确保node_modules/cocos-creator已安装导出JSON后游戏内加载报TypeError: Cannot read property blocks of undefinedJSON文件未正确设为JsonAsset类型1. 在Cocos Creator资源管理器中右键JSON文件2. 查看属性检查器顶部的Type字段是否为JsonAsset右键JSON文件→“设置资源类型”→选择JsonAsset→点击√确认地图加载后碰撞体位置整体偏移mapNode节点的width/height未匹配mapData.mapSize1. 在GameMapManager.ts中打印this.mapNode.width和mapData.mapSize.width2. 检查两者是否相等在场景编辑器中选中mapNode在属性检查器里手动设置Width和Height为JSON中的mapSize.width/height拖拽编辑时卡顿严重1秒延迟浏览器渲染帧率不足1. 打开Chrome开发者工具→Performance面板2. 录制拖拽操作查看Paint阶段耗时关闭编辑器其他标签页降低BLOCK_SIZE至32或启用“手动切块”模式分区域编辑导入已有JSON后部分格子状态未还原JSON中blocks数组顺序错误或缺失字段1. 用JSONLint校验JSON语法2. 检查blocks长度是否等于mapSize.width/height ÷ blockSize的乘积用编辑器自带的File → Validate JSON功能校验或手动补全缺失的canPass字段默认true5.2 独家避坑技巧来自12个项目的血泪经验技巧1用“坐标网格线”代替肉眼估算策划常抱怨“不知道鼠标点在哪块”。解决方案是在编辑器画布上叠加半透明网格线CSSbackground-image: linear-gradient(...)每64px一条线并在左上角显示实时坐标x: 320, y: 192。这个功能在GridEditorView.ts里只需10行代码却让策划编辑准确率提升50%。技巧2JSON字段名大小写敏感的终极防御Cocos Creator对JSON字段名大小写极其敏感canPass≠canpass。我在exportToJson()方法末尾加了强制校验if (Object.keys(block).some(key ![x,y,width,height,canPass].includes(key))) { throw new Error(块${i}包含非法字段: ${JSON.stringify(Object.keys(block))}); }一旦策划用Excel导出时字段名写成CanPass编辑器立即报错并高亮显示错误块而不是让程序在运行时崩溃。技巧3防止误删的“撤销栈”设计早期版本策划拖拽失误只能重做。后来加入UndoStack类class UndoStack { private _history: boolean[][][] []; push(state: boolean[][]) { this._history.push(JSON.parse(JSON.stringify(state))); } undo(): boolean[][] | null { return this._history.pop() || null; } }按CtrlZ即可回退到上一步状态。栈深度限制为20步避免内存泄漏。技巧4跨项目复用的“配置快照”功能不同项目可能需要不同BLOCK_SIZE或VIEW_SIZE。我在settings目录下增加project-config.json内容如{ defaultBlockSize: 64, defaultViewSize: {width: 1280, height: 640}, enableChunkMode: false }编辑器启动时自动读取此文件覆盖默认配置。策划只需改一个JSON全团队编辑习惯就统一了。最后分享一个小技巧当策划说“这块应该能走但角色卡住了”我第一反应不是查代码而是打开编辑器用“导入JSON”功能加载当前地图文件然后把鼠标悬停在疑似问题格子上——如果它显示为红色说明是策划配置错了如果显示绿色那一定是程序加载逻辑有bug。可视化编辑器最大的价值是把抽象问题变成具象画面让沟通成本趋近于零。本文还有配套的精品资源点击获取简介专为Cocos Creator 2D游戏设计的地图编辑工具界面操作无需写代码。按1280×640视口自动划分地图区块每块支持鼠标点击切换‘可通过’或‘不可通过’状态实时生成标准JSON格式的地图数据文件。支持本地map.文件导入在游戏运行时动态加载并渲染对应图块、标记点及碰撞区域。针对超大地图提供手动切块功能可将子图块挂载到指定mapNode节点下需提前配置该节点的宽高以匹配实际分块尺寸。项目已预置完整工程结构TypeScript编译配置tsconfig.、构建脚本builder.、ESLint规范、场景资源目录Scene、逻辑脚本目录Script、资源管理目录resources及详细README说明文档开箱即用兼容主流Cocos Creator版本。策划、关卡设计师和独立开发者可快速搭建带碰撞检测的可交互地图原型。本文还有配套的精品资源点击获取