「Unity」2DTileMap —— 能在運行中切換某位置的瓦片圖片的規(guī)則瓦片(二)

大家好,這里是秋野
先疊個甲
我自己是零零散散自學的Unity和C#,只是出于興趣編寫了這個東西。
代碼內(nèi)容里面大概率出現(xiàn)各種不規(guī)范和弱智寫法
如果發(fā)現(xiàn)
?。?!可以盡情的指出,罵也無所謂?。。?/span>
(如果要罵,還是罵輕一點吧)
而且寫這個專欄也是為自己理清楚自己做這個東西的邏輯
接下來就是正題了

四·功能實現(xiàn)(二)——魔改RuleTile
如小標題所說的
我們在這里需要魔改RuleTile
為什么需要魔改,那么具體這里有兩個原因
第一個原因
我們看看之前寫的代碼里面有一段是用于生成在BaseLayer的Tile
基本邏輯就是根據(jù)底下的RuleTile的sprite去生成一個Tile放上去
那么這里就會出現(xiàn)一個問題
每次刷新都要去生成要給新的Tile給覆蓋上去
當我們「畫」地圖的數(shù)量很多的時候
在BaseLayer的Tilemap組件里面就會出現(xiàn)一堆Tile

就,很不優(yōu)雅
第二個原因
我們需要有那么個東西去保存我們用來切換的Sprite或者Tile
雖說RuleTile本身儲存每個規(guī)則的Sprite的方式就是用一個Sprite[]來存儲的
但每次需要根據(jù)Sprite來獲取規(guī)則,就得遍歷兩邊來確認
一遍規(guī)則列表,一遍Sprite列表
還是突出一個,不優(yōu)雅
那么我們就得出來兩個需求了
「復用Tile,避免每次都要生成一個Tile浪費資源」
「優(yōu)化獲取規(guī)則的方法,方便以后切換Tile的步驟」
那么首先是復用Tile
既然要避免每次都生成一個新的出來
那就直接在editor界面的時候就預先制作好每個Tile
最簡單的方法就是直接將分割好的Sprite拖到TilePalette里面
他讓你選擇的路徑就是保存Tile的路徑
那么我們就可以直接用程序直接在這路徑去找對應的Tile使用了
但是,這樣還是很麻煩很不優(yōu)雅
所以咱們要開始「魔改」RuleTile了
首先創(chuàng)建一個腳本文件
using UnityEngine;
using UnityEngine.Tilemaps;
public class RuleTilePuls : RuleTile
{
?//Tile列表
?public Tile[] Tiles;
}
就很簡單的在RuleTile的基礎上加了一個Tile數(shù)組
選中我們的Ruletile


將代碼換成我們自己寫的Ruletile
即可看到我們的Tile數(shù)組出來了

但是這個只是解決了保存已有的Tile
沒法精確的找到這個Tile的索引值
除非每次找個Tile都去foreach一下
也很不優(yōu)雅
所以咱把Sprite的name作為key,索引值作為value用字典去快速找到咱們需要的tile
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
public class RuleTilePuls : RuleTile
{
? ?//Tile列表
? ?public List<Tile> Tiles;
? ?/// <summary>
? ?/// 獲取字典
? ?/// </summary>
? ?/// <returns></returns>
? ?public Dictionary<string, int> GetDic()
? ?{
? ? ? ?Dictionary<string, int> neighbors = new Dictionary<string, int>();
? ? ? ?for (int i = 0; i < this.Tiles.Count; i++)
? ? ? ?{
? ? ? ? ? ?neighbors.Add(this.Tiles[i].name, i);
? ? ? ?}
? ? ? ?return neighbors;
? ?}
}
然后咱們把之前生成好的Tile全放到這個Tile數(shù)組內(nèi)

這樣是可以做到了咱們的第一個需求
「復用Tile,避免每次都要生成一個Tile浪費資源」
但是咱們還沒能完成第二個需求
「優(yōu)化獲取規(guī)則的方法,方便以后切換Tile的步驟」
那么我們需要保存Tile的同時保存他對應的規(guī)則
如果看過前一篇那個快速制作RuleTile的文章的話

會知道Unity保存規(guī)則的方法是用一個字典去保存
那我們是也要去保存他的字典嗎?
當然不用
我們只需要保存一個索引值即可
就是RuleTile.m_TilingRules的索引值
因為一個TilingRule里面也就只會保存一個規(guī)則
那么保存他的索引值自然也就保存跟他對應規(guī)則的相關(guān)Sprite
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
using System;
public class RuleTilePuls : RuleTile
{
? ?//平鋪單元列表
? ?public List<TilingUnit> TilingUnits;
? ?/// <summary>
? ?/// 獲取字典
? ?/// </summary>
? ?/// <returns></returns>
? ?public Dictionary<string, Vector2Int> GetDic()
? ?{
? ? ? ?Dictionary<string, Vector2Int> neighbors = new Dictionary<string, Vector2Int>();
? ? ? ?for (int i = 0; i < this.m_TilingRules.Count; i++)
? ? ? ?{
? ? ? ? ? ?for (int j = 0; j < this.m_TilingRules[i].m_Sprites.Length; j++)
? ? ? ? ? ?{
? ? ? ? ? ? ? ?neighbors.Add(this.m_TilingRules[i].m_Sprites[j].name, new Vector2Int(i, j));
? ? ? ? ? ?}
? ? ? ?}
? ? ? ?return neighbors;
? ?}
? ?//平鋪單元
?[System.Serializable]
? ?public class TilingUnit
? ?{
? ? ? ?public List<Tile> Tiles;
? ?}
}
用一個類去打包這兩個數(shù)據(jù)
如果我們以后需要添加其他東西也能直接在這個類中添加

雖說這東西是寫好了
但是要往里填數(shù)據(jù)的時候就麻煩了
需要根據(jù)下面的TilingRules來一個一個添加和填寫
這就又很不優(yōu)雅了
既然咱們可以搞快速的制作一個RuleTile
自然就可以快速填入這個列表是不
避免篇幅過長就單獨一個專欄了
↓↓↓↓

假設我們這里已經(jīng)搞定好TilingRules的寫入
剩下的就是需要修改獲取Tile的邏輯了
只需修改之前的UpdateAroundTileAtBaseTiles即可
/// <summary>
? ?/// 刷新周圍八格與自己位置的Tile
? ?/// </summary>
? ?/// <param name="pos">位置</param>
? ?private void UpdateAroundTileAtBaseTiles(Vector3Int pos)
? ?{
? ? ? ?Vector2Int index;
? ? ? ?foreach (Vector3Int tilePos in GetAllAroundTilePositionList(pos))
? ? ? ?{
? ? ? ? ? ?//判斷ruleLayer是否為空,避免出現(xiàn)報錯
? ? ? ? ? ?if (ruleLayer.GetSprite(tilePos) == null)
? ? ? ? ? ?{
? ? ? ? ? ? ? ?baseLayer.SetTile(tilePos, null);
? ? ? ? ? ?}
? ? ? ? ? ?else
? ? ? ? ? ?{ ?
? ? ? ? ? ? ? ?index = neighbors[ruleLayer.GetSprite(tilePos).name];
? ? ? ? ? ? ? ?baseLayer.SetTile(tilePos, ruleTiles.TilingUnits[index.x].Tiles[index.y]);
? ? ? ? ? ?}
? ? ? ? ? ?
? ? ? ?}
? ?}
經(jīng)過測試是可以正常運行的
那么我就不再發(fā)一次測試的動圖了
也省一點流量
接下來的下一篇就是實踐切換Tile的功能了
如果感興趣或者獲得了幫助
請求來個一鍵三連(話說專欄能一鍵三連嗎?)
如果內(nèi)容有誤或者建議也歡迎指出?