本日は Unity の小ネタ枠です。
Unityでアセットから参照したテクスチャをDestroyすると権限エラーが発生する問題の対処です。
前回記事
本記事は以下の前回記事の続きです。
bluebirdofoz.hatenablog.com
アセットから参照したテクスチャをDestroyすると権限エラーが発生する
前回記事のスクリプトを以下のように修正し、コンポーネントが無効化されたときテクスチャデータを Destroy で破棄する処理を追加しました。
・TextureRawImageTest.cs
using UnityEngine; using UnityEngine.UI; public class TextureRawImageTest : MonoBehaviour { [SerializeField] private Texture2D assetTexture; [SerializeField] private RawImage targetImage; void OnEnable() { targetImage.texture = assetTexture; } private void OnDisable() { Destroy(targetImage.texture); } }
このスクリプトを使ってシーンを再生し、オブジェクトを無効化すると以下の権限エラーが発生します。
Destroying assets is not permitted to avoid data loss. If you really want to remove an asset use DestroyImmediate (theObject, true);
本エラーはアセット内のデータ削除が許可されていないため、発生するエラーです。
本サンプルシーンではテクスチャの参照を Assets フォルダ内のテクスチャを直接参照しており、アセット内のデータの削除を避けるため、削除がキャンセルされました。
エラーメッセージにある通り、削除を強制的に実施したいときは DestroyImmediate (theObject, true); を利用すれば削除可能です。
ただし、Assets フォルダ内のデータが削除されるため、シーンの復旧が困難になる可能性があることに注意が必要です。
Assetsフォルダ内のデータ削除を回避しながらDestroyを行う
Assetsフォルダ内のデータ削除を回避しながらDestroyを行いたい場合は、一旦テクスチャデータをコピーしてコピーインスタンスの参照を RawImage に渡しておきます。
テクスチャデータのコピーには Graphics.CopyTexture が利用可能です。
docs.unity3d.com
以下の通り、サンプルコードを修正しました。
Assets フォルダのテクスチャを参考にコピーデータを作成し、そのコピーデータを削除するため、問題なく Destroy が実行できます。
・TextureRawImageTest.cs
using UnityEngine; using UnityEngine.UI; public class TextureRawImageTest : MonoBehaviour { [SerializeField] private Texture2D assetTexture; [SerializeField] private RawImage targetImage; void OnEnable() { Texture2D copyTexture = new Texture2D( assetTexture.width, assetTexture.height, assetTexture.format, assetTexture.mipmapCount, false); Graphics.CopyTexture(assetTexture, copyTexture); targetImage.texture = copyTexture; } private void OnDisable() { Destroy(targetImage.texture); Debug.Log("Destroy Success !!"); } }