はじめに
先日、Unity初心者数十名を相手にUnityの基礎を教える機会があったのだが、多くのひとが同じようなミスを犯した。高い確率で同様のミスをするであろう初心者に(もしくは同じように初心者に教える必要が生じた者のために)そのミスを書き記しておく。概ね1番多かった順に。
ミス例:
↑Playerクラスを作って貰うだけでもこのくらいのミスが発生する
対象読者と必要知識、開発環境
想定する読者レベル
- Unity独学初心者 or ゲーム系学校の1年生
- プログラムはUnityがほぼ初めて (もしくはCやC++を学校や自分でちょっと齧っている程度)
- 「変数とは?」みたいな説明は要らない (int, floatくらいならわかる)
- if文やfor文などの基本的な制御文がなんとかわかる
- 簡単な入門サンプルやチュートリアルを1個以上打ち込んだことがある
- 「チュートリアル通りに打ち込んだら、確かに動いたんだけど、なんかよくわからん!」
- 「ゲームを自分で1から作れ!」て言われてもさっぱり作れる気がしない」
Unityの想定バージョンや環境
- 2018.3~2019.3辺り
- Microsoft Visual Studio Community 2017~2019
- Windows 10
(上記範囲外でも、たぶん問題ない筈)
第1位 スペルミス
大文字小文字の区別
プログラムの世界では違う名前として区別されるので注意すること。
「class Player」を「class player」と書くひとが非常に多い。
(一貫してすべての箇所で「player」と間違うならエラーは出ないが、写経やコピペでどこか一箇所で正しく「Player」と書いてエラーなってしまう)
C#スクリプト名とクラス名の不一致でエラー
初心者の「動きません」で非常によく見る。
ミスするプロセスをみてみよう!(宇宙刑事風)
→ 名前を入力し損ねて「NewBehaviourScript.cs」になってしまう…
→ 名前を後から「Player」等に修正
→ スクリプト内のクラス名がNewBehaviourScriptのまま
→ ドラッグ&ドロップでスクリプトをHierarchy上のオブジェクトにアタッチしようとするとエラー。
Can’t add script component ‘Player’ because the script class cannot be found. Make sure that there are no compile errors and that the file name and class name match.
スクリプトクラスが見つからないため、スクリプトコンポーネント「プレーヤー」を追加できません。コンパイルエラーがなく、ファイル名とクラス名が一致することを確認してください。
C#スクリプトファイル名とクラス名は完全に一致させること!
.cs作成時の段階でちゃんと名前を付けてしまうのが1番ラクでしょう。
クラス名の頭文字を小文字で書いてしまう
入門書やお手本では「Player」って書いているのに
「player」
とか書いてしまう。
そして、写経するコード内では正しく「Player」と書いてしまい、一貫性がなくエラーになる。
Unity「『Player』ってなんだよ? そんなの聞いたことねーんですけど?」
初心者「クラス名 『player』 って書いていた」
頭文字が小文字でもクラスは定義できてしまうが、初心者は
「クラス名の頭文字は大文字」 と機械的に覚えてしまって構わない。
クラス名や関数名は アッパーキャメルケース で書くのが一般的です。
例:RabbitController
- 余談 クラス名が大文字だと…
MyClass myClass;
のように変数名を考えるのもラク。
関数名を頭文字小文字で書いてしまう
- 入門書やお手本では「SetPlayer( )」って書いているのに
「setplayer( )」
とか書いてしまう。
関数名は原則、単語頭文字が大文字のアッパーキャメルケース で書くこと
UnityのStart()やUpdate()の関数名を変えてしまう
- 元から書いてあるUpdate( )関数を消して、update( )とかに書き換えてしまう。Start()→start()もよく見る。
この場合、Unity側で用意したUpdate( )関数ではなく、独自の関数を定義した扱いになってUnity側から毎フレームや起動時に呼び出されなくなる。
「何故か全然動かない…コードは何処もミスっていないのに…何故?」
となって目視では非常に発見し難いバグになるので注意。
複合語の大文字小文字スペルミス
Update()をUpDate()、RigidboyをRgidBody、TranslateをTransLateと書いてしまうようなミス。自作の独自関数名なら問題ないが、Unity側で用意されたクラス名や関数名だと問題になる。
VisualStudioの入力補完で書いてほしい。
OnTriggerEnterとOnCollisionEnterの引数型の違い
private void OnTriggerEnter(Collider other)
{
}
private void OnCollisionEnter(Collision collision)
{
}
で引数の型がCollider とCollision で違う。
何らかのコーディング上の都合でTrigger←→Collisionを手動で書き換えて引数の型名をそのままにしておくと「何故か衝突が検出されない…」となる。
目視では非常に発見し難いバグになるので注意。
- 部分的に書き換えるよりも、入力補完でOnTri..、OnColli...と書いたら全部自動で書いてくれるので安全!
OnTriggerEnter2DとOnCollisionEnter2DなのにAddしたComponentが3D用
private void OnTriggerEnter2D(Collider2D other)
{
}
private void OnCollisionEnter2D(Collision2D collision)
{
}
2Dは2D用の関数且つ2D用のコライダー(例:BoxCollider2DやCircleCollider2D)である必要がある。
関数は2D用なのにオブジェクトに追加したコンポーネントが3D用のコライダー、
逆に関数は3D用なのにコライダーを2D用にしてしまっているという例が非常に多い。
関数を書く場所がそこじゃない
- Update()内に書いてしまったり、classの外に書いてしまったりする初心者が非常に多い。
- プロジェクタの画面や入門書の紙面の都合でコードの一部分しか映せないときにこのミスは発生しやすい。
- 「 { } 」中括弧内はコードブロックといって、そのclassや関数、if文等の領域内を示すので、どこからどこまでが領域内なのか常に意識して貰いたい。
↑Visual Studio上で括弧をクリックすると薄い灰色で対応するブロックの括弧が表示される。
「それぞれのブロックが何処から何処までなのか?」
を常に意識してほしい。
- 通常は「{」と「}]は縦に同じ位置になるように揃える。
- 詳しくは字下げスタイル
※関数内に関数を定義する「ローカル関数」というのもあるが、初心者は取り敢えず知らなくていい
括弧の数の不一致、閉じ忘れ
上図では if の丸括弧「 ( ) 」 閉じが無い。
括弧は必ず閉じなければいけないので、{ }や( )は常に対になっている相手が何処にあるか意識したい。括弧をクリックして対がどれかをチェックしよう。
文字列名、タグ、レイヤー名
- Input.GetAxisRaw("Horizontal") の"Horizontal"や"Vertical"のスペルミス
入力補完で書けないので非常に間違えやすい。
- Input.GetButtonDown("Fire1")
を"Firel"「1(壱ではなくl(Lの小文字))と書いてしまうひとも居る。
当然下記のようなエラーになる。
ArgumentException: Input Button Firel is not setup.
To change the input settings use: Edit -> Settings -> Input
Player.Update () (at Assets/Scripts/Player.cs
input.GetButtonDown
「『Firel(ふぁいやーえる)』なんてInput Managerにセットアップされてないんですけど?」
- タグ名、レイヤー名のスペルミス
セットアップしたタグ名は「player」や「enemy」なのにコード上では"Player","Enemy"で指定しているケース。一字一句厳密に一致させる必要がある。これらもクラス名や変数名と同様、大文字小文字の区別がある。注意してほしい。
- Animatorの変数名のスペルミス
Animator上での変数名は"Jump"なのに
コード上ではSetTrigger("jump");って書いてしまう。
英語のスペルミス
- playerを「prayer」(祈り)とか書いてしまう。かなり多い。私が神に祈りたくなる。
- 面倒でもスペルが怪しければググってほしい
- Road、Siin、Maneejar とか平気で出てくる。英語が苦手なのは別にいい。ググってほしい。想像で英単語を創造してはいけない。
視認性の悪い文字のスペルミス
- 1 と l (Lの小文字)と | (or)
- Kとk
- 0とO
- 全角アルファベットABC、半角アルファベットABC
※全角変数名や関数名は作れてしまいますが、原則やめてください
クラスの二重定義
- 右クリックで不用意に作った class NewBehaviourScript がプロジェクト内に複数あるケース。
- 単純に同じ名前のクラス名がダブったケース
- アセットストアからインポートしたアセットのクラス名と衝突しているケース
- コードの写経が間に合わなくて、クラスメートや先生の完成スクリプトをインポートしたら同じクラス名のスクリプトが二重に存在するケース
などが考えられる。
エラーは以下のようになる。
error CS0111: Type 'Player' already defines a member called 'Update' with the same parameter types
「なんか『Player』って名前のクラス、既に定義されちゃっているんですけど?(大意)」
- 同名ファイルインポート時の注意点
特に最後の同名のC#スクリプトファイルをインポートするときは注意してほしい。
Unityエディタ上で上書き保存のつもりで同名ファイルをドラッグ&ドロップでインポートすると、Unity様が余計な気を利かして連番付き別名ファイルとしてインポートしてしまう。
- 正しい上書き保存による更新
C#スクリプト以外にも画像ファイルなどを更新して上書き保存で更新したいときにも困る。
Projectビュー上で右クリック→Show in ExplorerでWindowsのフォルダを表示させて、そこで上書き保存してほしい。
GetComponent「s」、FindGameObject「s」WithTag
単数形と複数形のある関数がある。
例:
- GetComponent<型名>( )
- GetComponent s <型名>( )
- FindGameObjectWithTag( )
- FindGameObject s WithTag( )
複数形は戻り値が配列変数になっている。
入力補完で間違えて選ぶひとが多いので注意。
第2位 publicメンバ変数のオブジェクトをセットしていなくてnull
publicなメンバ変数にオブジェクトをセットするケース。
(※Bulletとは弾の意味です)
(※PlayerやBulletは任意名の好きにつけた名前であり、予約語ではありません)
・None(Bullet)欄にBullet.csがアタッチされたオブジェクトをセットする必要がある
チュートリアル等には「セットして」とあるのに空欄のままで実行し、エラー
ArgumentException: The Object you want to instantiate is null.
君が生成しようとしたオブジェクト(弾)が空っぽ(null)だよん!(大意)
・たまに、何故かBullet.csファイルをここにセットしようとするひと居る(そうじゃない)
ちなみに
- public Bullet bullet; だとBullet.csをアタッチしたオブジェクトしかセットできない
- public GameObject bullet; ならHierarchy上のオブジェクトを何でもセットできる
- public Transform bullet; ならTransformコンポーネントが存在するオブジェクト(実質全部)をセットできる
【初学者必見】Unityの実行時エラーの9割はNullReferenceExceptionだよね
第3位タグを作ったはいいがセットしていない
第4位エディタの表示設定周り
なんか画面が真っ白なんすけどぉ?
・検索欄に文字を入れたままだと白っぽくなる(オブジェクトを絞り込める)
検索欄をクリアすれば元に戻ります
第5位 なんか色々とぶっ壊れる
↓以下のサイトに丸投げします
Unityのプロジェクトはなぜ壊れるのか。原因と対策
その他
何か思い出す度に追記していく予定…
定期的にメンテします。
間違い等あれば、お気軽に…
更新履歴
2019/09/28
- Collider2Dの話を追加、細かい表現の修正
2019/09/19
- 細かい誤字脱字、内容面の不確かさを修正、うさぎの可愛い画像を追加
2019/09/19
- 取り敢えず投稿