AssetBundleをビルドした後にAddComponentしてあるC#を書き換えたらどうなるのか
AssetBundleとは……?
AssetBundleについてのよくある誤解として「C#のScriptも動的に追加できる」というものがありますが、できません。
なぜかというと、今時はどのプラットフォームにビルドするのでもScripting BackendにはIL2CPPを要求されます。これはC#を事前コンパイル(AOT)でC++にしてビルドするというもので、後から動的にコードを追加することはできません。[1]
……というこのあたりの説明をしていると虚無に飲み込まれる可能性が高いので、
「AssetBundleって何???」みたいな人には、とりあえずランタイムロードできるprefabと説明するのが手っ取り早い気がします。prefabにScriptそのものは追加できないけど、AddComponentしておいたScriptはそのままついてくるよねそれと一緒だよ、みたいな。
実験
前書きが長くなりましたが
「
AssetBundleをビルドした後に、そのAssetBundleにAddComponentされているScriptを書き換えた上で、AssetBundleを再ビルドしないで読み込んだらどうなるのか?」
がこの記事の実験です。
before
Cubeを回転させるだけのScriptを用意します。
using UnityEngine;
public class MoveCube : MonoBehaviour
{
public float Speed = 0f;
private Transform _ts;
private void Start()
{
_ts = this.transform;
}
private void Update()
{
// Speedに従って回転する
_ts.Rotate(Vector3.up, Time.deltaTime * Speed);
}
}
これをAddしたcubeを3つ並べたものをAssetBundleにします。
InspectorからSpeedをそれぞれ40/80/120に設定してあります。

こんな感じのAssetBundle
これを動的に読み込むとこんな感じで再生されます。

before
after
さっそくScriptを書き換えてみます。このとき、元のクラスで使っていたSpeedという変数はそのまま使っています。
using UnityEngine;
public class MoveCube : MonoBehaviour
{
public float Speed = 0f;
private Transform _ts;
private void Start()
{
_ts = this.transform;
}
private void Update()
{
- // Speedに従って回転する
- _ts.Rotate(Vector3.up, Time.deltaTime * Speed);
+ // 自分じゃなくて(0,0,0)を中心に回る
+ _ts.RotateAround(Vector3.zero, Vector3.forward, Time.deltaTime * Speed);
}
}
で、Editorのコンパイルが終わったあたりでおもむろに実行してみます。

after
この通り、AssetBundleは再ビルドしていないですが、プロジェクトのScriptを書き換えたことによって動きが変わりました。Speedの値はそのまま使われています。
まとめ
知ってた。
頭ではわかってるんですが、このあたりのことを人に説明するのどうしようかなー、という思考を整理するための実験でした。
ランタイムロードできるprefabってそれっぽくて便利だな……今度からはこれで説明しておこうと思います。
いや違くね? って言う「ヤツ」は「ワカってる」って「コト」だからなぁ〜?
「プレゼント」してやるぜ〜AssetBundle周りの面倒をよぉ〜!!!!!![2]
おしまい。
参考
Discussion