2013年5月12日日曜日

Unity Tips #55 InitializeOnLoadなどの良くある間違い


Unify Community に InitializeOnLoadなどの良くある間違いに関する Tips があったので紹介したい:


http://wiki.unity3d.com/index.php/Tip_of_the_day
Feb 2013

Tip #55 InitializeOnLoad & Resources.Load gotcha’s

InitializeOnLoadおよびResources.Loadの良くある間違い


最近、 Unity 4 エディタで初めはバグだとおもった内容に遭遇した。 InitializeOnLoad からの Resources.Load メソッドの使用が絡んでいる。

例えば次のサンプルコードをみてみる:
namespace CBX.CoreProjectCode
{
    using UnityEditor;
 
    using UnityEngine;
 
    [InitializeOnLoad]
    public class EditorInitialization
    {
        static EditorInitialization()
        {
            LoadData(); // Resourceフォルダのtest.txt ファイルを参照することに失敗する
        }     
 
        private static void LoadData()
        {
            // データのロードを試みる
            var data = Resources.Load("test", typeof(TextAsset)) as TextAsset;
            if (data == null)
            {
                Debug.LogWarning("データは見つかりませんでした");
                return;
            }
 
            Debug.Log(data.text);
        }
    }
}

Unity がスクリプトをコンパイルした後、InitializeOnLoad によりマークされたクラスの static なコンストラクタを実行する。しかし、この時点で私は Unity がまだ Resources フォルダの中にあるアセットについては識別できていないとみている。クラスのコンストラクタが Resources.Load メソッドをコールしたとき、 text.txt リソースファイルを呼ぶことに失敗し、コンソールに警告メッセージを表示する。

この時点でやることが可能であることのひとつはプロジェクトウィンドウの Assets フォルダを右クリックして Reimport を選択することだ。 Unity は Assets を再インポートして、 InitializeOnLoad によりマークされたクラスをコールする。しかし、今回は Resources.Load は正しく test.txt の読み込みを行い、内容を Unity コンソールウィンドウに表示する。

この問題の回避方法のひとつは、 EditorApplication.Update コールバックをフックしてそこから LoadData メソッドへのコールを行うことだ。以下にそのサンプルを示す:

namespace CBX.CoreProjectCode
{
    using UnityEditor;
 
    using UnityEngine;
 
    [InitializeOnLoad]
    public class EditorInitialization
    {
        private static bool ranOnce;
 
        static EditorInitialization()
        {
            EditorApplication.update += RunCallbacks;
        }
 
        private static void RunCallbacks()
        {
            if (!ranOnce)
            {
                // Resource フォルダの test.txt がみつかり内容が
                // 表示される
                LoadData();
                ranOnce = true;
 
                // returnするかはあなた次第
                return;
            }
 
            // 必要な処理があれば記述
        }
 
        private static void LoadData()
        {
            var data = Resources.Load("test", typeof(TextAsset)) as TextAsset;
            if (data == null)
            {
                Debug.LogWarning("データはみつかりませんでした");
                return;
            }
 
            Debug.Log(data.text);
        }
    }
}
これがバグであるかどうかは認識していないが、Unity にバグレポートの提出は行っている。リンクは次のとおりだ。
-----------------

先人の知恵は重要。Unity プログラミングに活かそうぜ!

0 件のコメント:

コメントを投稿

ブックマークに追加

このエントリーをはてなブックマークに追加

自己紹介

自分の写真
Unity3D公式マニュアル翻訳やってる人がスマホ(iPhone, Android)のゲーム開発しています。気軽に面白く初心者が遊べる内容がモットー。Blogでは開発情報をひたすら、Twitterではゲーム作成の過程で参考にしている情報を中心につぶやきます

ページビューの合計

過去7日間の人気投稿