サンプルコードを写してキャラを動かせるようになった頃、ふと自分の PlayerController.cs を見ると——移動もHPもアイテムもUI更新も全部入りで、気づけば数百行。どこかを直すと別の場所が壊れ、「クラスをどう分ければいいのか」が分からない。変数と関数を覚えた初心者が、次に必ずぶつかる壁です。
この記事では、その壁を越えるためのC#の道具—— クラスとインスタンス、値型と参照型と null、プロパティ、継承とコンポジション、interface ——を順番にそろえます。最後は IDamageable というinterfaceを使って、プレイヤー・敵・木箱を「同じ剣の一振り」で処理できるところまで組み立てます。
この記事でわかること
- クラス= データと振る舞いのまとまり、インスタンス=その実体
- 値型と参照型の違いと、
null/ NullReferenceException の正体- Unity特有の「破棄済みオブジェクトは
== null」という特別ルールpublicフィールドではなく[SerializeField] privateとプロパティ を使う理由- 継承とコンポジション の使い分け(Unityは「部品を組む」エンジン)
- interface で「ダメージを受けられるもの」を共通化する実例
動作確認環境: Unity 2022.3 LTS / Unity 6
「全部PlayerControllerに書く」と何が壊れるか
まず、壁の正体をはっきりさせましょう。次のようなスクリプト、心当たりはないでしょうか。
public class PlayerController : MonoBehaviour
{
// 移動もHPもコインもUIも音も、ぜんぶここに……
public float moveSpeed = 5f;
public int health = 100;
public int coinCount = 0;
public Text healthText;
public AudioClip damageSound;
void Update()
{
// 移動処理 30行
// ダメージ処理 40行
// コイン処理 20行
// UI更新 30行 ……
}
}
動いてはいます。でも、この書き方は規模が少し増えただけで壊れ始めます。
- 直す場所が探せない: ジャンプのバグを直したいのに、HPやUIの コードをかき分けて探すことになる
- 1カ所の変更が全体に波及する: HPの変数名を変えたら、移動処理の中に紛れていた無敵判定まで巻き添えでエラーになる
- 使い回せない: 「敵にもHPが欲しい」と思っても、この中からHP部分だけを取り出せない

解決の方向はシンプルで、 「役割ごとに小さなクラスへ分ける」 です。移動は PlayerMover、HPは Health、コインは CoinCollector。実は GameObjectとコンポーネント で見た「部品を組み合わせる」というUnityの設計思想そのものです。この記事では、その「分ける」ためのC#の文法を一つずつ見ていきます。
クラスは「データと振る舞い」のまとまり
クラス は、関連する変数(データ)と関数(振る舞い)をひとまとめにした「設計図」です。そして設計図から作られた実体を インスタンス と呼びます。
