【UNITY3Dをゼロから学ぶ超入門書: DAY3】C#プログラムの基礎を徹底解説!!【FPS開発】
❏ はじめに ❏
閲覧ありがとうございます。はじめまして、ゲーム開発所RYURYUの”りゅうや”と申します。
❏ インプット講義 ❏
「いつ(トリガー)」
InputSystemとは。
アクションマップ (Action Map)
アクションマップは、関連するアクションの集まりを管理するコンテナのようなものです。
一つのアクションマップは特定のゲームプレイのコンテキスト(例えば、「メニュー選択中」や「バトル中」)に特化することができ、レイヤーが異なる状況下で異なる入力方法を持つことが可能です。
アクションマップを切り替えることで、ゲームの状態に応じて入力の挙動を動的に変更することができます。
アクション (Action)
アクションはプレイヤーの入力に対する具体的な反応を定義します。例えば、「ジャンプ」や「射撃」といった行動がアクションに該当します。
各アクションは一つ以上のバインディングを持ち、特定のキーやボタンに対応します。アクションを使用することで、コード内で直接キーコードを扱うことなく、入力を管理することができます。
バインディング
バインディングは、特定のアクションを具体的なデバイスのボタンやキー、あるいはマウスの動きなどに結び付けます。
これにより、どのボタンがどのアクションをトリガーするかを定義でき、多様な入力デバイスに対応可能です。
また、バインディングはユーザによるカスタマイズが容易であるため、プレイヤーが自分の好みに合わせてキー配置を変更することができます。
具体例
アクションマップ「Player」には、「Move」というアクションが含まれており、このアクションにはキーボードの「WASD」キーがバインドされています。
つまり、プレイヤーがWASDキーを使用して入力を行うと、その情報が「Move」アクションに送られます。
この設定を基にプログラムを作成することにより、入力に応じて適切な反応を返すインタラクティブなゲームを開発することが可能です。
// このメソッドはプレイヤーの移動入力を処理します
public void OnMove(InputAction.CallbackContext context)
{
// 入力が実行されたとき(例えばWASDキーが押されたとき)、以下のコードブロックが実行されます
if (context.performed)
{
// コンソールにログを出力し、移動が開始されたことを表示します
Debug.Log("移動が開始されました!");
}
}
Unityのライフサイクル
Unityのライフサイクルは、特定のメソッドが特定の順序で自動的に呼ばれることによってゲームの動作が制御されます。
1. Awake
Awake メソッドは、スクリプトインスタンスがロードされたときに一度だけ呼ばれます。このメソッドは、ゲームオブジェクトが有効になる前、他のオブジェクトとの関連付けや初期設定に適しています。
2. Start
Start メソッドは、Awake メソッドの直後に、スクリプトがアクティブになったときに一度だけ呼ばれます。主に、初期化処理に使用され、Awake で設定されたパラメータに基づいてのセットアップを行います。
3. Update
Update メソッドは、毎フレーム呼ばれます。このメソッドはゲームの主要なロジック、例えばユーザー入力の処理やオブジェクトの動き、時間に依存したチェックなどを行うのに使われます。
4. FixedUpdate
FixedUpdate メソッドは、物理計算のアップデートごとに定期的に呼ばれます。このメソッドは一定の間隔で実行されるため、物理演算やその他の間隔を要する処理に適しています。
5. LateUpdate
LateUpdate メソッドは、すべてのUpdate メソッドが呼び出された後に毎フレーム呼ばれます。カメラの追従など、他のオブジェクトに依存する動作を実装するのに適しています。
6. OnDestroy
OnDestroy メソッドは、ゲームオブジェクトが破棄される直前や、スクリプトが非アクティブ/破棄されるときに呼ばれます。リソースのクリーンアップや、他のオブジェクトへの最後の通知を行うのに役立ちます。
using UnityEngine;
public class LifecycleExample : MonoBehaviour
{
// Awakeメソッド: オブジェクトがロードされた時に一度だけ呼ばれる
void Awake()
{
Debug.Log("Awake called: オブジェクトのロード時に初期設定を行います");
}
// Startメソッド: オブジェクトが初めてアクティブになるときに一度だけ呼ばれる
void Start()
{
Debug.Log("Start called: オブジェクトの初期化処理をここで行います");
}
// Updateメソッド: 毎フレーム呼ばれる
void Update()
{
Debug.Log("Update called: フレームごとの更新処理をここで行います");
}
// FixedUpdateメソッド: 一定間隔で呼ばれる(物理演算用)
void FixedUpdate()
{
Debug.Log("FixedUpdate called: 物理演算の更新処理をここで行います");
}
// LateUpdateメソッド: すべてのUpdateメソッドが呼ばれた後に毎フレーム呼ばれる
void LateUpdate()
{
Debug.Log("LateUpdate called: 他のアップデート処理の後に行う処理をここで行います、例えばカメラの追従など");
}
// OnDestroyメソッド: オブジェクトが破壊される直前に呼ばれる
void OnDestroy()
{
Debug.Log("OnDestroy called: オブジェクトが破壊される前にクリーンアップを行います");
}
}
UGUI(Unity GUI)
エディタから設定可能なGUIシステムで、主にゲーム内UIに使用されます。
シーン内にCanvasオブジェクトを設置し、その上にButton、Text、ImageなどのUIコンポーネントを配置して構築します。
Buttonコンポーネント
インタラクション: ユーザーがクリックすることで特定のアクションをトリガーするUI要素です。
カスタマイズ可能: 背景色、テキスト、画像などをカスタマイズして視覚的に調整できます。
イベントハンドラー: `OnClick()`イベントを使用して、クリック時に呼び出されるメソッドを指定できます。
Textコンポーネント
表示用途: ゲーム内で文字情報を表示するために使用されます。
スタイリング: フォント、サイズ、カラー、アラインメントなどのスタイリングオプションが豊富です。
ダイナミックテキスト: スクリプトからテキスト内容を動的に更新することが可能です。
Imageコンポーネント
画像表示: スプライトやテクスチャをUI要素として表示するために用います。
変形可能: 画像のサイズやアスペクト比を自由に調整できます。
マスキング: 他のUIコンポーネントと組み合わせて、特定の形状で画像をマスクすることが可能です。
「どうしたら(条件)」
制御文
制御文は、プログラムのフローを制御し、特定の条件に基づいて異なるアクションを実行するために使用されます。
演算子
Unityでゲームロジックを記述する際、様々な種類の演算子を利用して条件式を評価します。
比較演算子
比較演算子は、二つの値を比較し、その比較結果に基づいて真 (true) または偽 (false) を返します。これらは条件分岐(if文など)の決定に頻繁に使用されます。
int score = 85;
if (score >= 50)
{
Debug.Log("Passed");
}
論理演算子
論理演算子は、一つまたは複数のブール条件式を組み合わせて評価し、最終的な真偽値を導き出します。これにより、より複雑な条件を表現することが可能になります。
bool hasKey = true;
bool isDoorLocked = true;
if (hasKey && isDoorLocked)
{
Debug.Log("You can open the door");
}
if文
`if` 文は、指定された条件が真(true)である場合にのみ、ブロック内のコードを実行します。例えば、プレイヤーの体力が0以下になったかどうかをチェックする場合に使用されます。
if (playerHealth <= 0)
{
Debug.Log("Player is dead.");
}
if文-else文
`if-else` 文は、条件が真の場合と偽の場合で異なるアクションを実行します。これにより、より複雑な決定をスクリプトに組み込むことができます。
if (playerHealth > 0)
{
Debug.Log("Player is alive.");
}
else
{
Debug.Log("Player is dead.");
}
Ray判定
Ray判定は、3D空間での視線や射撃の軌道をシミュレートする強力なツールです。`RaycastHit` オブジェクトを使用して、レイが何かと交差したかどうかを検出します。
RaycastHit hit;
if (Physics.Raycast(transform.position, transform.forward, out hit, 100))
{
Debug.Log("Hit: " + hit.collider.name);
}
Ray判定は、視線がクリックされたオブジェクトに到達するかどうかを確認したり、射撃ゲームでターゲットを狙ったりする際に特に有用です。
「何をするのか?(アクション)」
1. オブジェクトの生成・破壊
オブジェクトの生成
Unityでオブジェクトを生成するには、Instantiateメソッドを使用します。
using UnityEngine;
public class ObjectSpawner : MonoBehaviour
{
public GameObject objectToSpawn; // 生成するオブジェクトのプレハブ
void Start()
{
// 指定された位置と回転でオブジェクトを生成
Instantiate(objectToSpawn, new Vector3(0, 0, 0), Quaternion.identity);
}
}
オブジェクトの破壊
オブジェクトを破壊するには、Destroyメソッドを使用します。
using UnityEngine;
public class ObjectDestroyer : MonoBehaviour
{
public GameObject objectToDestroy; // 破壊するオブジェクト
void Start()
{
// オブジェクトを破壊
Destroy(objectToDestroy, 2.0f); // 2秒後にオブジェクトを破壊
}
}
2. コンポーネントの取得
Unityでコンポーネントを取得するには、GetComponentメソッドを使用します。
using UnityEngine;
public class ComponentGetter : MonoBehaviour
{
private Rigidbody rb;
void Start()
{
// このゲームオブジェクトのRigidbodyコンポーネントを取得
rb = GetComponent<Rigidbody>();
}
void Update()
{
if (rb != null)
{
// Rigidbodyコンポーネントを使用して操作を行う
rb.AddForce(Vector3.up * 10);
}
}
}
3. オブジェクト・コンポーネントの表示・非表示
オブジェクトやコンポーネントを表示・非表示にするには、SetActiveメソッドやenabledプロパティを使用します。
using UnityEngine;
public class VisibilityToggler : MonoBehaviour
{
public GameObject targetObject;
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
// オブジェクトの表示・非表示を切り替え
targetObject.SetActive(!targetObject.activeSelf);
}
}
}
4. オブジェクトの移動・回転・拡大
オブジェクトの移動、回転、拡大は、Transformコンポーネントを通じて行います。
移動
using UnityEngine;
public class ObjectMover : MonoBehaviour
{
public float speed = 5.0f;
void Update()
{
float move = speed * Time.deltaTime;
transform.Translate(Vector3.forward * move);
}
}
回転
using UnityEngine;
public class ObjectRotator : MonoBehaviour
{
public float rotationSpeed = 100.0f;
void Update()
{
float rotation = rotationSpeed * Time.deltaTime;
transform.Rotate(Vector3.up, rotation);
}
}
拡大
using UnityEngine;
public class ObjectScaler : MonoBehaviour
{
public float scaleSpeed = 2.0f;
void Update()
{
float scale = 1 + scaleSpeed * Time.deltaTime;
transform.localScale *= scale;
}
}
結論
これらの基本的な操作を組み合わせることで、Unityでゲームオブジェクトの管理や操作を行うことができます。各スクリプトは独立して動作しますが、実際のゲーム開発ではこれらを組み合わせて複雑な挙動を実現します。
❏ インプットテスト ❏
1.InputSystemとは。
ゲーム内でのキャラクターの動きを制御するシステム
プレイヤーの入力を処理するためのUnityの新しいシステム
ゲームのグラフィックを向上させるためのツール
2.UnityのUpdateメソッドについての説明として正しいものはどれですか。
Updateメソッドは物理演算の更新ごとに一定間隔で呼ばれます。
Updateメソッドは毎フレーム呼ばれ、ゲームの主要なロジックを処理します。
Updateメソッドはゲームオブジェクトが破壊される直前に呼ばれます。
3.A && B の結果は何ですか?
const bool A = true;
const bool B = false;
Debgu.Log(A&&B);
true
false
null
4. if 文についての説明として正しいものはどれですか。
if 文は条件が偽(false)の場合にのみコードを実行します。
if 文は条件が真(true)の場合にのみコードを実行します。
if 文は条件に関係なく常にコードを実行します。
5.以下のコードが実行された際に出力されるデバッグログを特定してください。
const bool A = true;
const bool B = false;
if (A || B)
{
Debug.Log("パターン1");
}
else if (A && B)
{
Debug.Log("パターン2");
}
else
{
Debug.Log("パターン3");
}
パターン1
パターン2
パターン3
6..Rayを使った当たり判定で正しい記述はどれですか。
Rayはゲームオブジェクトに直接影響を与える物理オブジェクトです。
Ray判定はレイが何も交差しない場合にのみ使用されます。
Ray判定は3D空間でレイがオブジェクトと交差するかを検出する方法です。
❏ インプットテストの解答 ❏
プレイヤーの入力を処理するためのUnityの新しいシステム
Updateメソッドは毎フレーム呼ばれ、ゲームの主要なロジックを処理します。
false
if 文は条件が真(true)の場合にのみコードを実行します。
パターン1
Ray判定は3D空間でレイがオブジェクトと交差するかを検出する方法です。
❏ アウトプット講義❏
「いつ(トリガー)」
InputSystemのダウンロード方法
① Window > Package Manager
② ドロップダウンで、Unity Registryを選択
③ 検索バーからInputSystemを検索
InputActionMapの作成
①Unityエディタの`Assets`メニューから`Create > Input Actions`を選択して新しいInput Actionsファイルを作成します。
②このファイルを開き、`Action Maps`セクションに新しいAction Mapを追加し、名前を付けます(例:PlayerActions)。
③アクションマップへアクションを追加する
移動: `PlayerActions`に`Move`アクションを追加し、対応する入力タイプ(例:StickやWASDキー)を設定します。
クリック: `Click`アクションを追加し、マウスの左クリックにバインドします。
Eキー: `Interact`アクションを追加し、キーボードの`E`キーにバインドします。
「どうしたら(条件)」 「何をするのか?(アクション)」
Input Systemとプログラムの紐付け
Input Action Assetをスクリプトで利用するには、まずスクリプト内で「On + アクション名(InputAction.CallbackContext context)」のメソッドを記述する。ここで、入力値(Vector2 moveInput)を更新する。更新したmoveInputを活用して実際に、Updateメソッド内で移動計算と移動処理を行う。
using UnityEngine;
using UnityEngine.InputSystem; // InputSystemを利用する場合は、必要
public class PlayerController : MonoBehaviour
{
// 移動速度を設定します
[SerializeField]
private float moveSpeed = 5f;
private Vector2 moveInput;
// 移動入力が行われたときに呼び出されるメソッド
public void OnMove(InputAction.CallbackContext context)
{
moveInput = context.ReadValue<Vector2>();
}
private void Update()
{
// 入力された方向を3D空間での移動ベクトルに変換します
Vector3 moveDirection = new Vector3(moveInput.x, 0, moveInput.y);
// 移動処理を行います
transform.position += moveDirection * moveSpeed * Time.deltaTime;
Debug.Log($"{moveDirection}の方向へ移動しています");
}
}
キー入力によるオブジェクトの生成
`E`キーを押すと特定のオブジェクトを生成する機能を追加します。
using UnityEngine;
using UnityEngine.InputSystem;
public class Hoge : MonoBehaviour
{
// 生成するプレハブを設定します
[SerializeField]
private GameObject prefab;
// インタラクト入力が行われたときに呼び出されるメソッド
public void OnInteractPerformed(InputAction.CallbackContext context)
{
// プレハブを現在の位置に生成します
Instantiate(prefab, transform.position, Quaternion.identity);
}
}
右クリックでオブジェクトを生成
マウスの右クリックでRayを飛ばし、ヒットした場所にオブジェクトを生成します。
using UnityEngine;
using UnityEngine.InputSystem;
public class Hoge : MonoBehaviour
{
public GameObject prefab; // インスタンス化するプレハブ
public void OnRightClickPerformed(InputAction.CallbackContext context)
{
// マウスの現在の位置を取得
Vector2 mousePosition = context.ReadValue<Vector2>();
// マウス位置からレイを生成
Ray ray = Camera.main.ScreenPointToRay(mousePosition);
// レイキャストを行い、ヒットした位置にプレハブをインスタンス化
if (Physics.Raycast(ray, out RaycastHit hit))
{
Instantiate(prefab, hit.point, Quaternion.identity);
}
}
}
左クリックでオブジェクトを破壊
マウスの左クリックでRayを飛ばし、ヒットしたオブジェクトを破壊します。
public void OnLeftClickPerformed(InputAction.CallbackContext context)
{
Ray ray = Camera.main.ScreenPointToRay(Mouse.current.position.ReadValue());
if (Physics.Raycast(ray, out RaycastHit hit))
{
Destroy(hit.collider.gameObject);
}
}
これらの基本をマスターすることで、Unityでのインタラクティブなゲーム環境の構築が可能になります。各ステップを詳細に理解し、実際のプロジェクトへ応用してみてください。
❏ アウトプット課題 ❏
ボタンを実装してみよう。
1. UI要素の追加
Unityエディタの階層ビュー(Hierarchy)で右クリックし、「UI」から「Button」を選択します。これにより、CanvasとButtonオブジェクトがシーンに追加されます。CanvasはUI要素を表示するための領域を提供し、Buttonはクリック可能なUI要素です。
2. ボタンの設定
追加されたボタンを選択し、インスペクター(Inspector)ビューでボタンのプロパティを確認し、必要に応じてボタンのテキストやデザインを変更します。
3. スクリプトの作成
次に、ボタンのクリックイベントを処理するためのスクリプトを作成します。プロジェクトビュー(Project)で右クリックし、「Create」->「C# Script」を選択して新しいスクリプトを作成します。スクリプトには適当な名前を付けましょう(例えばButtonHandler)。
using UnityEngine;
using UnityEngine.UI; // UI要素を扱うために必要
public class ButtonHandler : MonoBehaviour
{
public Button yourButton; // パブリック変数としてボタンを宣言
void Start()
{
yourButton.onClick.AddListener(TaskOnClick); // ボタンのクリックイベントにリスナーを追加
}
void TaskOnClick()
{
Debug.Log("You have clicked the button!"); // ボタンをクリックするとログが出力される
}
}
4. スクリプトのアタッチと設定
作成したスクリプトをCanvasにドラッグ&ドロップしてアタッチします。スクリプトのyourButton変数に、ボタンをドラッグして関連付けます。
5. 実行してテスト
Unityエディタの再生ボタンをクリックしてゲームを実行します。UIに表示されているボタンをクリックし、コンソールウィンドウにログが出力されることを確認します。
❏ アウトプット課題の解答 ❏
❏ おわりに ❏
ご不明点や疑問点がある方は、ぜひ、ゲーム開発所RYURYUの公式LINEの無料サポートをご活用ください。