対象読者
- UnityのWebGLでのビルド後の動作が変わって困っている人
記事の内容
- 特定の条件下でインターフェースのデフォルト実装を使用したとき、WebGLビルド後の動作が変わる原因の解説をする
実際に問題が発生するコード
public interface IHogeValue
{
int Value { get; set; }
int GetValue()
{
return Value;
}
}
public class HogeParent : IHogeValue
{
public int Value { get; set; }
public HogeParent()
{
Value = 1;
}
}
public class HogeChild : HogeParent, IHogeValue
{
new public int Value { get; set; }
public HogeChild()
{
Value = 2;
}
}
public class Logger : MonoBehaviour
{
void Start()
{
IHogeValue child = new HogeChild();
Debug.Log(child.GetValue());
Debug.Log(((IHogeValue)child).GetValue());
Debug.Log(child.Value);
Debug.Log(((IHogeValue)child).Value);
Debug.Log(((HogeParent)child).Value);
}
}
実際に動作させると、Loggerの出力結果は、Windowsビルドの場合は「1 1 2 1 1」、WebGLビルドの場合は「2 1 2 1 1」となります。
2つのビルドにおいて、変数「child」が保持している変数の値は同じで、プロパティから呼び出しても動作は同じだけど、関数からプロパティを呼びだしときだけ、動作が変わります。
予防法
- 曖昧なプロパティを作らない
今回の場合だと、「HogeChildのValue」が曖昧なプロパティです。
このプロパティを消すと、WindowsとWebGLで動作は同じになります。
問題が発生する条件
- 子クラスと親クラスに付けられたinterfaceは異なるが、同名の関数を持っている
- 継承しているinterfaceにデフォルト実装がされている
- 同名関数内で同名プロパティを使った処理をする
- 子クラスから、その関数を呼び出す
まとめ
- WebGLビルドをするなら、インターフェースのデフォルト実装の使い方に注意
- 普通の書き方をすれば、殆ど問題は発生しない
- 特殊な書き方をしても、「曖昧な関数やプロパティ」を消す事で問題が解消できる場合がある