このブログで使用しているUnityのVer
・Unity 2022.3.19f1
はじめに
おはこんにちばんわ!24時間体制でゲームを作ってます。嘘です。えきふるです。
今回はメソッド。
そう、UnityでC#スクリプトを作成すると最初から記載されてる「void Start()」とか「void Update()」とかの事です。
とりあえずここに処理を記載すればゲームスタート時に実行されるのと、マイフレーム毎に実行される事はわかってるけど、メソッドからメソッドに値を渡したりとか、そもそもこの2種類以外のメソッドを作ってなんか記述して、とかになると途端に訳わからん。
そんな経験しかありません。(・・・え?私だけじゃないよね?)
そこで今回はこのメソッドに関して基本的な部分を確認しながら、その仕様を把握していきましょう!
これでストレスフリーでメソッド作り放題だ!
メソッド(method)の基本
そもそもメソッドとはなんでしょうか?
メソッドとはClass(クラス)の内部にある、特定の処理や機能をまとめたブロックのことです。
決まった処理をひとまとまりにすることで再利用をしやすく、わかりやすくしてあるんですね。
なお、Class(クラス)に関しては下記の記事で詳しく書いてあります。
メソッドの基本構造
それでは、メソッドの基本構造を見ていきましょう。
一般的には下記のような構造で記述されます。
アクセス修飾子 戻り値の型 メソッド名(引数)
{
処理内容
}
このように4つの定義(アクセス修飾子、戻り値(型)、メソッド名、引数)とその処理内容によって構成されています。
「アクセス修飾子」だとか「戻り値」だとか独特でわかりにくいものが多いですが、この後1つ1つ一緒に丁寧に見ていきましょう!
またメソッドは「呼び出された時」に、その処理内容が実行される形になっています。
Unityのvoid Start()はゲームプレイ時に「呼び出される」メソッドということふるね〜
アクセス修飾子
アクセス修飾子は変数を作成するときに使う「public」などの事です。
public int a; //この例はメソッドではなく変数
これらは「アクセスできる範囲」を決めることができるキーワードになります。
主に使うのは下記3つになるかと思います。
public
この修飾子がついたメンバーをどこからでもアクセス可能にする。他のクラスからもアクセス可能。
private
定義されたクラス内でのみアクセス可能にする。他のクラスからはアクセス不可。
※アクセス修飾子の記載が無いメソッドはデフォルトでこの「private」として処理されます。
protected
定義されたクラスと、その派生クラスでのみアクセス可能。
※派生クラスに関しては上記にリンクしたClassの記事で説明しています。
戻り値
「戻り値」とはメソッドの処理をした結果をメソッドの呼び出し元に返す値のことです。
例えば下記のようなスクリプトで見て見ましょう。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Testmethod : MonoBehaviour
{
void Start()
{
int result = Test(); //Testメソッドを処理させてその結果をresultに代入
Debug.Log(result);
}
int Test() //戻り値の型を「int」で指定
{
return 5; //int型の値「5」を返す
}
}
この時
int Test() //戻り値の型を「int」で指定
ここで記述している「int」が「戻り値の型」です。
つまりこのメソッドで処理の結果出るのは「int」型だよ、と示している事になります。
メソッドの処理結果として値を返す場合は下記のように記載します。
return 戻り値;
サンプルの場合はTestメソッド内に記載してある
return 5; //int型の値「5」を返す
になります。
そしてvoid Start()メソッド内の
int result = Test(); //Testメソッドを処理させてその結果をresultに代入
部分で、Test();にてTestメソッドの処理を実行、その結果(戻り値)をresultに代入。
その結果をDebug.LogでUnityのコンソールに表示させています。
戻り値のイメージを単純にすると下記のようなイメージですね。
このスクリプトをUnity上の適当なオブジェクトにアタッチしてゲームプレイするとコンソールに正しく表示されました!
TIPS:voidってなに?
ところで、 サンプルのStart()メソッドを見てみると
void Start()
という風に「void」という戻り値の型がついてます。
※アクセス修飾子は記載がなければ勝手に「private」になるのでこのメソッドはprivateメソッドです。
では、この「void」とはなんなのか?
この「void」が「戻り値の型」に定義されたメソッドはメソッド内の処理を実行するだけで、戻り値として値は返しません。
メソッドの処理だけが必要で、その結果の値は必要がない(もしくは値がそもそも無い)ときはこの型を使います。
例えば攻撃アクションをするだけ、とかの場合は値は必要ないですよね。
TIPS:Unityじゃ無い場合(MonoBehaviourを継承しないクラス)のメソッドの呼び出し
メソッドを呼び出して処理させる記述を
int result = Test(); //Testメソッドを処理させてその結果をresultに代入
と一文だけで記述しましたが、これはUnityのみに限ります。
普通はスクリプト内で一度クラスをインスタンス化してからメソッドを呼び出す必要があります。
メソッドの呼び出し方は下記のように記述します。
インスタンス名.メソッド名(); //インスタンスメソッドの場合
クラス名.メソッド名(); //静的メソッドの場合はインスタンス化が必要ない。
戻り値のサンプルコードをMonoBehaviour
を継承せずに記述すると↓こんな感じになるかと思います。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Testmethod2 //ここのMonoBehaviour無し
{
int a;
void Start()
{
Testmethod2 testMethod = new Testmethod2(); // ここでクラスをインスタンス化させる
int result = testMethod.Test(); //インスタンス名.メソッド名();で処理したメソッドの戻り値をresultに代入
Debug.Log(result);
}
int Test()
{
return 5;
}
}
Unityではシーンにゲームオブジェクトが読み込まれると、そのオブジェクトにアタッチされたMonoBehaviour
を持つクラスは自動でインスタンス化されるため、記述ではインスタンス化を省略できます。
(というかMonoBehaviour
を継承したスクリプトでインスタンス化するとエラーになる)
クラスのインスタンス化や静的メソッド、MonoBehaviour
の継承に関しては下記記事にて説明してあります。
メソッドの処理の結果を「戻り値」、戻り値としてメソッドに出力したい値はreturnを使うんだね!
引数
メソッドには何かしら指定されたパラメーターを受け取り、そのデータを使ってメソッド内の処理をするものがあります。
この時、メソッドに渡されるデータのことを引数(ひきすう)と言います。
具体的にスクリプトで見ていきましょう。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestHikisuu : MonoBehaviour
{
int a;
int b;
void Start()
{
a = 5;
b = 3;
int result = Hikisuu(a,b);//メソッドを呼び出す、この時(a,b)で実パラメーター(引数)を渡す
Debug.Log(result);
}
public int Hikisuu(int c,int d)//仮のパラメーターを引数として設定しておく
{
int e = c + d;
return e; //処理した結果を戻り値として戻す
}
}
まず、スクリプト下部に書いてあるメソッドを先に見ましょう。
public int Hikisuu(int c,int d)//仮のパラメーターを引数として設定しておく
ここでメソッドを宣言したHikisuu()の()の中にint型のcとdを引数として設定します。
「ここに記載したcとdは他所から受け取るよ」と言っている状態です。
これはまだ中身のない箱のようなものですがこれを「仮パラメーター」と呼びます。
ちなみに、複数の引数を設定する場合は「カンマ(,)」で区切ります。
今回はint型で設定していますがstring等、他の型もちろん引数の設定は出来ます。
また、アクセス修飾子「Public」が指定されているので他のメソッドから呼び出す事が出来ます。
そしてその下の
int e = c + d;
return e; //処理した結果を戻り値として戻す
の部分で「c」と「d」を使い「e」の処理をして結果を戻り値として戻しています。
次にスクリプト上部のvoid Start()のメソッドを見てみましょう。
void Start()
{
a = 5;
b = 3;
int result = Hikisuu(a,b);//メソッドを呼び出す、この時(a,b)で実パラメーター(引数)を渡す
Debug.Log(result);
}
この時、aとbという変数にそれぞれ5、3という数値を代入した後の
int result = Hikisuu(a,b);//メソッドを呼び出す、この時(a,b)で実パラメーター(引数)を渡す
ここの部分で、Hikisuu(a,b);でHikisuuメソッドの処理を実行、その際に引数としてa,bを渡します。
このa,bはHikisuuメソッドを宣言した時の下記の赤文字部分c,dと連動しています。
public int Hikisuu(int c,int d)//仮のパラメーターを引数として設定しておく
つまり、c,dという仮パラメーターに実パラメーターとしてa,bを入れて、メソッドを処理させている、ということです。
最後に、メソッドが処理した結果(戻り値)をresultに代入します。(戻り値でやったことと同じですね。)
その結果をDebug.Logでコンソールに表示させます。
実際に、Unity上の適当なオブジェクトにこのスクリプトをアタッチしてゲームプレイすると下記の用に正しい計算処理をされた値がコンソールに表示されました!
このように、引数は外部からデータを受け取る形にすることでメソッドの処理が柔軟になります。
引数を使えるとダメージ計算などが処理しやすくなりそうだね!
メソッドの具体的な使い方
それでは、今までの内容のまとめとして、戻り値と引数を使って具体的な使い方を見てみましょう。
サンプルとして、ターン制のバトルをイメージして、敵の攻撃によってプレイヤーのHPが減る処理を戻り値と引数を作って作成してみました。
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DamageCalculator : MonoBehaviour
{
public int PlayerHP = 100;
//スタートと同時に攻撃処理のメソッドが走る
void Start()
{
int damage =DamageCal(50,10);
PlayerHP = HpCal(PlayerHP,damage);
Debug.Log(PlayerHP);
}
//ダメージ計算用メソッド
public int DamageCal(int attack,int defence)
{
int damage = Mathf.Max(attack-defence,0);
return damage;
}
//HP計算用メソッド
public int HpCal(int currentHP,int damage)
{
int HP = Mathf.Max(currentHP-damage,0);
return HP;
}
}
まずはダメージ計算用のメソッドから見てみましょう。
//ダメージ計算用メソッド
public int DamageCal(int attack,int defence)
{
int damage = Mathf.Max(attack-defence,0);
return damage;
}
このメソッドでは引数の仮パラメーターとしてint型のattack(敵の攻撃力)とdefence(プレイヤーの守備力)を設定しています。
そしてメソッド内の処理
int damage = Mathf.Max(attack-defence,0);
でint型のdamageとして「attack(攻撃力)-defence(守備力)」の計算をして「return」でdamageを戻り値として返しています。
なお、ここで使っている「Mathf.Max」という関数ですがこれは
値の型 maxValue = Mathf.Max(value1, value2);
という記述の仕方をして、value1、value2の値の大きい方を返すという関数処理になっています。
ここではdamageがマイナス値にならないよう、0を最大補償ダメージとしています。
(ダメージがマイナスになると回復してしまいますもんね!)
次にHP計算メソッドを見てみましょう。
//HP計算用メソッド
public int HpCal(int currentHP,int damage)
{
int HP = Mathf.Max(currentHP-damage,0);
return HP;
}
ここはダメージ計算メソッドと全く同じ処理をしています。
まずメソッドの引数としてint型のcurrentHP(現在のHP)、damage(実際のダメージ値)を設定します。
ここでのdamageは先ほどのダメージ計算メソッドでの戻り値をイメージしています。
次に
int HP = Mathf.Max(currentHP-damage,0);
でHPとして「currentHP(現在のHP)ー damage(実際のダメージ値)」の計算。
Mathf.Max関数を使って0未満、マイナスの値にならないようにしています。
最後にreturnでHPを戻り値として返しています。
最後に、一番上に書いてあるスタート時(ここでは攻撃時をイメージ)に処理をするメソッドを確認してみましょう。
public class DamageCalculator : MonoBehaviour
{
public int PlayerHP = 100;
//スタートと同時に攻撃処理のメソッドが走る
void Start()
{
int damage =DamageCal(50,10);
PlayerHP = HpCal(PlayerHP,damage);
Debug.Log(PlayerHP);
}
まず、
public int PlayerHP = 100;
でプレイヤーのHPを設定しました。
次にStart()メソッド内の
int damage =DamageCal(50,10);
でint型のdamageという変数にDamageCalメソッドに(50,10)という引数のじつパラメーターを渡して処理した結果(戻り値)を代入します。
ここでのDamageCalメソッドは先ほどのダメージ計算処理のメソッドになるので、(int attack,int defence)の仮パラメーターに(50,10)を入れて処理をさせた、という意味になります。
続いて
PlayerHP = HpCal(PlayerHP,damage);
ここでも同様にメソッド外のクラスで最初に宣言したPlayerHP(フィールド、もしくはメンバー変数と言います)
に対してHpCalメソッドに(PlayerHP,damage)という引数の実パラメーターを渡して処理します。
少し複雑ですがPlayerHPは現在のHPそのもの、damageは先ほどダメージ計算メソッドで処理した結果になります。
つまりこの処理でPlayerHPをダメージ処理に基づいて上書きしています。
HpCalメソッドはHP計算用のメソッドで
ここでは仮パラメーター(int currentHP,int damage)に(PlayerHP,damage)を代入して処理していますね。
(先ほどのdamageと同じ流れですね)
最後に
Debug.Log(PlayerHP);
でコンソールに攻撃をされた後のHPを表示させます。
このスクリプトをUnityで適当なオブジェクトにアタッチさせてゲームプレイすると下記のように表示されました!
計算結果もあっていますね。
今回、サンプルではHPや攻撃力をスクリプト内にそのまま記載していますが、キャラ毎、モンスター毎の固有のステータスは外部で別に保持しておき、引数として呼び出して戦闘計算メソッドを走らせ、また元の外部データに戻す事で1つのスクリプトで戦闘処理をする事も出来そうですね。
これにてメソッドの説明を終わりにしますふる!
終わりに
今回はUnity C#の基本であるメソッドに関して見ていきました。
戻り値や引数を理解することで最初から記載してあるStart/Updateメソッド以外にもさまざまな処理を使える事ができるようになりそうです。
これでゲームのシステム作りの幅もとっても広がること間違いなし!!一緒に頑張りましょう〜。
コメント貰えると元気も出ますので、どうぞお気軽にお願いしますふる!
※このブログは、UnityTechnologiesまたはその関連会社が後援または提携しているものではありません。「Unity」は、UnityTechnologiesまたはその関連会社の米国およびその他の国における商標または登録商標です。
コメント