InputActionAsset
⇒PlayerInputComponent
⇒GameObject
🧠 デリゲートとは?
**デリゲート(delegate)**は、簡単に言うと「関数を変数として扱える仕組み」です。
- 通常、変数には数値や文字列を入れますよね?
- デリゲート変数には「関数(メソッド)」を入れることができます。
つまり、**「この変数を呼び出すと、登録された関数が実行される」**というような使い方ができます。
🔧 例(C#の場合)
// デリゲートの定義
delegate void MessageDelegate(string message);
// 関数の定義
void Hello(string msg) {
Console.WriteLine("Hello: " + msg);
}
// デリゲート変数に関数を代入
MessageDelegate del = Hello;
// 呼び出し
del("World"); // → Hello: World
この例では、MessageDelegate
という型の変数 del
に Hello
関数を代入しています。del("World")
と呼び出すと、Hello("World")
が実行されるわけです。
🧩 どんなときに使うの?
- イベント処理(ボタンを押したときの動作など)
- コールバック関数(処理が終わった後に呼ばれる関数)
- 柔軟な設計(関数を引数として渡したり、動的に切り替えたり)
🌀 他の言語では?
- Pythonでは「関数は第一級オブジェクト」なので、普通に変数に代入できます。
- Javaでは「関数型インターフェース」や「ラムダ式」で似たようなことができます。
ゆきさんの関心領域(C言語や抽象化)に照らすと、デリゲートは「関数ポインタの高級版」とも言えます。C言語の void (*func)(int)
のような関数ポインタを、より安全かつ柔軟に扱えるようにしたものがデリゲートです。(by Copilot)
y軸の移動も組み込む。
using Unity.Collections;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.InputSystem;
public class Player : MonoBehaviour
{
[Header("---Base Parameter")]
public float moveSpeed = 5.0f;
[Header("---Bullet Settings---")]
public GameObject bulletPrefab;
public float shotPower = 10f;
[Header("=== Input Setting")]
public InputActionReference moveInput;
public InputActionReference fireInput;
public PlayerInput playerInput;
private Vector2 _moveInputValue;
private float _fireInputValue;
[HideInInspector] public Rigidbody2D bulletRb; // Rigidbodyの参照
void Start()
{
moveInput.action.performed += MoveInputActionPerformed;
moveInput.action.canceled += MoveInputActionCanceled;
}
private void MoveInputActionPerformed(InputAction.CallbackContext context)
{
_moveInputValue = context.ReadValue<Vector2>();
}
private void MoveInputActionCanceled(InputAction.CallbackContext context)
{
_moveInputValue = Vector2.zero;
}
void Update()
{
transform.Translate(_moveInputValue.x * moveSpeed * Time.deltaTime, _moveInputValue.y * moveSpeed *Time.deltaTime, 0);
/*
if (Input.GetKey(KeyCode.LeftArrow) | Input.GetKey(KeyCode.A))
{
transform.Translate(-moveSpeed * Time.deltaTime, 0, 0);
}
if (Input.GetKey(KeyCode.RightArrow)|Input.GetKey(KeyCode.D))
{
transform.Translate(moveSpeed*Time.deltaTime, 0, 0);
}
if (Input.GetKeyDown(KeyCode.Space))
{
GameObject bullet = Instantiate(bulletPrefab, this.transform.position, Quaternion.identity);
bulletRb = bullet.GetComponent<Rigidbody2D>(); // Rigidbody2Dを取得してbulletRbに代入
//AddForce(飛ばす方向と力、飛ばすときのモード指定)
bulletRb.AddForce(new Vector2(0, 1) * shotPower, ForceMode2D.Impulse); // Rigidbody2Dに力を加える
}
*/
}
}
弾の射出を組み込む。
using System;
using System.Security.Cryptography;
using Unity.Collections;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;
public class Player : MonoBehaviour
{
[Header("---Base Parameter")]
public float moveSpeed = 5.0f;
[Header("---Bullet Settings---")]
public GameObject bulletPrefab;
public float shotPower = 10f;
public float shotInterval = 0.5f; //発射間隔
private float _shotIntervalTimer = 0f; //発射間隔タイマー
[Header("=== Input Setting")]
public InputActionReference moveInput;
public InputActionReference fireInput;
public PlayerInput playerInput;
private Vector2 _moveInputValue;
private float _fireInputValue;
[HideInInspector] public Rigidbody2D bulletRb; // Rigidbodyの参照
void Start()
{
moveInput.action.performed += MoveInputActionPerformed;
moveInput.action.canceled += MoveInputActionCanceled;
fireInput.action.performed += FireInputActionPerformed;
fireInput.action.canceled += FireInputActionCanceled;
}
private void MoveInputActionPerformed(InputAction.CallbackContext context)
{
_moveInputValue = context.ReadValue<Vector2>();
}
private void MoveInputActionCanceled(InputAction.CallbackContext context)
{
_moveInputValue = Vector2.zero;
}
private void FireInputActionPerformed(InputAction.CallbackContext context)
{
_fireInputValue = context.ReadValue<float>();
}
private void FireInputActionCanceled(InputAction.CallbackContext context)
{
_fireInputValue = 0f;
}
private void ShootBullet()
{
GameObject bullet = Instantiate(bulletPrefab, transform.position, Quaternion.identity);
bulletRb = bullet.GetComponent<Rigidbody2D>();
bulletRb.AddForce(Vector2.up * shotPower, ForceMode2D.Impulse);
Destroy(bullet, 3f); // 3秒後に自動で破棄
}
void Update()
{
transform.Translate(_moveInputValue.x * moveSpeed * Time.deltaTime, _moveInputValue.y * moveSpeed * Time.deltaTime, 0);
/*
if (Input.GetKey(KeyCode.LeftArrow) | Input.GetKey(KeyCode.A))
{
transform.Translate(-moveSpeed * Time.deltaTime, 0, 0);
}
if (Input.GetKey(KeyCode.RightArrow)|Input.GetKey(KeyCode.D))
{
transform.Translate(moveSpeed*Time.deltaTime, 0, 0);
}
if (Input.GetKeyDown(KeyCode.Space))
{
GameObject bullet = Instantiate(bulletPrefab, this.transform.position, Quaternion.identity);
bulletRb = bullet.GetComponent<Rigidbody2D>(); // Rigidbody2Dを取得してbulletRbに代入
//AddForce(飛ばす方向と力、飛ばすときのモード指定)
bulletRb.AddForce(new Vector2(0, 1) * shotPower, ForceMode2D.Impulse); // Rigidbody2Dに力を加える
}
*/
_shotIntervalTimer += Time.deltaTime;
if (_fireInputValue >= 0.5f)
{
//発射間隔を過ぎていたら弾を発射
if (_shotIntervalTimer >= shotInterval)
{
ShootBullet();
//発射間隔タイマーリセット
_shotIntervalTimer = 0f;
}
}
}
}
[IsTrigger]
Colliderを使っていると、通常、接触した場合に物理エンジンの挙動に沿って「弾き飛ばされる」動きになる。
Colliderに「IsTrigger」をつけると、接触しても物理挙動をせずに「判定」だけとれるようになる。
※ただし
OnCollisionEnter2DとかOnCollisionStay2Dとか、Collision系のメソッドが効かなくなる。
代わりにOnTriggerEnter2Dなどを使うことになる。
[Tag]
if (collision.transform.tag == “Bulleet”)
⇒”Bullet”とタグが完全一致した場合のみ引っかかる。
if(collision.transform.tag.Contains(“Bullet”))
⇒”Bullet”が含まれるタグを判別する。”EnemyBullet”にも引っかかる。
BulletPrefabにTagを設定する。

このとき、Bullet/Normalなどとすると、Bullet内でTagを細かく分類することができる。

using UnityEngine;
public class Enemy : 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()
{
}
//Collider同士が接触した”瞬間(フレーム)”に実行される関数
/*void OnCollisionEnter2D(Collision2D collision)
{
//OnCollisionEnter2D内の引数であるcollisionには、衝突したオブジェクトの情報(Collision2D)が入る
Debug.Log($"HIT!...{collision.transform.name}");
Destroy(gameObject);//接触で削除される
Destroy(collision.gameObject);//接触した相手のオブジェクトも削除する
}
*/
private void OnTriggerEnter2D(Collider2D collision)
{
if(collision.transform.tag.Contains("Bullet"))
{
Destroy(gameObject);
}
}
}
弾が画面外に出たら破棄されるスクリプトを追加。
Destroyも、Enemy.csから移動する。BulletPrefabにアタッチ。
(Bullet.cs)
using UnityEngine;
public class Bullet : MonoBehaviour
{
void Update()
{
if (Mathf.Abs(transform.position.y) > 10f) // 画面外に出たら
{
Destroy(gameObject);
}
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.CompareTag("Enemy"))
{
Destroy(collision.gameObject); // 敵を破壊
Destroy(gameObject); // 弾も消える
}
}
}
[継承]
親から子に、変数とメソッドの機能を引き継がせる機能。
この機能を使って、敵の種類を増やしていく。
EnemyPrefab一つだったものをEnemy0PrefabとEnemy1Prefabに拡張。
BossEnemy.csを作って、Enemy1にアタッチ。

Enemy.cs、BossEnemy.csは、「子」に当たる。親に当たるクラス「BaseEnemy.cs」を作成する。
「子」の側のクラス名の後に「BaseEnemy」を書くだけ。
これで「親」側で作ったメソッドや変数等を、「子」の側でそのまま使うことができる。
public class BaseEnemy : MonoBehaviour⇒ここが「親」を書く部分
public class Enemy : BaseEnemy
public class BossEnemy : BaseEnemy
なお、EnemyとBossEnemyからはMonoBehaviourが消えるが、BaseEnemyの親はMonoBehaviourになるので、「親」経由で継承されることになる。
コメント