Texture2D.GetPixelData()で直接ピクセルデータを書き換えるとアセットも変更されてしまう
Unity 2020.1から Texture2D.GetPixelData()
というAPIが追加されています。
このメソッドを使えば、CPU上にあるテクスチャ色情報を直接参照することができるため、GetPixels()
と比較して、テクスチャ色情報を配列にコピーするコストを下げることができます。
しかし、このAPIを使ってアセットとしてインポートしたTexture2Dを直接書き換えてしまうと、アセットそのものも変更されてしまいます。
実例
Texture2Dを受け取って、ネガポジ変換するコードを書きました。
(画像は先日秋葉原に行った時の写真です)
using UnityEngine; namespace Clay.ImageProcessor { public class NegativeConverter : MonoBehaviour { [SerializeField] private Texture2D inputTexture; public void Start() { var pixels = inputTexture.GetPixelData<Color32>(0); for (var i = 0; i < pixels.Length; i++) { var color = pixels[i]; color.r = (byte)(255 - color.r); color.g = (byte)(255 - color.g); color.b = (byte)(255 - color.b); pixels[i] = color; } // 変更を適応する inputTexture.Apply(); } } }
このコードを実行すると……
なんと、元の画像アセットごとネガポジ変換されてしまいました。 また、このスクリプトを再度実行すると、元の画像に戻りました。
改善方法
- スクリプト内でTexture2DやRenderTextureとして複製し、それらが持つピクセルデータを書き換える
- 一度書き換えてしまった後でも、アセットを右クリックしてReimportすれば元に戻る
- これで直るのは、Unityが書き換えたのは「元の画像ファイルをエンジン内部で読み取って作ったデータ」であって、大元のJPGファイルは変更されていないからです。
まとめ
UnityのAPIには、不意にアセットそのものを破壊してしまうモノが多数あります。注意して開発を進めましょう。