C# Unity入門完全ガイド|初心者がつまずく文法・スクリプト・エラー解決までわかりやすく解説
はじめに
「C# Unity」と検索している人の多くは、Unityでゲームを作ってみたいけれど、C#の文法やスクリプトの書き方でつまずいている初心者ではないでしょうか。
Unityは2Dゲーム、3Dゲーム、スマホアプリ、VR・ARコンテンツなどを開発できる人気のゲームエンジンです。そして、Unityでキャラクターを動かしたり、当たり判定を作ったり、スコアを表示したりするために使われる代表的なプログラミング言語がC#です。
ただし、C#を単体で学ぶ場合と、Unityの中でC#を書く場合では、覚えるべきポイントが少し異なります。たとえば、UnityではStartやUpdateといった特別なメソッド、GameObjectやTransform、RigidbodyなどのUnity独自の仕組みを理解する必要があります。
この記事では、C# Unity入門として、初心者が最初に理解すべき基礎知識から、スクリプトの基本構造、よく使う文法、ゲーム機能の作り方、エラー解決方法までわかりやすく解説します。
1. C# Unityとは?初心者が最初に理解すべき基礎知識
C# Unityとは、Unityでゲームやアプリを開発するときにC#を使って処理を書くことを指します。
Unityでは、画面上にキャラクターやボール、敵、床、ボタンなどのオブジェクトを配置できます。しかし、配置しただけではゲームとして動きません。プレイヤーをキーボードで動かしたり、敵にぶつかったらゲームオーバーにしたり、アイテムを取ったらスコアを増やしたりするには、C#スクリプトで動作を命令する必要があります。
つまり、Unityが「ゲームの見た目や舞台を作る場所」だとすれば、C#は「ゲームに動きやルールを与えるための言語」です。
1-1. UnityでC#が使われる理由
UnityでC#が使われる主な理由は、ゲーム開発に必要な処理をわかりやすく、効率よく書けるからです。
C#は文法が比較的読みやすく、オブジェクト指向にも対応しているため、キャラクター、敵、アイテム、ステージ、UIなどを部品ごとに分けて管理しやすい特徴があります。
たとえば、プレイヤー用のスクリプト、敵用のスクリプト、スコア管理用のスクリプトを別々に作ることで、ゲーム全体の構造が整理しやすくなります。
また、UnityにはC#から利用できる便利な機能が多く用意されています。Transformを使えば位置や回転を変更でき、Rigidbodyを使えば物理演算でオブジェクトを動かせます。Colliderを使えば当たり判定も実装できます。
そのため、Unity初心者がゲームを作るうえで、C#は避けて通れない重要なスキルです。
1-2. C#とUnityスクリプトの関係
Unityで作成するC#ファイルは「スクリプト」と呼ばれます。スクリプトは、GameObjectに追加して使う部品のようなものです。
たとえば、PlayerController.csというC#スクリプトを作成し、それをプレイヤーのGameObjectにアタッチすると、そのGameObjectにプレイヤー操作の機能を追加できます。
UnityのC#スクリプトは、通常次のような形をしています。
C#using UnityEngine;
public class PlayerController : MonoBehaviour
{
void Start()
{
Debug.Log("ゲーム開始");
}
void Update()
{
Debug.Log("毎フレーム実行");
}
}
ここで重要なのが、MonoBehaviourです。UnityでGameObjectにアタッチして使う多くのスクリプトは、MonoBehaviourを継承します。これにより、StartやUpdateなど、Unityが自動で呼び出すメソッドを使えるようになります。
1-3. Unity初心者がC#でつまずきやすいポイント
Unity初心者がC#でつまずきやすいポイントは、主に次のようなものです。
C#の文法そのものがわからない場合、変数、if文、for文、メソッド、クラスなどの基本で混乱しやすくなります。さらに、Unity独自の考え方として、GameObject、Component、Inspector、Prefab、Collider、Rigidbodyなども理解する必要があります。
また、スクリプトを書いたのに動かない原因として、GameObjectにアタッチしていない、Inspectorで参照を設定していない、ファイル名とクラス名が一致していない、Consoleにエラーが出ているといったケースもよくあります。
初心者のうちは「C#のエラーなのか」「Unityの設定ミスなのか」が判断しにくいものです。そのため、文法だけでなく、Unity上でスクリプトがどのように動くのかをセットで理解することが大切です。
1-4. C#だけ学ぶ場合とUnityで学ぶ場合の違い
C#だけを学ぶ場合は、コンソールアプリなどで文字を表示したり、計算処理を書いたりするところから始めることが多いです。一方、UnityでC#を学ぶ場合は、画面上のオブジェクトを動かしながら学べます。
たとえば、C#単体では次のようなコードを書きます。
C#int score = 10;
Console.WriteLine(score);
一方、Unityでは次のように書くことが多くなります。
C#int score = 10;
Debug.Log(score);
また、UnityではUpdateメソッドの中に処理を書くことで、毎フレーム実行される動きを作れます。プレイヤー移動や入力処理など、ゲームならではの書き方が必要になります。
つまり、UnityでC#を学ぶ場合は、C#の基本文法に加えて、Unityの仕組みを同時に覚える必要があります。ただし、画面上で結果を確認しながら学べるため、初心者にとっては楽しく続けやすい学習方法でもあります。
2. UnityでC#を始めるための準備
UnityでC#を始めるには、まずUnity Hub、Unity Editor、コードエディタを準備します。環境構築が正しくできていないと、スクリプトが開けない、補完が効かない、エラーが出るといった問題につながります。
2-1. Unity HubとUnity Editorのインストール
Unityを使うには、まずUnity Hubをインストールします。Unity Hubは、Unity Editorのバージョン管理やプロジェクト管理を行うためのアプリです。
Unity Hubをインストールしたら、Unity Editorを追加します。初心者の場合は、安定版のLTSバージョンを選ぶのがおすすめです。LTSは長期サポート版のため、学習中に大きな仕様変更で混乱しにくいメリットがあります。
インストール時には、必要に応じて次のモジュールも追加します。
2D・3Dゲームを作るだけなら基本構成で問題ありません。スマホアプリを作りたい場合はAndroid Build SupportやiOS Build Supportが必要になります。Visual Studioをまだ入れていない場合は、Unity Hubのインストール画面で一緒に追加できます。
2-2. 新規プロジェクトの作成手順
Unity Hubを開いたら、新しいプロジェクトを作成します。
初心者の場合は、まず2Dまたは3Dのテンプレートを選びましょう。2Dゲームを作りたいなら「2D」、立体的な空間でキャラクターやオブジェクトを動かしたいなら「3D」を選びます。
プロジェクト名はわかりやすい名前にします。たとえば、練習用ならUnityCSharpPractice、プレイヤー移動を試すならPlayerMoveTestのようにしておくと管理しやすくなります。
プロジェクトを作成すると、Unity Editorが開きます。最初は画面に多くのパネルが表示されて戸惑うかもしれませんが、主に使うのはSceneビュー、Gameビュー、Hierarchy、Project、Inspector、Consoleです。
2-3. Visual Studio・Riderなどコードエディタの設定
UnityでC#を書くには、Visual Studio、Visual Studio Code、Riderなどのコードエディタを使います。
初心者にはVisual Studioがわかりやすいです。Unityとの連携機能があり、コード補完やエラー表示、デバッグ機能を使いやすいためです。
Unityで使用するエディタは、次の手順で確認できます。
Unity Editorのメニューから、Edit、Preferences、External Toolsを開きます。External Script Editorの項目で、Visual StudioやRiderなど、使いたいエディタを選択します。
コード補完が効かない場合は、Unity側の外部エディタ設定や、必要な拡張機能が入っているかを確認しましょう。初心者のうちは、エディタの補完機能を活用すると、メソッド名やプロパティ名の入力ミスを減らせます。
2-4. C#スクリプトを作成して開く方法
UnityでC#スクリプトを作成するには、Projectウィンドウで右クリックし、Create、C# Scriptを選びます。
スクリプト名を入力すると、.cs拡張子のC#ファイルが作成されます。ここで注意したいのは、スクリプトのファイル名とクラス名を一致させることです。
たとえば、PlayerController.csというファイル名なら、クラス名も次のようにします。
C#public class PlayerController : MonoBehaviour
{
}
ファイル名とクラス名が違うと、Unityで正しく認識されなかったり、Inspectorに表示されなかったりする原因になります。
作成したスクリプトをダブルクリックすると、設定したコードエディタで開けます。
3. Unity C#スクリプトの基本構造
Unity C#スクリプトには、初心者が最初に理解すべき基本構造があります。using、class、MonoBehaviour、Start、Updateを理解すると、Unityスクリプトの読み書きがしやすくなります。
3-1. using・class・MonoBehaviourとは
UnityのC#スクリプトの先頭には、よく次のような記述があります。
C#using UnityEngine;
usingは、特定の機能を使えるようにするための宣言です。UnityEngineを指定することで、Unityの基本機能であるGameObject、Transform、MonoBehaviour、Debugなどを使えるようになります。
次に重要なのがclassです。
C#public class PlayerController : MonoBehaviour
{
}
classは、処理をまとめるための設計図のようなものです。Unityでは、1つのC#スクリプトに1つのクラスを書くことが基本です。
MonoBehaviourは、UnityでGameObjectにアタッチできるスクリプトを作るための基本クラスです。MonoBehaviourを継承することで、UnityのライフサイクルメソッドであるStartやUpdateなどが使えるようになります。
3-2. StartメソッドとUpdateメソッドの違い
Unity初心者が最初に覚えるべきメソッドが、StartとUpdateです。
Startは、ゲーム開始時やオブジェクトが有効になったときに一度だけ実行されます。初期設定や変数の初期化に使います。
C#void Start()
{
Debug.Log("Startは最初に一度だけ実行されます");
}
一方、Updateは毎フレーム実行されます。キーボード入力、マウス入力、キャラクターの移動など、常に確認したい処理に使います。
C#void Update()
{
Debug.Log("Updateは毎フレーム実行されます");
}
たとえば、プレイヤーが右キーを押している間だけ移動させたい場合は、Updateの中で入力を確認します。
C#void Update()
{
if (Input.GetKey(KeyCode.RightArrow))
{
transform.position += new Vector3(0.01f, 0, 0);
}
}
初心者は、最初からすべてのメソッドを覚える必要はありません。まずはStartは最初に一度、Updateは毎フレームと覚えておきましょう。
3-3. GameObjectにスクリプトをアタッチする方法
UnityのC#スクリプトは、作成しただけでは動きません。GameObjectにアタッチする必要があります。
アタッチとは、GameObjectにスクリプトという機能を追加することです。たとえば、プレイヤーのGameObjectにPlayerControllerスクリプトをアタッチすると、そのGameObjectをC#で動かせるようになります。
アタッチする方法は簡単です。ProjectウィンドウにあるC#スクリプトを、Hierarchy上のGameObjectにドラッグ&ドロップします。または、GameObjectを選択してInspectorのAdd Componentからスクリプト名を検索して追加することもできます。
スクリプトを書いたのに動かない場合は、まず対象のGameObjectにスクリプトがアタッチされているか確認しましょう。
3-4. Inspectorから値を設定する基本
Unityでは、スクリプト内の変数をInspectorから設定できます。これにより、コードを書き換えなくてもUnity Editor上で値を調整できます。
たとえば、次のようにpublicな変数を作ります。
C#public float speed = 5f;
このスクリプトをGameObjectにアタッチすると、InspectorにSpeedという項目が表示されます。そこで数値を変更すれば、スクリプト内のspeedの値も変わります。
ただし、publicにすると他のスクリプトからもアクセス可能になります。外部から変更されたくないけれどInspectorには表示したい場合は、SerializeFieldを使います。
C#[SerializeField] private float speed = 5f;
初心者のうちは、Inspectorから値を調整できるようにしておくと、移動速度やジャンプ力などを試しやすくなります。
4. Unity初心者が覚えるべきC#文法
UnityでC#を使うために、最初から高度な文法をすべて覚える必要はありません。まずは、変数、if文、ループ、メソッド、クラス、アクセス修飾子を理解しましょう。
4-1. 変数とデータ型の使い方
変数とは、数値や文字などのデータを入れておく箱のようなものです。
Unity C#でよく使うデータ型には、次のようなものがあります。
C#int score = 0;
float speed = 5.0f;
bool isGameOver = false;
string playerName = "Hero";
intは整数、floatは小数、boolは真偽値、stringは文字列です。
Unityでは、位置や方向を表すためにVector3もよく使います。
C#Vector3 position = new Vector3(0, 1, 0);
Vector3は、x、y、zの3つの値を持つデータ型です。3D空間の位置、回転、拡大縮小、移動方向などで頻繁に登場します。2Dゲームでも、内部的にはVector3を使う場面があります。
4-2. if文・else文による条件分岐
if文は、条件によって処理を分けるために使います。
C#int hp = 0;
if (hp <= 0)
{
Debug.Log("ゲームオーバー");
}
この例では、hpが0以下なら「ゲームオーバー」と表示されます。
else文を使うと、条件に当てはまらない場合の処理も書けます。
C#int score = 50;
if (score >= 100)
{
Debug.Log("クリア");
}
else
{
Debug.Log("まだクリアではありません");
}
Unityでは、プレイヤーのHPが0になったらゲームオーバー、アイテムを取ったらスコア加算、敵に当たったらダメージなど、条件分岐を使う場面が非常に多いです。
4-3. for文・while文による繰り返し処理
for文は、同じ処理を決まった回数だけ繰り返すときに使います。
C#for (int i = 0; i < 5; i++)
{
Debug.Log(i);
}
このコードは、0から4までの数字を順番に表示します。
while文は、条件が成立している間、処理を繰り返します。
C#int count = 0;
while (count < 5)
{
Debug.Log(count);
count++;
}
ただし、UnityのUpdate内でwhile文を使うと、条件によっては無限ループになり、Unityが固まる原因になります。初心者は、繰り返し処理にはまずfor文を使うと安全です。
敵を複数生成する、アイテムを一覧処理する、配列の中身を確認するなど、ゲーム開発ではループ処理もよく使います。
4-4. メソッドの作り方と呼び出し方
メソッドとは、処理をひとまとまりにしたものです。同じ処理を何度も書かずに済むため、コードを整理できます。
C#void GameOver()
{
Debug.Log("ゲームオーバーです");
}
このメソッドは、次のように呼び出します。
C#GameOver();
たとえば、プレイヤーのHPが0になったときにゲームオーバー処理を呼び出すなら、次のように書けます。
C#int hp = 0;
void Update()
{
if (hp <= 0)
{
GameOver();
}
}
void GameOver()
{
Debug.Log("ゲームオーバーです");
}
メソッドを使うと、プレイヤー移動、ジャンプ、スコア加算、ゲームオーバーなどの処理を分けて書けるため、コードが読みやすくなります。
4-5. クラス・オブジェクト・インスタンスの考え方
C#はオブジェクト指向の言語です。初心者にとって、クラス、オブジェクト、インスタンスは少し難しく感じるかもしれません。
クラスは設計図、インスタンスは設計図から作られた実体と考えるとわかりやすいです。
たとえば、Enemyというクラスを作れば、敵のHPや移動速度、攻撃処理などをまとめられます。そして、ゲーム内に複数の敵を配置した場合、それぞれがEnemyクラスをもとにしたインスタンスになります。
Unityでは、GameObjectにスクリプトをアタッチすると、そのスクリプトのインスタンスがGameObjectごとに作られます。同じEnemyControllerスクリプトを複数の敵にアタッチしても、各敵はそれぞれ別のHPや位置を持てます。
この考え方を理解すると、Prefabを使って敵やアイテムを複数生成する仕組みも理解しやすくなります。
4-6. public・private・SerializeFieldの違い
C#では、変数やメソッドにアクセス修飾子を付けます。Unity初心者がよく使うのは、publicとprivateです。
publicは、他のスクリプトからアクセスでき、Inspectorにも表示されます。
C#public float speed = 5f;
privateは、そのクラスの中だけで使えます。基本的には、外部から変更されたくない変数はprivateにします。
C#private int hp = 100;
ただし、privateのままだとInspectorには表示されません。Inspectorから値を設定したいけれど、外部スクリプトからは直接触られたくない場合は、SerializeFieldを使います。
C#[SerializeField] private float jumpPower = 8f;
Unity C#では、基本的に変数はprivateにして、Inspectorで調整したいものだけSerializeFieldを付ける書き方がおすすめです。
5. Unityでよく使うC#の基本操作
Unity C#では、GameObjectの取得、Transformの操作、入力処理、物理演算、当たり判定、Prefab生成などをよく使います。ここを理解すると、簡単なゲーム機能を自分で作れるようになります。
5-1. GameObjectを取得する方法
GameObjectを取得する方法はいくつかあります。
名前で取得する場合は、GameObject.Findを使います。
C#GameObject player = GameObject.Find("Player");
ただし、GameObject.Findは便利ですが、名前の入力ミスに弱く、頻繁に使うと処理が重くなることがあります。
初心者におすすめなのは、Inspectorから参照を設定する方法です。
C#[SerializeField] private GameObject player;
このように書くと、InspectorにPlayer欄が表示されます。そこに対象のGameObjectをドラッグ&ドロップすれば、スクリプトから参照できます。
コンポーネントを取得したい場合は、GetComponentを使います。
C#Rigidbody rb = GetComponent<Rigidbody>();
GetComponentは、同じGameObjectに付いているコンポーネントを取得するときによく使います。
5-2. Transformで位置・回転・拡大縮小を変更する方法
UnityのGameObjectは、基本的にTransformを持っています。Transformには、位置、回転、拡大縮小の情報が入っています。
位置を変更するには、transform.positionを使います。
C#transform.position = new Vector3(0, 1, 0);
現在位置から少し移動させたい場合は、次のように書きます。
C#transform.position += new Vector3(1, 0, 0) * Time.deltaTime;
回転させるには、transform.Rotateを使います。
C#transform.Rotate(0, 90 * Time.deltaTime, 0);
拡大縮小を変更するには、transform.localScaleを使います。
C#transform.localScale = new Vector3(2, 2, 2);
Time.deltaTimeは、フレーム間の時間差です。移動や回転に使うと、フレームレートに左右されにくい動きになります。
5-3. キーボード・マウス入力を受け取る方法
Unityでキーボード入力を受け取るには、Input.GetKeyやInput.GetKeyDownを使います。
キーを押している間ずっと処理したい場合は、Input.GetKeyを使います。
C#if (Input.GetKey(KeyCode.RightArrow))
{
transform.position += new Vector3(1, 0, 0) * Time.deltaTime;
}
キーを押した瞬間だけ処理したい場合は、Input.GetKeyDownを使います。
C#if (Input.GetKeyDown(KeyCode.Space))
{
Debug.Log("スペースキーを押しました");
}
マウスクリックを検出するには、次のように書きます。
C#if (Input.GetMouseButtonDown(0))
{
Debug.Log("左クリックしました");
}
0は左クリック、1は右クリック、2は中央クリックを表します。
5-4. Rigidbodyを使ってオブジェクトを動かす方法
Rigidbodyは、Unityの物理演算を使ってオブジェクトを動かすためのコンポーネントです。重力、衝突、力を加える処理などを扱えます。
Rigidbodyを使うには、対象のGameObjectにRigidbodyコンポーネントを追加します。その後、C#で取得します。
C#private Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
}
力を加えて動かすには、AddForceを使います。
C#rb.AddForce(Vector3.up * 300f);
ジャンプ処理などでは、Rigidbodyを使うことが多いです。
C#if (Input.GetKeyDown(KeyCode.Space))
{
rb.AddForce(Vector3.up * 300f);
}
物理演算を使う場合、Transformを直接変更するよりも、Rigidbodyを通して動かすほうが自然な動きになります。
5-5. Colliderと当たり判定の基本
Colliderは、当たり判定の範囲を表すコンポーネントです。Box Collider、Sphere Collider、Capsule Collider、Mesh Colliderなどがあります。
当たり判定を検出するには、OnCollisionEnterやOnTriggerEnterを使います。
通常の衝突を検出する場合は、OnCollisionEnterを使います。
C#void OnCollisionEnter(Collision collision)
{
Debug.Log("ぶつかりました");
}
Triggerを使った当たり判定では、OnTriggerEnterを使います。
C#void OnTriggerEnter(Collider other)
{
Debug.Log("通過しました");
}
Triggerを使う場合は、ColliderのIs Triggerにチェックを入れます。アイテム取得、ゴール判定、ダメージエリアなどではTriggerを使うことが多いです。
5-6. Prefabをスクリプトから生成する方法
Prefabは、GameObjectを再利用できる形で保存したものです。敵、弾、アイテム、エフェクトなどを何度も生成したい場合に便利です。
Prefabをスクリプトから生成するには、Instantiateを使います。
C#[SerializeField] private GameObject bulletPrefab;
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
Instantiate(bulletPrefab, transform.position, Quaternion.identity);
}
}
この例では、スペースキーを押したときに、現在位置に弾のPrefabを生成します。
Prefabを使うと、同じ敵を複数出したり、アイテムをランダムに配置したり、弾を連続で発射したりできます。Unity C#でゲームらしい動きを作るために、PrefabとInstantiateは必ず覚えておきたい基本操作です。
6. Unity C#で簡単なゲーム機能を作ってみよう
ここからは、Unity C#を使って簡単なゲーム機能を作る例を紹介します。プレイヤー移動、ジャンプ、当たり判定、スコア表示、ゲームオーバー処理は、多くのゲームで使われる基本です。
6-1. プレイヤーを移動させるスクリプト
まずは、キーボード入力でプレイヤーを移動させるスクリプトです。
C#using UnityEngine;
public class PlayerController : MonoBehaviour
{
[SerializeField] private float speed = 5f;
void Update()
{
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
Vector3 move = new Vector3(horizontal, 0, vertical);
transform.position += move * speed * Time.deltaTime;
}
}
Input.GetAxis("Horizontal")は、左右入力を取得します。Input.GetAxis("Vertical")は、上下入力を取得します。
3Dゲームでは、x方向とz方向に移動することが多いため、new Vector3(horizontal, 0, vertical)としています。
2Dゲームの場合は、x方向とy方向を使うことが多いです。
C#Vector3 move = new Vector3(horizontal, vertical, 0);
ゲームの種類に合わせて、どの軸を使うかを変えましょう。
6-2. ジャンプ処理を実装する方法
ジャンプ処理には、Rigidbodyを使うのが一般的です。
C#using UnityEngine;
public class PlayerJump : MonoBehaviour
{
[SerializeField] private float jumpPower = 5f;
private Rigidbody rb;
private bool isGrounded = true;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space) && isGrounded)
{
rb.AddForce(Vector3.up * jumpPower, ForceMode.Impulse);
isGrounded = false;
}
}
void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.CompareTag("Ground"))
{
isGrounded = true;
}
}
}
このスクリプトでは、スペースキーを押したときに上方向へ力を加えています。isGroundedを使うことで、空中で何度もジャンプできないようにしています。
地面のGameObjectには、Groundタグを設定しておきます。タグ名が違うと判定されないため、Inspectorで正しく設定しましょう。
6-3. 敵や障害物との当たり判定を作る方法
敵や障害物に当たったときの処理は、OnCollisionEnterやOnTriggerEnterで作れます。
C#void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.CompareTag("Enemy"))
{
Debug.Log("敵に当たりました");
}
}
Triggerを使う場合は、次のように書きます。
C#void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Obstacle"))
{
Debug.Log("障害物に触れました");
}
}
CompareTagは、GameObjectのタグを比較するためのメソッドです。other.gameObject.tag == "Enemy"のように書くこともできますが、UnityではCompareTagを使う書き方がよく使われます。
当たり判定が反応しない場合は、Colliderが付いているか、Rigidbodyが必要な側に付いているか、Is Triggerの設定が合っているかを確認しましょう。
6-4. スコアを加算して画面に表示する方法
スコアを表示するには、UIのTextやTextMeshProを使います。ここではTextMeshProを使う例を紹介します。
C#using UnityEngine;
using TMPro;
public class ScoreManager : MonoBehaviour
{
[SerializeField] private TextMeshProUGUI scoreText;
private int score = 0;
void Start()
{
UpdateScoreText();
}
public void AddScore(int amount)
{
score += amount;
UpdateScoreText();
}
void UpdateScoreText()
{
scoreText.text = "Score: " + score;
}
}
アイテムを取ったときにスコアを加算する場合は、別のスクリプトからAddScoreを呼び出します。
C#[SerializeField] private ScoreManager scoreManager;
void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player"))
{
scoreManager.AddScore(10);
Destroy(gameObject);
}
}
InspectorでscoreTextやscoreManagerの参照を設定し忘れると、NullReferenceExceptionが出ることがあります。UIや管理用オブジェクトを使うときは、Inspectorの設定確認が重要です。
6-5. ゲームオーバー処理を作る方法
ゲームオーバー処理では、プレイヤーを止める、ゲームオーバー画面を表示する、操作を無効にする、シーンを再読み込みするなどの処理を行います。
簡単な例として、ゲームオーバー用のUIを表示するスクリプトを作ります。
C#using UnityEngine;
public class GameManager : MonoBehaviour
{
[SerializeField] private GameObject gameOverPanel;
private bool isGameOver = false;
void Start()
{
gameOverPanel.SetActive(false);
}
public void GameOver()
{
isGameOver = true;
gameOverPanel.SetActive(true);
Time.timeScale = 0f;
}
}
敵に当たったらゲームオーバーにする場合は、次のように呼び出します。
C#[SerializeField] private GameManager gameManager;
void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.CompareTag("Enemy"))
{
gameManager.GameOver();
}
}
Time.timeScale = 0f;にすると、ゲーム内の時間が止まります。再スタートする場合は、Time.timeScale = 1f;に戻す必要があります。
7. Unity C#で初心者がよく遭遇するエラーと解決法
Unity C#を学んでいると、必ずと言っていいほどエラーに遭遇します。エラーは悪いものではなく、コードや設定の間違いを教えてくれるヒントです。Consoleに表示される内容を読めるようになると、解決が早くなります。
7-1. NullReferenceExceptionの原因と直し方
NullReferenceExceptionは、初心者が非常によく遭遇するエラーです。これは、参照が入っていない変数を使おうとしたときに発生します。
たとえば、次のようなコードで発生します。
C#[SerializeField] private GameObject player;
void Start()
{
player.SetActive(false);
}
この場合、InspectorでplayerにGameObjectを設定していないと、playerがnullのままになり、SetActiveを呼び出せません。
解決方法は、Inspectorで参照を設定することです。また、コードで取得する場合は、GameObject.FindやGetComponentが正しく成功しているか確認します。
C#void Start()
{
player = GameObject.Find("Player");
if (player != null)
{
player.SetActive(false);
}
}
NullReferenceExceptionが出たら、まず「どの変数がnullなのか」を確認しましょう。Consoleのエラーをクリックすると、該当するスクリプトの行に移動できます。
7-2. CS0103「現在のコンテキストに存在しません」の対処法
CS0103は、指定した名前の変数やメソッドが見つからないときに発生するエラーです。
たとえば、次のコードではscroeという変数を使っていますが、正しくはscoreです。
C#int score = 0;
void Start()
{
Debug.Log(scroe);
}
このようなスペルミスでCS0103が発生します。
また、変数を宣言した場所が間違っている場合にも起こります。
C#void Start()
{
int score = 0;
}
void Update()
{
Debug.Log(score);
}
この場合、scoreはStartメソッドの中だけで使えるローカル変数です。Updateでも使いたいなら、クラスの中にフィールドとして宣言します。
C#int score = 0;
void Start()
{
score = 0;
}
void Update()
{
Debug.Log(score);
}
CS0103が出たら、スペルミス、変数の宣言場所、メソッド名の間違いを確認しましょう。
7-3. CS1061「定義が含まれていません」の対処法
CS1061は、指定した型にそのメソッドやプロパティが存在しないときに発生します。
たとえば、次のように書くとエラーになります。
C#GameObject player;
player.position = new Vector3(0, 0, 0);
GameObjectにはpositionというプロパティはありません。位置を変更するには、transform.positionを使います。
C#player.transform.position = new Vector3(0, 0, 0);
また、メソッド名のスペルミスでもCS1061が発生します。
C#rb.Addforce(Vector3.up);
正しくはAddForceです。
C#rb.AddForce(Vector3.up);
C#は大文字と小文字を区別します。AddForceとaddforceは別物として扱われるため、入力ミスに注意しましょう。
7-4. スクリプトがInspectorに表示されない原因
C#スクリプトがInspectorに表示されない場合、いくつかの原因が考えられます。
まず、ファイル名とクラス名が一致しているか確認しましょう。PlayerController.csというファイルなら、クラス名もPlayerControllerである必要があります。
C#public class PlayerController : MonoBehaviour
{
}
次に、スクリプトがMonoBehaviourを継承しているか確認します。GameObjectにアタッチするスクリプトでは、基本的にMonoBehaviourが必要です。
C#public class PlayerController : MonoBehaviour
また、プロジェクト内にコンパイルエラーがある場合、新しいスクリプトが正しく認識されないことがあります。Consoleに赤いエラーが出ていないか確認しましょう。
クラスがpublicになっていない場合も問題になることがあります。初心者のうちは、Unityで使うスクリプトのクラスはpublicで作成しましょう。
7-5. スクリプトを変更してもUnityに反映されないときの確認点
スクリプトを変更したのにUnityに反映されない場合は、まず保存しているか確認します。コードエディタ側で保存していないと、Unity側に変更が反映されません。
次に、Consoleにエラーが出ていないか確認します。C#のコンパイルエラーがあると、Unityはスクリプトの変更を正しく反映できません。
また、Playモード中にInspectorで値を変更した場合、Playモードを終了すると元に戻ることがあります。Unity初心者がよく混乱するポイントです。永続的に変更したい値は、Playモードを止めた状態で変更しましょう。
それでも反映されない場合は、Unity Editorを再起動する、スクリプトの再インポートを行う、エディタ設定を確認するなども有効です。
7-6. Consoleエラーの読み方とデバッグ方法
UnityのConsoleには、エラー、警告、ログが表示されます。赤い表示はエラー、黄色は警告、白は通常ログです。
エラーが出たら、まず一番上のエラーから確認しましょう。複数のエラーが出ていても、最初の1つを直すと他のエラーも消えることがあります。
Consoleのエラーをクリックすると、どのスクリプトの何行目で問題が起きているか確認できます。
また、Debug.Logを使うと、変数の値や処理の流れを確認できます。
C#Debug.Log("ジャンプ処理が呼ばれました");
Debug.Log("現在のスコア: " + score);
初心者のうちは、処理が実行されているか、変数に正しい値が入っているかをDebug.Logで確認するだけでも、かなり問題を解決しやすくなります。
8. Unity C#を効率よく学ぶコツ
Unity C#を効率よく学ぶには、文法を暗記するだけでなく、実際に小さなゲームを作りながら覚えることが大切です。Unityは画面上で結果を確認できるため、手を動かしながら学ぶほど理解が深まります。
8-1. 文法だけでなく小さなゲームを作りながら学ぶ
C#の文法を最初から完璧に覚えようとすると、途中で挫折しやすくなります。Unityを学ぶ目的がゲーム制作なら、文法学習とミニゲーム制作を並行するのがおすすめです。
たとえば、次のような小さな機能から作ってみましょう。
プレイヤーを左右に動かす、ジャンプさせる、アイテムを取る、スコアを増やす、敵に当たったらゲームオーバーにする。これだけでも、変数、if文、メソッド、当たり判定、UI表示など、Unity C#の基本を多く学べます。
重要なのは、最初から大作を作ろうとしないことです。まずは1画面で完結する簡単なゲームを作り、少しずつ機能を追加していきましょう。
8-2. 公式ドキュメントとサンプルコードの活用法
Unity C#を学ぶときは、公式ドキュメントも活用しましょう。公式ドキュメントには、各クラスやメソッドの使い方、引数、サンプルコードが掲載されています。
たとえば、Transform、Rigidbody、Collider、Input、Instantiateなどを調べると、使い方の例を確認できます。
ただし、初心者が公式ドキュメントを最初からすべて理解するのは難しいこともあります。最初は、わからないメソッド名を調べる辞書のように使うとよいでしょう。
サンプルコードを見るときは、丸写しするだけでなく、「どの変数が何を表しているのか」「どのタイミングで処理が呼ばれているのか」「自分のゲームならどこを変えるべきか」を考えることが大切です。
8-3. エラーを検索するときのキーワードの選び方
Unity C#でエラーが出たときは、検索キーワードの選び方が重要です。
たとえば、NullReferenceExceptionが出た場合は、次のように検索すると解決策を見つけやすくなります。
Unity C# NullReferenceException 原因Unity NullReferenceException Inspector 参照Unity C# GetComponent null
CS0103の場合は、次のように検索します。
Unity C# CS0103 現在のコンテキストに存在しませんUnity CS0103 変数 見つからない
エラー全文をそのまま検索するのも有効です。ただし、自分のクラス名や変数名が含まれている場合は、一般的な部分だけを抜き出して検索するとよいでしょう。
「Unity」「C#」「エラー名」「やりたいこと」を組み合わせて検索するのがコツです。
8-4. 初心者におすすめの学習順序
Unity C#初心者におすすめの学習順序は、次の流れです。
まず、Unity Editorの基本操作を覚えます。Sceneビュー、Hierarchy、Inspector、Project、Consoleの役割を理解しましょう。
次に、C#スクリプトの作成、GameObjectへのアタッチ、StartとUpdateの違いを学びます。
その後、変数、if文、メソッド、クラスなどのC#文法を、Unityの動きと関連付けながら学びます。
次に、Transformで移動、Inputで入力、Rigidbodyで物理演算、Colliderで当たり判定を作ります。
最後に、スコア表示、ゲームオーバー、シーン切り替え、Prefab生成などを追加すると、簡単なゲームが完成します。
この順序で学ぶと、文法とUnityの機能が自然につながりやすくなります。
8-5. 挫折しないための練習テーマ
初心者が挫折しないためには、完成させやすい小さなテーマを選ぶことが大切です。
おすすめの練習テーマは、ボールを転がしてゴールを目指すゲーム、横スクロールでジャンプするゲーム、落ちてくるアイテムをキャッチするゲーム、敵を避けながらスコアを稼ぐゲーム、クリックで的を消すゲームなどです。
これらのテーマは、Unity C#の基本である移動、入力、当たり判定、スコア、ゲームオーバーを学びやすい構成です。
最初からオンラインゲームや本格的なRPGを作ろうとすると、覚えることが多すぎて大変です。まずは1日から数日で完成できる小さなゲームを作り、完成体験を積み重ねましょう。
9. Unity C#入門でよくある質問
ここでは、Unity C#を学び始めた初心者が疑問に感じやすい質問に答えます。
9-1. Unityを使うにはC#をどこまで覚える必要がある?
最初からC#を完璧に覚える必要はありません。Unityで簡単なゲームを作るなら、まずは変数、if文、for文、メソッド、クラス、public、private、SerializeFieldを理解できれば十分です。
そのうえで、Unity独自のGameObject、Transform、Rigidbody、Collider、Prefab、Instantiateなどを覚えていくと、基本的なゲーム機能を作れるようになります。
高度なC#文法は、必要になったときに学べば問題ありません。最初は「読める」「少し書ける」「エラーを調べて直せる」状態を目指しましょう。
9-2. C#初心者でもUnityでゲームは作れる?
C#初心者でもUnityでゲームは作れます。むしろ、Unityは画面上で動きが確認できるため、プログラミング初心者でも学びやすい面があります。
ただし、最初から複雑なゲームを作ろうとすると難しく感じます。まずは、プレイヤーを動かす、ジャンプする、アイテムを取る、スコアを表示するなど、小さな機能から始めましょう。
C#の文法を少し学んだら、すぐにUnityで試すことが大切です。実際に動かすことで、文法の意味が理解しやすくなります。
9-3. UnityのC#と普通のC#は違う?
UnityのC#と普通のC#は、基本的な文法は同じです。変数、if文、for文、メソッド、クラスなどは通常のC#と同じ考え方で使えます。
違うのは、Unity独自のクラスやメソッドを多く使う点です。たとえば、MonoBehaviour、Start、Update、GameObject、Transform、Rigidbody、ColliderなどはUnityでよく使う仕組みです。
つまり、UnityのC#は「C#の基本文法」と「Unityの機能」を組み合わせて書くものだと考えるとわかりやすいです。
9-4. JavaScriptやPython経験者はUnity C#を学びやすい?
JavaScriptやPythonの経験がある人は、Unity C#を比較的学びやすいです。変数、条件分岐、ループ、関数の考え方は共通しているためです。
ただし、C#は型を明確に書く言語です。Pythonのように自由に変数へ値を入れる感覚とは少し違います。
たとえば、C#では次のように型を指定します。
C#int score = 0;
float speed = 5f;
string name = "Player";
また、C#では文末にセミコロンが必要です。
C#Debug.Log("Hello Unity");
JavaScriptやPythonの経験者は、プログラミングの考え方を活かしつつ、C#の型、クラス、アクセス修飾子、Unity独自のライフサイクルに慣れていくとよいでしょう。
9-5. 2Dゲームと3DゲームでC#の書き方は変わる?
2Dゲームと3Dゲームで、C#の基本文法は変わりません。ただし、使うコンポーネントや座標の考え方が少し変わります。
3Dゲームでは、位置にVector3を使い、x、y、zの3軸で考えます。Rigidbody、Box Collider、Sphere Colliderなどの3D用コンポーネントを使います。
2Dゲームでは、Rigidbody2D、BoxCollider2D、CircleCollider2Dなど、2D用のコンポーネントを使います。当たり判定のメソッドも、2DではOnCollisionEnter2DやOnTriggerEnter2Dになります。
たとえば、2Dの当たり判定は次のように書きます。
C#void OnCollisionEnter2D(Collision2D collision)
{
Debug.Log("2Dで衝突しました");
}
3D用と2D用のコンポーネントを混ぜると、当たり判定が反応しない原因になります。2Dゲームなら2D用、3Dゲームなら3D用で統一しましょう。
まとめ
C# Unityを学ぶうえで大切なのは、C#の文法とUnityの仕組みをセットで理解することです。
Unityでは、C#スクリプトをGameObjectにアタッチすることで、キャラクターを動かしたり、ジャンプさせたり、敵との当たり判定を作ったり、スコアを表示したりできます。
初心者がまず覚えるべきなのは、using、class、MonoBehaviour、Start、Update、変数、if文、for文、メソッド、public、private、SerializeFieldなどの基本です。そのうえで、GameObject、Transform、Rigidbody、Collider、Prefab、Instantiateを使えるようになると、ゲーム制作の幅が大きく広がります。
また、Unity C#ではエラーに慣れることも重要です。NullReferenceException、CS0103、CS1061などは初心者がよく遭遇するエラーですが、原因を理解すれば解決できるようになります。Consoleのエラーを読み、該当行を確認し、変数や参照、スペルミスをチェックする習慣をつけましょう。
C# Unity入門では、最初から完璧を目指す必要はありません。小さなゲームを作りながら、少しずつ文法とUnityの機能を覚えていくことが上達への近道です。まずは、プレイヤーを動かす、ジャンプさせる、アイテムを取る、スコアを表示するという基本機能から挑戦してみましょう。

