[Unity] AssetBundleNameをアセットのファイルパスから設定する

## AssetBundleNameの設定

UnityEditor上で任意のアセット (Project上のSprite,Audio,Scene...etc) を選択すると
Inspectorの下部にて一つのAssetBundleNameが設定できます。
AssetBundleをBuildする際にAssetBundleNameが同一のアセットがAssetBundleとしてまとめられます。

![assetbundle1.png](https://qiita-image-store.s3.amazonaws.com/0/102664/e28b5521-6c9b-f71f-a9a4-ed44e2f6103c.png)

これは [AssetImporter](http://docs.unity3d.com/ja/current/ScriptReference/AssetImporter.html) を利用することで、Script上からでも設定することが出来ます。

```csharp
AssetImporter importer = AssetImporter.GetAtPath("Assets/Resources/Sprites/Enemy/1.png");
importer.assetBundleName = "sprites/enemy/1.unity3d";
```

上記を利用して、指定したディレクト以下のファイルに対し
自動でAssetBundleNameを設定するエディタ拡張を作ってみます。
(ただし、1アセットに対し、1アセットバンドルを生成する前提)

## コード

```csharp
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.Linq;
using System.IO;

public static class SetAssetBundleName
{
    [MenuItem("Assets/AssetBundle/SetName")]
    public static void SetName()
    {
        string resourcePath = Application.dataPath + "/Resources";
        string projectPath  = Application.dataPath.Replace("Assets", "");

        List<string> paths = Directory.GetFiles(resourcePath, "*.*", SearchOption.AllDirectories)
            .Where(path => !path.EndsWith(".meta"))
            .Select(path => path.Replace(projectPath, ""))
            .ToList();

        foreach (string path in paths)
        {
            AssetImporter importer = AssetImporter.GetAtPath(path);
            var assetBundleName = path.Substring(0, path.LastIndexOf(".")) + ".unity3d";
            importer.assetBundleName = assetBundleName;
        }
    }
}

```

[Directory.GetFiles](https://msdn.microsoft.com/ja-jp/library/system.io.directory.getfiles(v=vs.110).aspx) は指定した条件のファイルパスを返します。
[SearchOption.AllDirectories](https://msdn.microsoft.com/ja-jp/library/ms143448(v=vs.110).aspx) を指定することでサブディレクトリ内のファイルも対象となります。

```
Directory.GetFiles(resourcePath, "*.*", SearchOption.AllDirectories)
```

System.Linqにおける [Where](https://msdn.microsoft.com/ja-jp/library/system.linq.enumerable.where(v=vs.110).aspx) は条件に沿う要素への絞込を行います。
ここでは `.meta` 拡張子のファイルを除外しています。

```
.Where(path => !path.EndsWith(".meta"));
```

System.Linqにおける [Select](https://msdn.microsoft.com/ja-jp/library/system.linq.enumerable.select(v=vs.110).aspx) は各要素に対する処理を行います。
`Directory.GetFiles` で取得されるファイルの絶対パス群に対し
`AssetImporter.GetAtPath` で使用するパスへ置換を行っています。

```
.Select(path => path.Replace(projectPath, ""));
```

`importer.assetBundleName` に `assetBundleName` を代入する前に
現状の拡張子を取り除いた上で、AssetBundleで付けたい拡張子を付けています。

```
var assetBundleName = path.Substring(0, path.LastIndexOf(".")) + ".unity3d";
importer.assetBundleName = assetBundleName;
```

## 使い方
エディタ拡張として生成しているので、 UnityEditor上部の `Assets/AssetBundle/SetName` にて実行できます。

![assetbundle3.png](https://qiita-image-store.s3.amazonaws.com/0/102664/30d29ea8-ce56-0869-870e-9d016ed6562f.png)

ビルド時に漏れを防ぐのであれば、ビルド用のスクリプトで `SetAssetBundleName.SetName()`を呼ぶのが良さそうです。
(もしくはアセットインポートにフックしてAssetBundleName設定する君を作ると良さそう)

また、1アセット1アセットバンドルで無い運用の場合は `string.IsNullOrEmpty(importer.assetBundleName)` で漏れが無いかチェックする君に置き換えるのが良さそうです。

## 実行後

![assetbundle2.png](https://qiita-image-store.s3.amazonaws.com/0/102664/9985edd9-4abb-7502-55eb-66e63e58213b.png)

## 参考
- [Unity5で選択したファイルにアセットバンドルの名前を自動で付ける](https://gist.github.com/marukun700/2c07787b99339045bb64)