SRPG游戏开发(六)第三章 绘制地图 - 三 创建自己的SrpgTile
返回目录
第三章 绘制地图
一 导入素材
http://blog.csdn.net/darkrabbit/article/details/79168225
二 绘制一张简单地图
http://blog.csdn.net/darkrabbit/article/details/79177935
三 创建自己的SrpgTile
这一节中,我们选择继承Rule Tile的方式来创建自己的SrpgTile。
1 创建SrpgTile.cs
经过我们之前的分析,我们知道地形需要一个类型,还有数据。我这里只添加两个,一个地形类型,一个是回避率,同样你可以按你的需求添加所需数据。
地形类型枚举事例TerrainType.cs:
using System;namespace DR.Book.SRPG_Dev.Maps {/// <summary>/// 地形类型/// </summary>[Serializable]public enum TerrainType : byte{/// <summary>/// 平地/// </summary>Plain,/// <summary>/// 湿地(沼泽)/// </summary>[Obsolete("Game Not Used", true)]Swamp,/// <summary>/// 道路/// </summary>Road,} }
FE4中共26种,使用18种;这里创建的共3种,使用2种。其中可以看到湿地(Swamp)项目有个Obsolete Attribute,这是一个小技巧,意思是这个地形虽然定义了,但不使用它,在编辑器的Inspector面板中也不会显示。如果以后的版本你需要使用,只要去除Obsolete就可以了。
创建好地形后,就该创建Tile文件了。
完成后的文件SrpgTile.cs:
using System; using UnityEngine;namespace DR.Book.SRPG_Dev.Maps {[Serializable][CreateAssetMenu(fileName = "New SRPG Tile.asset", menuName = "SRPG/Tile")]public class SrpgTile : RuleTile{private TerrainType m_TerrainType = TerrainType.Plain;private int m_AvoidRate = 0;/// <summary>/// 地形类型/// </summary>public TerrainType terrainType{get { return m_TerrainType; }set { m_TerrainType = value; }}/// <summary>/// 回避率/// </summary>public int avoidRate{get { return m_AvoidRate; }set { m_AvoidRate = value; }}} }
不要忘记添加“CreateAssetMenu”,否则我们在Create菜单中看不到它。
这样我们就我们完成了SrpgTile.cs的编写,如果你要创建它,可以选择菜单Assets/Create/SRPG/Tile。
2 创建SrpgTileEditor.cs
创建完SrpgTile后,发现Rule Tile的Inspector面板被我们破坏了。这就需要我们也继承它的Editor文件,而且还要在Inspector面板中添加我们的数据。
请注意原始的Rule Tile Editor类使用了internal class,我们需要将它改成public class。在Tile/Script下创建一个新的文件夹,重命名为Editor。在这个文件夹下创建SrpgTileEditor.cs。
完成后的文件SrpgTileEditor.cs:
using UnityEditor;namespace DR.Book.SRPG_Dev.Maps {[CustomEditor(typeof(SrpgTile))][CanEditMultipleObjects]public class SrpgTileEditor : RuleTileEditor{public SrpgTile srpgTile { get { return target as SrpgTile; } }public override void OnInspectorGUI(){// 渲染新增的数据EditorGUI.BeginChangeCheck();srpgTile.terrainType = (TerrainType)EditorGUILayout.EnumPopup("Terrain Type", srpgTile.terrainType);srpgTile.avoidRate = EditorGUILayout.IntSlider("Avoid Rate", srpgTile.avoidRate, -100, 100);if (EditorGUI.EndChangeCheck()){EditorUtility.SetDirty(target);}// 渲染RuleTile的内容EditorGUILayout.Space();base.OnInspectorGUI();}} }
这样,Inspector面板就显示了我们要的数据了。
3 测试SrpgTile
首先,在Tile/Asset中创建2个SrpgTile,并设置他们。
图 3 - 13设置SrpgTile
- Default Sprite:Tiling Rules中没有合适的贴图时使用;
- Default Collider:Collider类型,项目不需要;
- Tiling Rules:Tile规则。
- Rule:设置贴图旋转或镜像;
- Collider:Collider类型,项目不需要;
- Output:Tile类型,有普通(Single),随机(Random),动画(Animation)三个选项。
Tiling Rules中右侧有绿色箭头和红色叉子的地方是设置规则的地方,根据是否有邻居瓦片(Neighbor Tile),选择其中的贴图,绿色代表有邻居,红色代表没邻居,空白代表不关心。
设置好之后,我们将其拖入Tile Palette中。选择它开始绘制地图。但你会发现两种Tile之间并没有很好的衔接,如图。
图 3 - 14没有衔接的Tile
这可不是我们想要的,我们希望不同地形之间也能很好的衔接。而产生的原因是因为Rule Tile判断邻居的方法限定了只有相同Tile才是邻居。这需要我们在Rule Tile中找到相应的位置,并加以修改,让它认为只要有Tile就是邻居。
4 修改RuleTile.cs与SrpgTileEditor.cs
我们已经知道原因了,我们添加一个bool变量来控制邻居的类型是否为其本身,这样可以有选择的使用我们的Tile。
4.1 修改RuleTile.cs
打开RuleTile.cs,添加变量与检测方法:
/// <summary>/// true: 只要旁边有Tile就使用Rule;/// false: 旁边只有是自己时才使用Rule。/// </summary>public bool m_CheckAnyTile = false;/// <summary>/// 我们添加的方法,判断是不是采用规则(Rule)/// true: 使用/// false: 不使用/// </summary>/// <param name="neighbor"></param>/// <param name="neighborTile"></param>/// <returns></returns>private bool NeighborMatches(TilingRule.Neighbor neighbor, TileBase neighborTile){switch (neighbor){/// 不关心,直接采用规则case TilingRule.Neighbor.DontCare:return true;/// 绿色箭头,/// 如果检测所有Tile,返回neighbor是不是不为null,/// 否则返回neighbor是不是自己case TilingRule.Neighbor.This:return m_CheckAnyTile ? neighborTile != null : neighborTile == this;/// 红色叉子,/// 如果检测所有Tile,返回neighbor是不是为null,/// 否则返回neighbor是不是不为自己case TilingRule.Neighbor.NotThis:return m_CheckAnyTile ? neighborTile == null : neighborTile != this;default:return false;}}
有了方法后,我们要找到使用它的地方,在RuleTile中有两处。
修改前代码:
public bool RuleMatches(TilingRule rule, Vector3Int position, ITilemap tilemap, int angle){for (int y = -1; y <= 1; y++){for (int x = -1; x <= 1; x++){if (x != 0 || y != 0){Vector3Int offset = new Vector3Int(x, y, 0);Vector3Int rotated = GetRotatedPos(offset, angle);int index = GetIndexOfOffset(rotated);TileBase tile = tilemap.GetTile(position + offset);if (rule.m_Neighbors[index] == TilingRule.Neighbor.This && tile != this || rule.m_Neighbors[index] == TilingRule.Neighbor.NotThis && tile == this){return false;} }}}return true;}
public bool RuleMatches(TilingRule rule, Vector3Int position, ITilemap tilemap, bool mirrorX, bool mirrorY){for (int y = -1; y <= 1; y++){for (int x = -1; x <= 1; x++){if (x != 0 || y != 0){Vector3Int offset = new Vector3Int(x, y, 0);Vector3Int mirrored = GetMirroredPos(offset, mirrorX, mirrorY);int index = GetIndexOfOffset(mirrored);TileBase tile = tilemap.GetTile(position + offset);if (rule.m_Neighbors[index] == TilingRule.Neighbor.This && tile != this || rule.m_Neighbors[index] == TilingRule.Neighbor.NotThis && tile == this){return false;}}}}return true;}
修改后的代码:
public bool RuleMatches(TilingRule rule, Vector3Int position, ITilemap tilemap, int angle){for (int y = -1; y <= 1; y++){for (int x = -1; x <= 1; x++){if (x != 0 || y != 0){Vector3Int offset = new Vector3Int(x, y, 0);Vector3Int rotated = GetRotatedPos(offset, angle);int index = GetIndexOfOffset(rotated);TileBase tile = tilemap.GetTile(position + offset);// 修改的地方if (!NeighborMatches(rule.m_Neighbors[index], tile)){return false;}}}}return true;}
public bool RuleMatches(TilingRule rule, Vector3Int position, ITilemap tilemap, bool mirrorX, bool mirrorY){for (int y = -1; y <= 1; y++){for (int x = -1; x <= 1; x++){if (x != 0 || y != 0){Vector3Int offset = new Vector3Int(x, y, 0);Vector3Int mirrored = GetMirroredPos(offset, mirrorX, mirrorY);int index = GetIndexOfOffset(mirrored);TileBase tile = tilemap.GetTile(position + offset);// 修改的地方if (!NeighborMatches(rule.m_Neighbors[index], tile)){return false;}}}}return true;}
4.2 修改SrpgTileEditor.cs
Editor的修改相对简单,只要加一条bool变量的就可以了。
修改后的代码:
public override void OnInspectorGUI(){// 渲染新增的数据EditorGUI.BeginChangeCheck();srpgTile.terrainType = (TerrainType)EditorGUILayout.EnumPopup("Terrain Type", srpgTile.terrainType);srpgTile.avoidRate = EditorGUILayout.IntSlider("Avoid Rate", srpgTile.avoidRate, -100, 100);// 添加的bool变量srpgTile.m_CheckAnyTile = EditorGUILayout.Toggle("Check Any Tile", srpgTile.m_CheckAnyTile);if (EditorGUI.EndChangeCheck()){EditorUtility.SetDirty(target);}// 渲染RuleTile的内容EditorGUILayout.Space();base.OnInspectorGUI();}
5 再次测试SrpgTile
首先在Inspector面板中把
2个Plain的SrpgTile的Check Any Tile打勾。图 3 - 15 Check Any Tile
再次在Scene面板中绘制地图,是不是好多了。
图 3 - 16不再衔接不正常
6 Tile之间的细线
你可能会发现,有的Tile之间会有一条细线,这是Unity渲染模式造成的,并不是Tile的问题。无论什么贴图,在同一张贴图中的两个Sprite如果是紧贴着的,有一定几率会出现这个问题,有两种解决办法,一种就是在每个Sprite边缘加一个像素,还一种是加入图集(加入图集时,Unity会自动在边缘补像素,查看图集可以看到),说道图集时再来详细说。
SRPG游戏开发(六)第三章 绘制地图 - 三 创建自己的SrpgTile相关推荐
- SRPG游戏开发(七)第三章 绘制地图 - 四 初步完善地图编辑器(Map Graph)
返回目录 第三章 绘制地图 四 初步完善地图编辑器(Map Graph) 到目前为止我们可以开心的绘制我们的地图了,但有不少小问题.一直开心忘我的绘制地图,却不知道地图已经绘制了多大,还要 ...
- SRPG游戏开发(五)第三章 绘制地图 - 二 绘制一张简单地图
返回目录 第三章 绘制地图 一 导入素材 点击进入 二 绘制一张简单地图 这一节我们来看如何绘制一张地图. 1 新建Grid与Tilemap 在Hierarchy面板中,点击Create/2D ...
- SRPG游戏开发(四)第三章 绘制地图 - 一 导入素材
返回目录 第三章 绘制地图 这一章我们来创建自己的Tile,绘制我们的地图,然后显示我们的角色.如果你已经对Tilemap非常的熟悉,可以跳过本章.
- SRPG游戏开发(六十四)间章 第十一点五章 总结(Summary)
返回<SRPG游戏开发>导航 间章 第十一点五章 总结(Summary) 这一章,是对第十章与第十一章的一个补充性质的文章. 文章目录 间章 第十一点五章 总结(Summary) 一 说明 ...
- 《SRPG游戏开发》导航(2019.03.04更新)
<SRPG游戏开发>导航 第一章到第五章并没有使用Markdown,且经过CSDN几次改版和取消目录,这几章排版有些怪怪的. 2019.03.04 第十一章(十 - 十二) ,间章 第十一 ...
- SRPG游戏开发(六十三)第十一章 地图动作与地图事件 - 十二 完善地图信息与测试(Perfect MapEventInfo and Testing)
返回<SRPG游戏开发>导航 第十一章 地图动作与地图事件(Map Action and Map Event) 我们已经有了剧本,而且可以运行剧本,但我们还缺少对地图的操作控制. 我们这一 ...
- SRPG游戏开发(六十)第十一章 地图动作与地图事件 - 九 触发事件与切换回合(Trigger Events and Change Turn)
返回<SRPG游戏开发>导航 第十一章 地图动作与地图事件(Map Action and Map Event) 我们已经有了剧本,而且可以运行剧本,但我们还缺少对地图的操作控制. 我们这一 ...
- SRPG游戏开发(六十一)第十一章 地图动作与地图事件 - 十 NPC操作(NPC Control)
返回<SRPG游戏开发>导航 第十一章 地图动作与地图事件(Map Action and Map Event) 我们已经有了剧本,而且可以运行剧本,但我们还缺少对地图的操作控制. 我们这一 ...
- OCulus Rift 游戏开发六原则
本文章由cartzhang编写,转载请注明出处. 所有权利保留. 文章链接:http://blog.csdn.net/cartzhang/article/details/46685477 作者:car ...
最新文章
- KPCR:CPU控制区(Processor Control Region)
- 下巴痤疮的治疗方法有哪些?
- 此情应是长相守 你若无心我便休
- 计算机基础- -操作系统环境
- java接收二进制数据_java-从套接字读取二进制数据
- php调用restful接口_分享一个PHP调用RestFul接口的函数
- CentOs6.6安装Python3
- 最优化 | 二次规划的基础知识理论 | 例题讲解
- 网上车市通过聆讯:营收单一,上半年减员15%,徐翀持股80%
- 电视剧《乡村爱情2》之演员表(ZT)
- 随机池化(Stochastic Pooling)
- ARGIS利用计算器对属性表数据进行编号
- http/2与http/1的区别
- Mantis -- linux
- Java学习打卡第八天——[Collection终结之HashMap,Collections的简介和使用]
- 详解i++和++i,通俗易懂
- 故障申报系统php源码,seay源代码全自动在线审计系统,PHP源代码缺陷自动审计平台-在线工具...
- android开发和手游开发工具,developer盘点Android开发者必备十大开发工具
- 虚拟化之Proxmox VE安装教程
- Power BI常见问题篇1:无法打开文档
热门文章
- 线性代数 --- 投影Projection 六(向量在子空间上的投影)
- Coursera| Mathematics for maching learning | Linear Algebra
- python面对对象建立自己的电子宠物的编码_一种基于Kinect技术的电子宠物的制作方法...
- 个人开发android如何赚钱
- CSS水平垂直居中常见方法总结
- 弘辽科技:淘宝劳动节活动什么时候开始呢?商家要准备什么呢?
- 一款超级简单的后台管理系统模板
- java的反射和反编译机制介绍
- 95后女数据分析师的千字经验,都在这了
- Geant4教程学习(一)