Unity學習筆記#11 : 制作簡單Scriptable Tile

 

上次說了一些使用Unity TileMap的方法,今次的學習筆記會説一下如何製作Scriptable Tile;Scriptable Tile是也一個蠻好玩的東西,可以讓開發者利用程序定義Tile的內容,例如在RPG常用的自動化地形生成 (Terrain Tile);

這次筆記會先説説簡單的Scriptable Tile,讓大家理解一下基本的做法;下次才説Terrain Tile那些比較複雜的Scriptable Tile。

學習重點:

  • 什麼是Scriptable Tile?
  • Scriptable tile 能做什麼?
  • 如何製作簡單的Scriptable Tile: ColorTile
  • 其他Scriptable Tile例子

什麼是Scriptable Tile?

其實Scriptable Tile並不是什麼特別的東西,當我們把Sprite拉到Tile Palette時,其實已經使用了Unity提供的Scriptable Tile來生成一個TileAsset了;那個Scriptable Tile就是Tile Class;

Tile class 相關文檔 :https://docs.unity3d.com/Manual/Tilemap-ScriptableTiles-Tile.html
Tile Asset相關文檔 : https://docs.unity3d.com/Manual/Tilemap-TileAsset.html

當默認的Tile不能滿足我們的需要時,就可以創造我們自己的Scriptable Tile來處理。

另外,說說Scriptable Tile的本質

  • Scriptable Tile是繼承TileBase來製作;
  • 由於TileBase繼承於ScriptableObject,所以其實Scriptable Tile也是Scriptable Object; 所以不會直接使用Scriptable Tile,而是使用Scriptable Tile生成出來的TileAsset;
    所以Scriptable Tile不會像MonoBehaviour那樣,可定義Update, Start 那些邏輯;

Scriptable Tile, Tile Asset,Tile Palette 和 TileMap之間的關係

Screen Shot 2018-01-18 at 10.18.40 AM

雖然有點複雜,但是大概是通過TilePalette拿出Tile,然後放在Tilemap繪畫;
TileMap便紀錄了不同位置(Grid)用了什麼TileAsset,而TileMapRender也用該TileAsset的資料來進行Render;

 

Scriptable Tile可作什麼?

自定義的Scriptable Tile可以做到以下的東西:

  • 定義顯示的圖像,顏色,Transform(Rotation),例如Color Tile
  • 定義碰撞的做法: 沒有碰撞 / Grid為碰撞範圍 / Sprite為碰撞範圍
  • 動態Tile,例如移動的小花或瀑布
  • 動態改變Tile的內容;例如Terrain Tile,Rule Tile

如何製作簡單的Scriptable Tile: ColorTile

ColorTile是一個讓TileMap的Grid填上顏色的Tile, 主要參數是Sprite和指定的顏色;

效果如下:Screen Shot 2018-01-18 at 10.18.40 AM
製作重點

  • ScriptableTile需要繼承TileBase類
  • 需要定義GetTileData, 而且需要定義tileData.sprite, 否則不能正常顯示相關的Tile
  • 需要定義CreateTile方法來創建Tile的Asset
  • 因為ScriptableTile是不會直接使用,TileMap只使用TileAsset來進行處理;

製作步驟

  1. 建立ColorTile類
  2. 定義以下properties :
       public Color customColor; // 這樣可以讓TileAsset定義顏色;
    
        public Sprite customSprite; // TilePalette, TileMap用來顯示
    
        public bool isPassable = true; // 指定是否能通過
  3. 定義GetTileData
    這是其中一個必要實現的方法,告訢TileMap要用畫什麼Sprite和配什麼顏色;   
public override void GetTileData(Vector3Int location, 
             ITilemap tileMap, ref TileData tileData)
{
  tileData.color = customColor;           // the main input 
  tileData.sprite = customSprite;         // mandatory to show something 
  tileData.colliderType = isPassable ? Tile.ColliderType.None : Tile.ColliderType.Grid;
  tileData.flags = TileFlags.LockAll; 
}
 

定義CreateTile

這是另一個必要實現的方法,令ScriptableTile可以生成Tile Assets

 #if UNITY_EDITOR
[MenuItem("Assets/Create/Custom Tile/Color Tile")]
public static void CreateTile()
{
   string path = EditorUtility.SaveFilePanelInProject("Save ColorTile",
                         "ColorTile", "asset", "Save ColorTile", "Assets");
   if (path == "") {
       return;
   }
 
   AssetDatabase.CreateAsset(ScriptableObject.CreateInstance<ColorTile>(), path);
}
#endif

 

  1. 建立使用的Sprite;
      使用 Asset -> Create -> Sprites -> Square 來創建;成功後,會生成一張4×4的Texture;
    如果CellSize是1, 把相關Sprite的PPU(Pixel Per Unit)改為4;
    如果CellSize不是1,需要把PPU改為其他數值,公式: ppu = 4 / cellSize
  1. 使用 Asset -> Create -> Custom Tile -> Color Tile來創建新的tileAsset
  2. 設定TileAsset
      把剛剛生成的Sprite拉到TileAsset設定中;
    設定顏色和passable
  1. 最後把tileAsset拉到tilePalette就完成; 
  2. 選定目標的Tile Layer和用Dropper選擇該Tile, 就能畫在tileMap上了。


其他Scriptable Tiles

Transform Tile

Tile把Sprite進行不同的Rotation;

Screen Shot 2018-01-18 at 10.28.04 AM
參考代碼:


 public override void GetTileData(Vector3Int location, ITilemap tileMap, ref TileData tileData)
 {
     // Set the Matrix4x4 using Quaternion and SetTRS 
     Quaternion quaternion = Quaternion.Euler(0f, 0f, -rotateDegree);    // ken: rotate using Z-axis
                                                                         // degree > 0: clockwise 
 
     Matrix4x4 mat = Matrix4x4.identity;
     mat.SetTRS(Vector3.zero, quaternion, Vector3.one);
 
     // Define the new Matrix
     tileData.transform = mat;
 
 
     // Define the sprite, the image to be rotated
     tileData.sprite = customSprite;                // manadatory to show something 
 
     // using default Setting 
     tileData.color = color;                
     tileData.colliderType = Tile.ColliderType.None;
 
     // Confirm the change 
     tileData.flags = TileFlags.LockAll;        // need to make the tiled filled with a color 
 }

備註: 把Rotation轉為Quaternion,並放在Matrix4x4,然後在tileData.transform進行設定;

 

Animation Tile

動態Tile:利用多張Sprite (Frame Animation技術)令Tile出現動畫,例如瀑布,被風吹的花草;

Screen Shot 2018-01-18 at 10.30.47 AM

參考代碼:

 public override bool GetTileAnimationData(Vector3Int location, ITilemap tileMap, ref TileAnimationData tileAnimationData)
 {
     if (spriteList.Length == 0) {
         return false;
     }
 
     tileAnimationData.animatedSprites = spriteList;
     tileAnimationData.animationSpeed = animationSpeed;
     tileAnimationData.animationStartTime = startTime;
     return true;
 }


備註:

  • 定義用reference傳入的tileAnimationData,並設定主要數值:
    • animatedSprites : 動畫frame sprite
    • animationSpeed : 播放速度,(fps – 一秒出多少個frame)
    • animationStartTime: 開始播放的時間

Random Tile

隨機Tile:當繪畫tile時,隨機使用多張Sprite其中一張,例子:花,草

Screen Shot 2018-01-18 at 10.32.00 AM.png
參考代碼:

 public override void GetTileData(Vector3Int location, ITilemap tileMap, ref TileData tileData)
 {
     //tileData.transform = tileMap.GetTransformMatrix (location);    // Matrix4x4.identity;
     int index = Random.Range (0, spriteList.Length);
     Sprite selectedTile = spriteList [index];
 
     tileData.sprite = selectedTile;
 
     tileData.flags = TileFlags.LockAll;
 }
 

備註: 利用 Random.Range,就能找出一個隨機數!

文章相關代碼

https://github.com/tklee1975/UnityTileExample

延伸閱讀

 

發表留言

在 WordPress.com 建立免費網站或網誌.

向上 ↑