この記事でのバージョン
Unity 2018.4.0f1
はじめに
処理を軽くするために、複数の画像を一つにまとめて使うというのは常套手段です。
UnityではSpriteAtlasを使ってまとめたり、
最初から1つの画像にまとめたものを、Sprite ModeをMultpleにして使う、などの方法があります。
ただ、このように複数の画像をまとめて使うとSpriteのTextureを取得した時に困った事になります。
例えばSpriteのテクスチャのサイズをログで表示してみると、
//レンダラーからSprite取得 Sprite sprite = GetComponent<SpriteRenderer>().sprite; //テクスチャのサイズをログで表示 Debug.Log(sprite.texture.width);
そのSpriteのサイズではなく、元々の大きな画像のサイズが表示されてしまうのです。
実はこの内容の記事は既に書いていて、
その時は任意のSpriteの画素値だけを取得する方法を紹介しました。
そして今回は、任意のSpriteのTextureを取得する方法の紹介です!
なお、記事中の画像は以下のアセットを使っております。
2D Medieval Fantasy Character Pack | 2D Characters | Unity Asset Store |
GetTextureSameSizeAsSprite
さっそくプログラムですが、やり方はいたってシンプル、
Spriteから元の画像上の位置とサイズを取得し、
その範囲の画素値を取得、さらに画素値からテクスチャを生成しているだけです。
//Spriteと同じサイズ(部分)のTextureを取得する private Texture2D GetTextureSameSizeAsSprite(this Sprite sprite){ //Spriteから全体のテクスチャを取得 Texture2D texture = sprite.texture; //スプライトの位置とサイズを取得 int x = (int)sprite.textureRect.x, y = (int)sprite.textureRect.y; int width = (int)sprite.textureRect.width, height = (int)sprite.textureRect.height; //スプライト部分の画素値だけ抜き出す Color[] pixels = texture.GetPixels(x, y, width, height); //画素値を使ってSprite部分だけのテクスチャを作成 Texture2D newTexture = new Texture2D(width, height); newTexture.SetPixels(pixels); newTexture.Apply(); return newTexture; }
これを先ほどと同じ感じで使ってみると、Spriteと同じサイズが取得出来てるのが分かります。
//レンダラーからSprite取得 Sprite sprite = GetComponent<SpriteRenderer>().sprite; //Spriteと同じ部分のTextureのサイズをログで表示 Debug.Log(GetTextureSameSizeAsSprite(sprite).width);
なお画素値を読み込むにはTextureの設定で、Read/Write Enabledを有効にする必要がありますが、
Read/Write Enabledを有効にすると、メモリの使用量が 2 倍になるので、注意が必要です。
ちなみにTexture2DからSpriteを生成したい場合はSprite.Createを使います。
Sprite sprite = Sprite.Create( texture : texture2D, rect : new Rect(0, 0, texture2D.width, texture2D.height), pivot : new Vector2(0.5f, 0.5f) );
拡張メソッド
先ほどのプログラムを必要になる度に書くのは面倒なので、拡張メソッド にすると便利かもしれません。
using UnityEngine; /// <summary> /// Spriteの拡張クラス /// </summary> public static class SpriteExtension{ /// <summary> /// Spriteと同じサイズ(部分)のTextureを取得する /// </summary> public static Texture2D GetTextureSameSizeAsSprite(this Sprite sprite){ //Spriteのサイズとてスクチャのサイズが同じならそのままテクスチャを返す if (Mathf.Approximately(sprite.rect.height, sprite.texture.height)) { return sprite.texture; } //Spriteから全体のテクスチャを取得 Texture2D texture = sprite.texture; //スプライトの位置とサイズを取得 int x = (int)sprite.textureRect.x, y = (int)sprite.textureRect.y; int width = (int)sprite.textureRect.width, height = (int)sprite.textureRect.height; //スプライト部分の画素値だけ抜き出す Color[] pixels = texture.GetPixels(x, y, width, height); //画素値を使ってSprite部分だけのテクスチャを作成 Texture2D newTexture = new Texture2D(width, height); newTexture.SetPixels(pixels); newTexture.Apply(); return newTexture; } }
上記のようなプログラムを用意する事で、
どのSpriteからでも直接GetTextureSameSizeAsSpriteが使えるようになります。
//レンダラーからSprite取得 Sprite sprite = GetComponent<SpriteRenderer>().sprite; //Spriteと同じ部分のTextureのサイズをログで表示 Debug.Log(sprite.GetTextureSameSizeAsSprite().width);