🧊

AssetBundleをビルドした後にAddComponentしてあるC#を書き換えたらどうなるのか

2021/11/11に公開

AssetBundleとは……?

AssetBundleについてのよくある誤解として「C#Scriptも動的に追加できる」というものがありますが、できません。

なぜかというと、今時はどのプラットフォームにビルドするのでもScripting BackendにはIL2CPPを要求されます。これはC#を事前コンパイル(AOT)でC++にしてビルドするというもので、後から動的にコードを追加することはできません。[1]

……というこのあたりの説明をしていると虚無に飲み込まれる可能性が高いので、
AssetBundleって何???」みたいな人には、とりあえずランタイムロードできるprefabと説明するのが手っ取り早い気がします。prefabScriptそのものは追加できないけど、AddComponentしておいたScriptはそのままついてくるよねそれと一緒だよ、みたいな。

実験

前書きが長くなりましたが

AssetBundleをビルドした後に、そのAssetBundleにAddComponentされているScriptを書き換えた上で、AssetBundleを再ビルドしないで読み込んだらどうなるのか?」

がこの記事の実験です。

before

Cubeを回転させるだけのScriptを用意します。

MoveCube
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]

おしまい。

参考

https://docs.unity3d.com/ja/2021.2/Manual/ScriptingRestrictions.html
https://qiita.com/4_mio_11/items/d5d7b4e879a8341595cd

脚注
  1. RoslynとかLuaとかDLLとかで、100%できないわけではありませんが、黒魔術です。
    「不可能ではない」と「実際にやる」の間には深い深い溝があって、でも人は飛び降りてしまうんだなこれが…… ↩︎

  2. 俺様への批判は許さんとかそういうんじゃなくて実際よくわかってないのでAssetBundle完全に理解したマンに丸投げしてぇ〜! ↩︎

Discussion