0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Resources.LoadのBestPracticesの検証(Term,Unloadを理解する

Last updated at Posted at 2019-02-17

[Resources.LoadのBestPracticesの検証(3,複数回読んでみる]
(https://qiita.com/tessa256/items/ae5cc80aa0a5d6306858)
の続き


Resources.LoadしたUnityEngine.Objectを
Resources.UnLoadの引数にしただけではダメということが分かってきたので
ここで改めてUnityAPIドキュメントを見てみる。

・参照しているAssetのみに対して呼び出すことができる。
・解放されたオブジェクトは無効になる。

ということでResources.Loadされたものに対して対で呼ばれるメソッドではないようなので
今回は下記ソースコードで解放のテストをしてみる。

ResourcesLoaderByType.cs
using System;
using System.Collections;
using UnityEngine;

public class ResourcesLoaderByType : MonoBehaviour
{
	public enum LoadType
	{
		Order = 0,

		Sprite
	};

	// LoadTypeの定義順に合わせること
	private static readonly System.Type[] _LoadTypeTable = new System.Type[]
	{
		typeof(UnityEngine.Object),

		typeof(Sprite)
	};

	public event Action<UnityEngine.Object> OnLoadComplete;

	[SerializeField, Header("ResourcesLoadのPathを指定")]
	private string ResourcesLoadPath;

	[SerializeField, Header("指定したAssetの型を指定")]
	private LoadType AssetType;

	private UnityEngine.Object Asset;

	private IEnumerator Start()
	{
		var request = Resources.LoadAsync(ResourcesLoadPath, _LoadTypeTable[(int)AssetType]);

		yield return request;

		Asset = request.asset;

		if (OnLoadComplete != null)
			OnLoadComplete(Asset);
	}

	private void OnDestroy()
	{
		if (Asset == null)
			return;

		switch (AssetType)
		{
			case LoadType.Order:
				Resources.UnloadAsset(Asset);
				break;
			case LoadType.Sprite:
				{
					var targetObject = Asset as Sprite;

					if (targetObject == null)
						break;

					Resources.UnloadAsset(targetObject.texture);
					Resources.UnloadAsset(targetObject);
				}
				break;
		}
	}
}

ざっくり解説すると
1.ResourcesLoadPathに指定されたAssetをAssetTypeで指定された形式で非同期で読み込む。
2.読み込みが完了するとOnLoadCompleteが呼ばれる。
3.解放するときは指定したTypeにダウンキャストして参照しているAssetに対してUnloadAssetする。
挙動を見るために今回はSpriteのみ

注意:
・ロード中に破棄されたらどうする?等の考慮がなかったり(そもそもResourceRequestにキャンセルがない。
・ダウンキャストそのものは失敗の危険性がある。

これで例のごとくProfilerでMemory項目を見ていく。

Load時
load.png
UnLoad時
unload.png

あらかじめProfileでLoadで増えたものをメモっておきそれを
Unloadで呼ぶ分には動いてる模様。

ただ
Resources.LoadがType指定で何を読み込んでいるのかを見るためには
・Profileによる目視
・Resources.Loadのソースの中身を見る
ぐらいしか思いつかないのでAssetの中でも
・画像
・サウンド
・Prtefab、component
を必要になったらLoadして必要なくなったら解放する
という用途で使用するにはかなりリスキーだと感じる。
なによりUnloadが複数呼ばないといけないのは気持ち悪い
特にPrefab、componentはspriteやaudio sourceがついている状態で
できているのが普通なのでくっついているAssetをUnloadなんてやろうものなら
解放対象のAssetを検索して消すなんてコードを足すなんてやるべきでないしやりたくない。

このメソッドの用途はここは公式の推奨に従い
・最善の方法は使わないこと

使うとしても
・ScriptableObjectを使った設定ファイルの読み込み
・最小限必要かつ変更のないデータベースのダンプの読み込み
ぐらいだろう。

ただプラットホームごとにResourcesフォルダのAssetの扱いが
ちがうのでそこはしっかり調べてから使った方がよいだろう
(マルチプラットフォームだったら使わない方がよい

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?