void Start()
いろんなUnityのサンプルソースを見ていると、
void Start()
と書いてあることがほとんどなんですが、たまに
public void Start()
とも書いてあったりします。publicを省略した場合はprivate扱いのはずなので、これらは違うメソッドです。…でも動く。
こういう時は親クラスを見れば済む話なので、MonoBehaviourをチェック。…ない。Behaviourにもない。ComponentにもObjectにもない。どこにも定義されてない!!どういうこっちゃ??
ということで、正解はと言いますと、
引数なしの"Start"という名前のメソッドであればUnity的にはどっちでもいい
です。
どうやら、Unity内部から呼ばれるメソッドに関しては、public,private関係なく単純に名前解決しているだけのようで、AwakeやUpdateはもちろん、コマンドラインからメソッドを指定する場合も同様な挙動を示します。調べるまでは、MonoBehaviourのvirtualなStart()をオーバーライドしているのかと思ってました(定義されていないのでコード補完されないのも納得)。
でもこれ、Unityが裏技を使っているということではなく、C#の言語仕様(実装仕様?)的に許されておりまして、
public class HogeClass
{
private void HogeMethod()
{
Debug.Log("Hoge!!");
}
}
var instance = new HogeClass();
var method = instance.GetType().GetMethod("HogeMethod", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic);
method.Invoke(instance, null);
という感じにすると、publicでもprivateでも自由に呼び出すことが可能です。
C#怖っ!!
おまけ
ついでに、privateなstaticメソッドはこんな感じで呼べます。
public class HogeClass
{
private static void StaticHogeMethod()
{
Debug.Log("Static Hoge!!");
}
}
var staticMethod = typeof(HogeClass).GetMethod("StaticHogeMethod", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
staticMethod.Invoke(null, null);
privateでもコマンドラインからは呼べてしまうため、同僚がうっかりprivateで書いてしまったメソッドを内部から呼ぶ場合は、本人が直してくれるまではこうして呼びましょう。(実話)