はじめに
こんにちは、rinngo です!
この記事では、現代のプログラミングに欠かせない オブジェクト指向プログラミング について解説します!
そしてこれを含めて4回に分けて少しずつ解説していこうと思うので、少しずつ一緒に勉強していきましょう!
今回では主に以下のことを解説していきます。
- クラス とは?
- インスタンス とは?
- フィールド と ローカル変数 の違いは?
- メソッド とは?
また、これは私が所属している徳島大学ゲームクリエイトプロジェクトの勉強会で使用するものです。
興味がありましたら、UnityroomとX公式アカウントなども見に行ってください!
この記事の目標
この記事では主に以下を目標とします。
- オブジェクト指向プログラミング についてなんとなく理解できる
- クラス を自分でかける
- フィールド と メソッド の名前を覚えて使えるようになる
また、オブジェクト指向プログラミングは初心者にとって 難しい 概念なので今回で完璧に理解する必要は ありません!
なんとなくのイメージと用語などを少しずつ理解していって欲しいです!
環境
- OS: macOS 26.3
- UnityEditor: 6000.3.14f1
今回の記事ではそこまで環境は影響しません。
少しUIが変わってるくらいだと思います。
オブジェクト指向プログラミングとは?
さっそくですが、 オブジェクト指向プログラミング とはなんでしょうか?
これをざっくりと説明すると
「 クラス と呼ばれる設計図のようなものを作成し、それを使って インスタンス(オブジェクト) を生成してそれを使う 」
というプログラミングの方法のことを指します。
...といっても何を言ってるかよくわからないですよね?
ですので、まずは一旦概要を理解してもらうためにもう少し詳しく解説していきますね。
オブジェクト指向プログラミングのイメージ
まずは 工場 を想像してみてください。
工場 の中では絶え間なくたくさんの もの が作られ続けていますよね?
ですが、この もの を作るためには最初に 設計図 のようなものがあるはずですよね?
例えば、車などの部品だと「形」「大きさ」「素材」「作り方」などが細かく決められており、それを元に生産しているはずです。
オブジェクト指向プログラミング とはまさにこれと同じで
「クラス」 と呼ばれる 設計書 をプログラマが作成しておいて、
コンピュータがその設計書の通りに 「インスタンス」 と呼ばれる もの を生成する
というものです。
Unity で例えると?
この概念、少し聞いたことがあるのではないでしょうか?
実は、オブジェクト指向プログラミングはUnityの Prefab にとてもよく似ています。
Prefab を作成しておいて、それを元に GameObject を生成するという使い方をしますよね?
ほとんどそれと同じです。
ですのでそれをイメージしていきながら読み進めていくと理解しやすいかと思います。
なんとなく理解できましたかね?
次はオブジェクト指向プログラミングをする メリット について解説します。
オブジェクト指向プログラミングのメリット
オブジェクト指向プログラミングを使用することで、私は主に 2つ のメリットがあると思います。
(もちろんもっとありますが、一旦この記事で扱う表面上のものだけ紹介します。)
- 独立した インスタンス(もの) を扱える
- インスタンス を「部品」として扱い、それらを組み合わせることができる
1つずつ見ていきましょう。
メリット1
クラス設計によって、急な変化に強いシステムを実装できます。
具体的には、まずは 敵 の要素を書いている クラス(設計書)を作ったとしましょう。
そしてそのクラスをもとにコンピュータがインスタンス(もの)を生成できるようになります。
ここで「敵を10体一気に生成したい」と思ったとします。
すると、 クラス(設計書) を作成しているおかげで インスタンス(もの)を1体出そうが10体出そうが ほとんどプログラムを変えなくていいんです。
工場でも、「もの」を10個作成しようが100個作成しようがほとんどやることは変わらないということはなんとなく想像がつきますよね?
(もしかしたら違うのかもしれませんが、これはイメージの話なのでなんとなくで大丈夫です。)
このように、クラスを使ってインスタンスを管理することで、急な変化に強いシステムを実装できるというメリットがあります。
メリット2
複数のインスタンスを組み合わせることで、柔軟な実装をしやすくなります。
具体的には、また工場を想像してみてください。
「何種類の部品を作成して、それらを組み合わせて1つの製品を作成する」ということは結構ありますよね?
これにより、製品のなにかの仕様を変更するとしても どの部分を変更すればいいのか分かりやすい というメリットがあります。
(これもイメージです。実際は知らないですが...)
オブジェクト指向プログラミングも同じで、
1つのインスタンスを作成するために複数のインスタンスを作成して組み合わせる ということができます。
よって、 より柔軟な実装をしやすい というメリットがあります。
クラスとは?
ではここからは「設計書」と説明していた クラス についての説明と書き方について解説していきます。
GameObject の作成と準備
まずは適当にプロジェクトの作成をしましょう。
何でもいいですが、とりあえず Universal 3D でプロジェクトをつくりましょう。
次にオブジェクトの作成をしましょう。
Player という名前の Cube を作成してください。
次に Player.cs という MonoBehaviour のファイルを生成しましょう。
ソースコードは以下のようにしてください。
using UnityEngine;
public class Player : MonoBehaviour
{
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetKey(KeyCode.UpArrow))
{
transform.Translate(Vector3.up * Time.deltaTime);
}
if (Input.GetKey(KeyCode.DownArrow))
{
transform.Translate(Vector3.down * Time.deltaTime);
}
if (Input.GetKey(KeyCode.LeftArrow))
{
transform.Translate(Vector3.left * Time.deltaTime);
}
if (Input.GetKey(KeyCode.RightArrow))
{
transform.Translate(Vector3.right * Time.deltaTime);
}
}
}
これを先ほど作った Cube にアタッチしましょう。
デフォルトの設定では Input.GetKey() は使用できないので使用できるように設定を変更しましょう。
メニューバーの「Edit」->「Project Settings...」をクリックしてください。
次に Player を選択してください。
下にスクロールしていくと Active Input Handling の項目があるので、その項目を Input System Package (New) から Both に変更してください。
すると Unity Editor が再起動します。
再起動後実行してみると、 Cube を十字キーで上下左右に動かすことができます。
これで一旦は準備は完了しました!
クラスの書き方
これから自分でクラスを書いていくのですが、一旦はクラスの書き方について学びましょう。
以下が基本的な書き方です。
class <クラス名>
{
// 色々な要素
}
これ見たことありますよね?
そうです。いつもいつも MonoBehaviour のスクリプトを生成すると自動で書かれているんですよね。
MonoBehaviourのデフォルト
using UnityEngine;
public class <クラス名> : MonoBehaviour
{
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
というわけで基本的なクラスの書き方はこれで大丈夫です!
では、今から PlayerStatus.cs というファイルを生成しましょう。
今回は MonoBehaviour と違って Empty C# Script を生成してください。
下の画像のように Create->Scripting->Empty C# Script をクリックしてください。
そしてファイル名は PlayerStatus にしましょう。
すると、デフォルトで下のようなコードが記述されていますよね。
using UnityEngine;
public class PlayerStatus
{
}
これで、すでに PlayerStatus というクラスを作成できています。
フィールドとは?
フィールド とは、クラスの中で定義した変数のことです。
実はすでにみなさんはこの フィールド を何回も使っています。
今までに以下のようなコードを書いたことがあると思います。
class Player : MonoBehaviour
{
[SerializeField] private int _maxHP;
private int _hp;
void Start()
{
}
void Update()
{
}
}
このコードだと、 _hp と _maxHP のことを フィールド と呼んでいます。
ですが、今まではこれらのことを変数と呼んでいましたよね?
ですが、クラスの中といえど メソッドの中で定義した変数 はフィールドとは 呼びません。
それは ローカル変数 と呼ばれます。
さて、これらの フィールド と ローカル変数 の違いはなんでしょうか?
それは、 記憶している期間 と その変数にアクセスできる場所 です。
少しややこしいので表にまとめました。
| 種類 | 記憶している期間 | その変数にアクセスできる場所 |
|---|---|---|
| フィールド | クラスから生成したインスタンスが存在している間 | (基本的に)そのクラス全体 |
| ローカル変数 | 定義したメソッドが始まってから終わるまで(毎回生成されては解放される) | そのメソッドの中のみ |
このように、どれだけ記憶させたいかを基準に 「フィールド」と「ローカル変数」を使い分けていくことになります。
フィールドの別の呼び方
フィールドは結局は変数であるので、ローカル変数と同じように 「メンバー変数」 とも呼ばれています。
言語や人によってメンバー変数と呼ぶこともあるのですが、一般的にはC#では「フィールド」と呼ぶのでここではそれに合わせています。
「フィールド」 とは?
- クラスの中で定義されている 変数 のこと
- インスタンスが生成されてから解放されるまで記憶する
- ローカル変数 との使い分けをする
フィールドを追加する
では今から実際にフィールドを追加しましょう。
以下の2つのフィールドを追加しましょう。
_hp_attack
このように PlayerStatus.cs を書いてください。
public class PlayerStatus
{
private int _hp;
private int _attack;
}
これで追加できましたね!
フィールドにアクセスするためのメソッドを追加する
次にそのフィールドの変数に値を設定できるメソッドと値を取得できるメソッドを追加しましょう。
以下のようにメソッドを定義してください。
public class PlayerStatus
{
private int _hp;
private int _attack;
public void SetParameters(int hp, int attack)
{
_hp = hp;
_attack = attack;
}
public int GetHp()
{
return _hp;
}
public int GetAttack()
{
return _attack;
}
}
これで SetParameters()メソッドで値を設定し、GetHp()メソッドで _hp の取得、GetAttack()メソッドで _attack の取得ができるようになりました。
インスタンスを扱う
ここからはクラスから インスタンス を生成していきましょう。
つまり工場の例でいうと、 「設計図から もの を作成する」 という工程です。
基本的にインスタンスの生成は以下のように記述します。
<クラス> <インスタンス> = new <クラス>();
今回の PlayerStatusクラスだと
PlayerStatus status = new PlayerStatus();
になります。
これで、 status という インスタンス の生成ができます!
インスタンスの生成をしないと?
もし、インスタンスの生成をせずにメソッドなどにアクセスしようとするとどうなるでしょうか?
コードで書くと以下のようになります。
PlayerStatus status;
status.SetParameters(100, 5);
結果は普通にエラーが出ます。
これだけでは、PlayerStatus型の変数を宣言しただけで実体(インスタンス)は生成されないです。
よって、無理にアクセスしようとエラーが出てしまうというわけですね。
ですのでくれぐれも 忘れずにインスタンスの生成をしてください。
ではUnityの方にも記述していきましょう!
Player.csで以下のように変更してください。
Start()の中でインスタンスを生成して、Update()の中でメソッドにアクセスするようにしました。
using UnityEngine;
public class Player : MonoBehaviour
{
private PlayerStatus _status;
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
_status = new PlayerStatus(); // インスタンス生成
_status.SetParameters(100, 10); // メソッドの実行
}
// Update is called once per frame
void Update()
{
if (Input.GetKey(KeyCode.UpArrow))
{
transform.Translate(Vector3.up * Time.deltaTime);
}
if (Input.GetKey(KeyCode.DownArrow))
{
transform.Translate(Vector3.down * Time.deltaTime);
}
if (Input.GetKey(KeyCode.LeftArrow))
{
transform.Translate(Vector3.left * Time.deltaTime);
}
if (Input.GetKey(KeyCode.RightArrow))
{
transform.Translate(Vector3.right * Time.deltaTime);
}
if (Input.GetKey(KeyCode.Z))
{
Debug.Log($"HP: {_status.GetHp()}, Attack: {_status.GetAttack()}"); // メソッドの実行
}
}
}
まとめ
この記事ではオブジェクト指向プログラミングの本当の基礎の基礎を勉強していきました。
色々な用語が出てきたと思いますが、とりあえず今回理解して欲しいのは オブジェクト指向プログラミングの考え方 です!
イメージが湧かないな...と感じている人もいるかもしれないですが、それでも大丈夫です!
だんだん使うにつれて慣れてくると思うので、少しずつ勉強していきましょう!
それではお疲れ様でした!






