Blog ブログ
ウラガワを知るという事
皆様こんにちは。
プログラマの島鼻と申します。
今回は、Unityの見えにくい部分を書いてみたいと思います。
皆さんは一度こんなエラーにぶつかった事は無いでしょうか?
error CS0103: The name `Hoge’ does not exist in the current context
私がこのエラーが発生した時は「Plugins」フォルダに入れたソースのクラス定義が通常の「Assets」フォルダのソースから見つからないというものでした。
以下がソースです。一見問題無さそうです。
※今回は説明のため実装は割愛
using UnityEngine;
class Hoge : MonoBehaviour
{
/// <summary>
/// Start this instance.
/// </summary>
void Start()
{
}
/// <summary>
/// Update this instance.
/// </summary>
void Update()
{
}
}
UnityのC#のソースファイルがどのようにコンパイルされ、どのようにモジュール化されるのかが分かれば実は単純な理由でした。
Unityのソースのコンパイル順は以下です。
- Assetsフォルダ内のランタイムスクリプト、とPluginsフォルダ内のランタイムスクリプト。
- Assets/EditorとPlugins/Editorフォルダ内のエディタのスクリプト。
- Editorフォルダの中にないすべての他のスクリプト。
- 残りのすべてのスクリプト(すなわち、Editorというフォルダ内にあるもの)。
1.の中でもPluginsフォルダが先にコンパイルされます。
また、Pluginsフォルダ内のソースと、Assetsフォルダ内のソースは別のモジュールにされ、後者が、前者を参照する形でリンクされます。
別モジュールと言うのがミソです。
次に考えなければならないのが、C#の構文です。通常、以下のように「public」等とアクセス修飾子を記述しなければ、暗黙的に「private」になります。こちらはC++も同じですね。
/// <summary>
/// Am I enough.
/// </summary>
/// <returns><c>true</c> Yes, I am enough. <c>false</c> No. I am not enough.</returns>
public bool amIEnough()
{
// TODO:Why I am not enough? Do it. Do it. Do it.
return false;
}
続いてクラス定義にもアクセス修飾子がある事を思い出してみましょう。
Unityはデフォルトでは、下記のソースを生成します。
using UnityEngine;
using System.Collections;
public class Hoge : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
}
クラス定義を「private」にするとはどういうことが起きるのでしょうか?
/// <summary>
/// I am private class. What Happened?
/// </summary>
class Hoge : MonoBehaviour {
}
他のモジュールから参照出来ないという事が発生します。
error CS0103: The name `Hoge’ does not exist in the current context
今回はPluginsフォルダのクラスのアクセス修飾子が間違っており、発生しました。
このように、バグを修正するには「ウラガワ」を知っておく事が重要になります。
コンパイル順やモジュールがどのように作成されるのか分からなければ、もしかしたら、直せなかったかもしれません。
「ソース書き直したら何故か直った」となった場合、またいつ同じミスをしてしまうか分かりません。きちんと原因を突き止めて、解決しておく事がその後の運用に大変役立ちます。逆にAssetsフォルダから参照されないように作成するなども設計として考えられます。
以上、いかがでしょうか?
ウラガワまで知って、生産性の良いプログラムを心がけたいです。