【Unity】トラブル対策(個人の備忘録) 【Unity】トラブル対策(個人の備忘録) – みなためラボ

【Unity】トラブル対策(個人の備忘録)


文字サイズ:?? (px)

もくじ

はじめに

みなため

どうも! みなため(@MinatameT)です。

この記事は、Unityのトラブルが発生したときの対策を個人的にメモしたものです。

そのため、他人に読ませる文章ではなく、自分用の簡単な備忘録になっていることをご了承ください。

また、動作環境によってはうまく解決できない場合や、そもそも情報が間違っている可能性もあります。

それでも誰かのお役に立てるかもしれないと思い、公開しました。

キャラクター

以下、私の備忘録です。

作ったばかりのプロジェクトで「Error detecting Visual Studio installations: System.ArgumentNullException: Value cannot be null. Parameter name: input」というエラーが発生する場合

Window > Package Manager
から、「Visual Studio Editor」を「Remove」する。

※「~Code Editor」のほうではないことに注意!

スクリプトをダブルクリックしても、Visual Studio Codeが開かない場合

Window > Package Manager
から、「Visual Studio Code Editor」を最新版にアップデートする。

「Update to ~」というボタンがあるので、それをクリックすればアップデートできる。

CanvasのPanelの子要素の画像(Sprite)が、実行環境(解像度)の違いで崩れて表示されてしまう場合

PanelなどのUI要素は「RectTransform」という特殊なコンポーネントで管理されており、Spriteなどの「非UI要素」はそれに対応していない。

そのため、UI要素の子要素に「非UI要素」を配置すると表示が崩れる原因になる。

UI要素の子要素として画像を配置するためには、ハイアラーキー上を右クリックして UI > Image を使うと良い。

ImageならRectTransformコンポーネントが最初からついており、UI要素に対応できる。

ビルド後に、UIのフォントの色が黒くなる場合

それぞれの黒くなったフォントの、Text (Script) の下の方にあるMaterialを設定する。

種類がたくさんあるが、Noneのすぐ下の「Font Material」にしておけば良い。

コライダーの設定はできているのに、オブジェクトがすり抜ける(貫通する)場合

isTriggerをOFFにしていたり、RigidbodyのCollision Detectionを「Continuous」にしているのにすり抜ける場合は、当たり判定が狭すぎたり、衝突(接触)時間が短すぎる可能性がある。

コライダーの当たり判定を大きくしたり、オブジェクトの移動スピードを下げたりしよう。

親オブジェクトのトリガー判定のみを有効にしたいのに、子オブジェクトのトリガー判定も有効になってしまう場合

トリガーをもつ子オブジェクトにもRigidBodyをアタッチすることで解決する。

詳細は下記のとおり。

親子で「まとめて」トリガー判定される組み合わせ

  • 親オブジェクト:RigidBody、Collider(トリガー)、親のトリガー判定用のスクリプト
  • 子オブジェクト:Collider(トリガー)

この場合、親のトリガー判定用のスクリプトでは、自身のトリガー判定に加えて子オブジェクトのトリガー判定にも反応する。

親は親子で「まとめて」、子は「子のみ」でトリガー判定される組み合わせ

  • 親オブジェクト:RigidBody、Collider(トリガー)、親のトリガー判定用のスクリプト
  • 子オブジェクト:Collider(トリガー)、子のトリガー判定用のスクリプト

この場合、親のトリガー判定用のスクリプトでは、自身のトリガー判定に加えて子オブジェクトのトリガー判定にも反応する。

また、子のトリガー判定用のスクリプトでは、自身のトリガー判定のみに反応する(親のトリガー判定は無視される。)。

親子が「個別に」トリガー判定される組み合わせ

  • 親オブジェクト:RigidBody、Collider(トリガー)、親のトリガー判定用のスクリプト
  • 子オブジェクト:RigidBody、Collider(トリガー)、子のトリガー判定用のスクリプト

この場合、親のトリガー判定用のスクリプトでは、自身のトリガー判定のみに反応する(子のトリガー判定は無視される。)。

また、子のトリガー判定用のスクリプトでは、自身のトリガー判定のみに反応する(親のトリガー判定は無視される。)。

Find関数で取得できないオブジェクトがある場合

階層や対象名を間違えている可能性が高い。

例えば、Canvas/Panel/Text としなければいけないところを、Canvas/Text としているなど。

または、Canvas/Panel/text としているなど、大文字と小文字の違いにも気をつけよう。

※そもそも、ゲームオブジェクト名や階層は開発途中でよく変更されがちなので、Find関数を使うのはあまりおすすめしない。

編集したスクリプトを更新したら、エラー「error CS1513; } expected」が発生した場合

if文が「else if」からスタートしていないかを確認する。

else~を、if文の先頭にすることはできないので注意。

編集したスクリプトを更新したら、エラー「error CS1519: Invalid token ‘;’ in class, record, struct, or interface member declaration」が発生した場合

変数の宣言時に、変数の型(intやGameObjectなど)の指定を忘れている可能性がある。

例えば、次のように修正しよう。

public max_speed;

public float max_speed;

上の階層のオブジェクトのスクリプトが取得できない場合

transform.parent.gameObject; //1つ上の階層のオブジェクト
transform.root.gameObject; //最も上の階層のオブジェクト

これらの使い分けにミスがないかを確認すること。

「Property or indexer ‘GameObject.transform’ cannot be assigned to — it is read only」といったエラーが出る場合

左辺のtransformの後に、.positionや.scaleをつけ忘れていることが原因。

例えばpositionを変更したければ、
~transform = ~;
ではなく
~transform.position = ~;
にすることで解決する。

これは入門レベルのことだが、慣れていてもうっかりミスしやすいと思う。

「Operator ‘+’ is ambiguous on operands of type ‘Vector3’ and ‘Vector2’」といったエラーが出る場合

Vector3型とVector2型の演算が混ざっていることで起きるエラー。

演算をどちらかの型に統一することで、このエラーを回避できる。

例えばベクトルの足し算であれば、
transform.position = transform.position + new Vector2(x, y);
ではなく
transform.position = transform.position + new Vector3(x, y, 0.0f);
とする。

「The type or namespace name ‘Image’ could not be found」といったエラーが出る場合

ImageはUI要素なので、Imageコンポーネントを利用するスクリプトの冒頭の宣言部分で「using UnityEngine.UI;」と記述しておく必要がある。

Instantiateで「cannot convert from object to GameObject」といったエラーが出る場合

変数の型はobjectではなく「Object」にすること。

先頭は大文字。

「error CS0650: Bad array declarator: To declare a managed array the rank specifier precedes the variable’s identifier. To declare a fixed size buffer field, use the fixed keyword before the field type.」といったエラーが出る場合

配列の宣言がミスっている。

変数名ではなく、変数の型に配列マーク([])をつける。

public string name[];

public string[] name;

ゲームオブジェクトを複製した直後から「NULLエラー」が発生するようになった場合

あるスクリプトのFind関数で何かを取得するとき、同名のオブジェクトが(階層問わず)複数存在するとエラーが発生する。

例えば、Canvasという名前のオブジェクトが2つあるのなら、Find関数で取得しないほうのCanvasを「Canvas2」などにリネームすることで解決できる。

ただそもそもFind関数は使わずに、public変数にしてインスペクター上で直接指定したほうが良い。

親オブジェクトをthis.gameObject.transform.positionで瞬間移動させても子オブジェクトが追従しない場合

子オブジェクトがStaticになっているか、子オブジェクトにRigidBodyがついていると、その「コライダーのみ」が親オブジェクトに追従してしまう。

そのため、次のいずれかの方法で解決しよう。

  • Staticであれば、子オブジェクトのStaticのチェックを外す。
  • RigidBodyがついているのであれば「瞬間移動時に子オブジェクトのRigidBodyを一旦OFFにする」スクリプトにする。
  • RigidBodyがついているのであれば、FixedJointコンポーネントを利用する。
  • 「子オブジェクトの絶対座標を親オブジェクトの絶対座標に書き換える」スクリプトにする。

Spatial Blendを3Dに設定している音がおかしな位置(方向)から鳴る場合

鳴らしたい位置に「そのAudio Source(音)をアタッチしているゲームオブジェクト」が存在するのかを確認する。

例えば、あるゲームオブジェクトの子オブジェクトにAudioSource(音)をアタッチしている場合、その子オブジェクトのTransformのPositionが(0, 0, 0)になっていなければ、効果音が再生される位置が親オブジェクトの位置とズレる。

単純なミスだが、意外と忘れがち。

Start関数内で他のスクリプトから呼び出したpublic変数が「NULL扱い」になる場合

呼び出すpublic変数が、本当にNULLの状態(中身がまだ入っていない状態)であることが考えられる。

おそらく、お互いのスクリプトのコードの実行タイミング(順序)が噛み合っていない。

この場合、Start関数内に「Invoke関数」を用意し、1.5秒後や2.0秒後に「public変数呼び出しの専用の関数」を実行することで解決する。

例:Items.csのnumberというpublic変数の値を、別のスクリプトのi_numberというprivate変数に代入したいとき

//int型のi_number変数
int i_number;
//Items.cs(スクリプト)を「items_script」という名前で定義する。
Items items_script;

void Start()
{
  //InfoにアタッチされていItems.csを取得する。
  items_script = GameObject.Find("Info").GetComponent<Items>();
  //Call関数を2.0秒後に実行する。
  Invoke("Call", 2.0f);
}
//public変数呼び出しの専用の関数
void Call()
{
  //Items.csのnumber変数を、i_number変数に代入する(取得完了!)。
  i_number = items_script.number;
}

実機でプレイしてみると、一部のゲームオブジェクトの動きがおかしい(荒ぶっている)場合

補間(動き予測)が悪く働いている可能性がある。

そのため、RigidbodyのInterpolateを「None」にすると良い。

それでも解決しない場合は、補間以外の問題点があるはずなので、スクリプトから原因を特定したいところ。

Prefab化したCanvasを新しいシーンに配置したが、UI(ボタンなど)が反応しない場合

Prefab化されたEventSystemを読み込むと、正しく動作しない。

そのため、EventSystemはシーンごとに新規作成する必要がある。

また、Main CameraにEvent Systemがアタッチされていても正しく動作しないので、アタッチされている場合は削除しよう。

特定のキーを押すとボタンイベントなどが誤動作する場合

スペースキーなどを押したときに、直前で使ったボタンイベントなどが誤動作する場合がある。

これはスクリプトが悪いのではなく、ボタンなどの初期設定(Unityの仕様)が悪い。

ボタンなら「Button」コンポーネント、スクロールバーなら「Scrollbar」コンポーネントのインスペクターを表示し、Navigationの設定をAutomatic(初期値)から「None」に変更することで解決する。

スクロールバーがドラッグしても動かない場合

カーソルロックを手動で解除しても、スクロールバーが反応しないときがある。

この現象は、カーソルロックをしている状態でスクロールバーを表示すると発生する。

解決するためには、そのスクロールバーを表示する前に「カーソルロックを解除する処理」を入れよう。

記事本文下のバナー広告

この記事をSNSでシェアする

 

プログラミングカテゴリーの最新記事(5件)

管理人のTwitter

Tweets by MinatameT

内部リンク集

広告枠のレンタルの詳細はこちら!
記事作成のご依頼の詳細はこちら!