UnityのAssetを名前で取得したかった件

#またアタッチが外れた:rage::rage::rage:

PlayOnMacで昔のRailloadTycoon2をやってるとしばしばPCごと落ちます。
それはまぁ良いです。
さっきは、一緒に立ち上げてたUnityも道連れにして落ちちゃいました。
その影響かアタッチが綺麗さっぱり外れてキレ散らかしそうになりました。
いくら気をつけてても、やっぱりアタッチが外れることがあります。人間だもの。

#何が問題か
例えば、SpriteやPrefabをたくさん作ったら
![ss.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439286/5987b779-5f4c-fc91-863b-2ac168a68497.png)
こんな感じでListでアタッチしていくことがあると思いますが、これをやめたい。
どれを引っ張りだすのかindexで指定するのも治安が良くない気がします。

この辺のアタッチをどうにかすればQoLが上がる気がします。


#書いた

```C#:AutoAssetLoader.cs
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;



#if UNITY_EDITOR

using UnityEditor;

public class AutoAssetLoader<T> where T : UnityEngine.Object
{
    private readonly Dictionary<string, T> _assets = new Dictionary<string, T>();

    private string GetFilter()
    {
        if (typeof(T) == typeof(GameObject)) return "t:Prefab t:GameObject";
        else if (typeof(T) == typeof(Sprite)) return "t:Sprite";
        throw new Exception("とりあえずprefabとspriteのみ対応");
    }
    
    public AutoAssetLoader(string dir)
    {
        var assetPaths = AssetDatabase
            .FindAssets(GetFilter(), new string[] { "Assets/Editor/" + dir } )
            .Select(AssetDatabase.GUIDToAssetPath);

        foreach (var path in assetPaths)
        {
            var asset = AssetDatabase.LoadAssetAtPath<T>(path);
            _assets.Add(asset.name, asset);
        }
    }


    public T Get(string name)
    {
        var f = _assets.TryGetValue(name, out var o);
        return f ? o : null;
    }

    public IEnumerable<string> Names() => _assets.Keys;
}

#else

public class AutoAssetLoader<T> where T : UnityEngine.Object
{
    private readonly AssetBundle _assetBundle;
    private readonly Dictionary<string, T> _assets = new Dictionary<string, T>();

    public AutoAssetLoader(string path)
    {
        _assetBundle = AssetBundle.LoadFromFile("AssetBundleData/" + path);

    }


    public T Get(string name)
    {
        var f = _assets.TryGetValue(name, out var asset);
        if (f) return asset;
        asset = _assetBundle.LoadAsset<T>(name);
        _assets.Add(name, asset);
        return asset;
    }

    public IEnumerable<string> Names() => _assetBundle.GetAllAssetNames().Select(str=>
        {
            var from = str.LastIndexOf("/", StringComparison.Ordinal) + "/".Length;
            var to = str.LastIndexOf(".", StringComparison.Ordinal);
            var len = to < from ? (str.Length - from) : (to - from);
            return str.Substring(from, len);
        });
}


#endif
```
ディレクトリ内のprefabやらspriteやらを全て読み込みます。
AssetDatabaseはUnityEditor名前空間内、つまりビルド時は使えないので、
プリプロセッサディレクティブで切り替えます。

開発時は**Editorフォルダ内にPrefabやSpriteを置きます。**
リリース時はちゃんとAssetBundleを作って
ルートディレクトリ直下のAssetBundleData内に置きます。

UnityProject/
├ Assets/
│└ Editor/
│  ├ Prefabs/
│  └ Sprites/
└ AssetBundleData/


#使い方


```C#:usage.cs
        AutoAssetLoader<GameObject> prefabs = new AutoAssetLoader<GameObject>("Prefabs");
        foreach (var name in prefabs.Names())
        {
            Instantiate(prefabs.Get(name));
        }
        
        
        AutoAssetLoader<Sprite> sprites = new AutoAssetLoader<Sprite>("Sprites");
        image.sprite = sprites.Get("Cat");

```


#追記
2019/9/22
AssetDatabaseがビルド時に使えないのに気づいて、AssetBundleと切り替えるようにしました。