Unity上コードで2D Textureを切り出してみた

Cropping Unity 2D textures

概要

Unityを使う際、ちゃんとしたTextureがある場合Resource.Load()で簡単にロードできますが、ネット上のものを使ったりするとき、DemoにTextureをすぐ使いたいときは、コード上でクロップしなければならないこともよくあると思います。

このブログで2D Textureをクロップする方法をメモしたいと思ういます。

やり方

今回の例は、この麻雀牌の画像を元のものとし、麻雀牌を一つずつ切り出したいです。
画像のGithub Link

 

using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEditor;

public class TextureManager : MonoBehaviour
{
    public Texture2D mahjongTileImage; // 元の画像
    public List<Texture2D> textureList; // クロップした結果

    // ソフト上に確認した各サイズ
    int bgWidth = 273; // 青い背景を含めた牌の幅
    int bgHeight = 217; // 青い背景を含めた牌の高さ
    int tileWidth = 150; // 牌の幅
    int tileHeight = 200; // 牌の高さ
    int leftDummy = 60; // 最初の左から要らない部分
    int bottomDummy = 12; // 最初の下から要らない部分
}

まず、TextureManager : MonoBehaviourというクラスを作って、上記のメンバーを定義します。

 

そして、Unity Editorに、mahjongTileImageに元の映像を指定します。

 

var assetPath = AssetDatabase.GetAssetPath(mahjongTileImage);
var tImporter = AssetImporter.GetAtPath(assetPath) as TextureImporter;
tImporter.textureType = TextureImporterType.Default;

tImporter.isReadable = true;
AssetDatabase.ImportAsset(assetPath);
AssetDatabase.Refresh();

元の映像は.pngで直接コードで編集することはできなそうなので、一度isReadable = trueにし、編集できる形にインポートし直します。

 

textureList = new List<Texture2D>();

int MaxRow = 4; // Suit x 3 rows, Honor x 1 row
int MaxColumn = 10; // 9 + special 5

// 実験なので、空の部分と赤牌無視してTextureを切り出したい
List<int> tilesToIgnore = new List<int>() { 7, 8, 9, 15, 25, 35 }; 

// Tempのリストのリスト、「x = 0, y = 0」は左下で、実際ロードする際は「東」からなので、 その後Textureの並び順は「一萬」からにしたい
List<List<Texture2D>> tempTexListList = new List<List<Texture2D>>();
```     
行、列、無視するブロック、一時使うリストのリストを定義します。    



     

```csharp
// Scan all the tile textures from the tiles image

for (int row = 0; row < MaxRow; row++)
{
    List<Texture2D> tempTexList = new List<Texture2D>();

    for (int column = 0; column < MaxColumn; column++)
    {
        // 無視する部分
        if (tilesToIgnore.Contains(row * 10 + column)) continue;

        // GetPixels(x, y, width, height)
        Color[] pixels = mahjongTileImage.GetPixels(leftDummy + bgWidth * column, bottomDummy + bgHeight * row, tileWidth, tileHeight);
        Texture2D newTex = new Texture2D(tileWidth, tileHeight); ;
        newTex.SetPixels(pixels);
        newTex.Apply();
        tempTexList.Add(newTex);
    }

    tempTexListList.Add(tempTexList);
}


// 下からロードするので、「一萬」を最初のTextureにしたので、行の順番を逆にします
tempTexListList.Reverse();
foreach (var list in tempTexListList)
{
    // メンバー変数としてのリストに保存します
    textureList.AddRange(list);
}

コードをGameObjectにアタッチして、シーンに入れてから実行すると、Texture予想通りキャッシュされてます。

 

 public Texture2D GetTexture(int tileIndex)
{
    // list.ElementAt()を使うため、System.Linqをインポートしてください
    return textureList.ElementAt(tileIndex);
}

実際Textureを使いたい時、Indexを指定して取れます。

 
 

以上です。