Unity : get_dataPath can only be called ~ エラーの解決

Unityのロゴ。

Unity を使った開発で次のようなエラーが起きました。

get_dataPath can only be called from the main thread. Constructors and field initializers will be executed from the loading thread when loading a scene. Don't use this function in the constructor or field initializers, instead move initialization code to the Awake or Start function.

ここではこの問題を解決する1つの方法について紹介します。 原因と解決の方法は必ずしもここで紹介するものでない可能性があります。

問題の原因と発見

上記のようなエラーが発生するとき、合わせて次のようなエラーが発生しているはずです。

ArgumentException: get_dataPath can only be called from the main thread. Constructors and field initializers will be executed from the loading thread when loading a scene. Don't use this function in the constructor or field initializers, instead move initialization code to the Awake or Start function. ImportWarpMesh..cctor () Rethrow as TypeInitializationException: An exception was thrown by the type initializer for ImportWarpMesh

このエラーは、エラー通知から直接原因となっているスクリプトなどに飛ぶことができないのが厄介です。 ただし、上のようなエラーコードから、

ImportWarpMesh..cctor() などから、該当するスクリプトファイルを検索するなどして検出します。 ここでは、ImportWarpMesh.cs でした。

問題の解決

次のようにフィールドで、Application.dataPath などを参照するとき、このエラーが発生するようです。

string hoge = Application.dataPath + "/hoge/hoge.obj";

この問題を解決するためには Start メソッドなどで初期化するようにします。

void Start()
{
    hoge = Application.dataPath + "/hoge/hoge.obj";
}

問題が発生しやすいタイミング

今回の問題ですが、実はシーン遷移しない状態であればエラーが発生しないため、問題に気が付きにくいです。

例えば、ある正常に動作するシーン A があり、問題のコードがあるシーンを B とします。 シーン B を直接起動するとき、今回の問題は起こりませんが、シーン A からシーン B に遷移しようとすると問題が起こります。

また、シーン B を直接起動し、シーン A に遷移し、再度シーン B に移動するような場合には問題が起こりません。

発覚するパターンが少なく少々厄介な問題ですね。

Reference