
Unity上コードで2D Textureを切り出してみた
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
概要
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を指定して取れます。
 
 
以上です。











