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