2016年7月8日金曜日

C#クロージャのUnity3Dにおけるコストについて

前回に引き続きクロージャです.

クロージャを実現するために, コンパイラは裏側でクラスを作成します.
もしスマートフォン向けのアプリケーションを開発しているのならば,
これだけでも高いコストを支払っています.

かなり強引な例ですが, 以下のようなコードの場合を考えます.
Destroyボタンを押してから, Unloadボタンを押してもテクスチャは解放されません.
Clearボタンを押してから, Unloadボタンを押すことで解放されます.
クラスはどこかから参照されているかぎり, ガーベージコレクタによって削除されません.
明らかにLoaderの実装に欠点がありますが,
texture変数は, コード上ではスコープから外れて参照が切れているように見えてしまっている、
ことも問題です.
public class Loader : MonoBehaviour
{
    private UnityEngine.Events.UnityAction onLoadFinish_;
    private ResourceRequest request_;

    public void load(string path, UnityEngine.Events.UnityAction onLoadFinish)
    {
        request_ = Resources.LoadAsync(path);
        onLoadFinish_ = onLoadFinish;
    }

    public void clear()
    {
        onLoadFinish_ = null;
        request_ = null;
    }

    void Update()
    {
        if(null != request_){
            if(request_.isDone){
                if(null != onLoadFinish_){
                    onLoadFinish_(request_.asset);
                }
                request_ = null;
            }
        }
    }
}

public class Scene : MonoBehaviour
{
    public Loader loader_;

    public UnityEngine.UI.Button buttonDestroy_;
    public UnityEngine.UI.Button buttonClear_;
    public UnityEngine.UI.Button buttonUnload_;

    public GameObject prefab_;
    private GameObject instance_;

    void Start()
    {
        buttonDestroy_.onClick.AddListener(onClickDestroy);
        buttonClear_.onClick.AddListener(onClickClear);
        buttonUnload_.onClick.AddListener(onClickUnload);

        Texture2D texture;
        loader_.load(
            "image",
            (UnityEngine.Object obj)=>
            {
                GameObject.Destroy(instance_);
                instance_ = GameObject.Instantiate(prefab_);
                instance_.transform.SetParent(transform);
                texture = obj as Texture2D;
                instance_.GetComponent().texture = texture;
            });
    }

    void onClickDestroy()
    {
        GameObject.Destroy(instance_);
        instance_ = null;
    }
 
    void onClickClear()
    {
        loader_.clear();
    }

    void onClickUnload()
    {
        Resources.UnloadUnusedAssets();
    }
}

人それぞれですが, 私はこのコードが読みやすいとは思えません.
コールバックを多用する設計も奇麗とは思えません.
特にJavascript界隈でコールバック地獄と聞きますが,
わざわざ地獄に足を突っ込む必要はないと思います.
達人に刃物を持たせる分には一向に構わないのですが.


追記.
少し修正, でも強引過ぎるか.

0 件のコメント:

コメントを投稿