2Dゲームでプレイヤーがジョイスティック(Ultimate Joystick)で移動し、自動的に弾丸を発射する機能を実装する【Unity・備忘録】

ゲーム開発
スポンサーリンク

2Dゲームでプレイヤーがジョイスティック(Ultimate Joystick)で移動し、自動的に弾丸を発射する機能を実装する

目標: 2DゲームでプレイヤーがUltimate Joystickで移動し、自動的に弾丸を発射する機能を実装する。

使用アセット:

  • Ultimate Joystick (ジョイスティック操作用)
Ultimate Joystick | Input Management | Unity Asset Store
Get the Ultimate Joystick package from Tank & Healer Studio and speed up your game development process. Find this & other Input Management options on the Unity ...

プロジェクト構成:

  • Player (ゲームオブジェクト):
    • JoystickManager スクリプト (移動制御)
    • PlayerController スクリプト (弾発射、向き制御)
    • Rigidbody2D コンポーネント
    • Sprite Renderer コンポーネント
    • タグ: Player
    • レイヤー: Player (またはプレイヤー専用のレイヤー)
  • FirePoint (空のゲームオブジェクト):
    • Player オブジェクトの子オブジェクトとして配置
    • 弾丸の発射位置と向きを示す
    • レイヤー: Default (またはプレイヤーと衝突しないレイヤー)
  • Bullet (プレハブ):
    • Bullet スクリプト (弾の移動、衝突判定)
    • Rigidbody2D コンポーネント (Gravity Scale は 0 に設定)
    • Circle Collider 2D コンポーネント (Is Trigger をオン)
    • Sprite Renderer コンポーネント
    • タグ: なし (または必要に応じて設定)
    • レイヤー: Bullet (または弾丸専用のレイヤー)
  • Enemy (プレハブ):
    • EnemyController スクリプト (敵の移動)
    • Enemy スクリプト (敵の体力、ダメージ処理)
    • Rigidbody2D コンポーネント
    • Collider2D コンポーネント
    • Sprite Renderer コンポーネント
    • タグ: Enemy
    • レイヤー: Enemy(または敵専用のレイヤー)

スクリプト:

1. JoystickManager.cs (プレイヤーの移動)

using UnityEngine;

public class JoystickManager : MonoBehaviour
{
    RectTransform mytransform;

    [SerializeField]
    float movespeed = 300f;

    void Start()
    {
        mytransform = GetComponent<RectTransform>();
    }

    void Update()
    {
        mytransform.position = mytransform.position + new Vector3(UltimateJoystick.GetHorizontalAxis("Movement"), UltimateJoystick.GetVerticalAxis("Movement"), 0) * movespeed * Time.deltaTime;
    }
}

2. PlayerController.cs (プレイヤーの弾発射、向き制御)

using UnityEngine;

public class PlayerController : MonoBehaviour
{
    public GameObject bulletPrefab;       // 弾丸のプレハブ
    public Transform firePoint;          // 弾丸の発射位置
    public float fireRate = 0.5f;        // 発射間隔(秒)
    public AudioClip shootSound;        // 発射時の効果音
    public bool isFacingRight = true;  // プレイヤーが右を向いているかどうか

    private float nextFire = 0.0f;       // 次に発射可能になる時間

    void Update()
    {
        // 自動発射処理
        if (Time.time > nextFire)
        {
            nextFire = Time.time + fireRate;
            Shoot();
        }

        // プレイヤーの向きを更新
        UpdateFacingDirection();
    }

    void Shoot()
    {
        // 弾丸を生成
        Vector3 spawnPosition = firePoint.position;
        spawnPosition.z = 0; // Z座標を0に設定
        Instantiate(bulletPrefab, spawnPosition, firePoint.rotation);

        // 効果音を再生
        if (shootSound != null)
        {
            AudioSource.PlayClipAtPoint(shootSound, transform.position);
        }
    }

    void UpdateFacingDirection()
    {
        // Joystickの水平方向の入力を取得
        float horizontalInput = UltimateJoystick.GetHorizontalAxis("Movement");

        // 入力方向に基づいてプレイヤーの向きを更新
        if (horizontalInput > 0)
        {
            isFacingRight = true;
        }
        else if (horizontalInput < 0)
        {
            isFacingRight = false;
        }

        // プレイヤーのSpriteの向きを反転させる (必要に応じて)
        if (isFacingRight)
        {
            transform.localScale = new Vector3(1, 1, 1); // 正面向き
        }
        else
        {
            transform.localScale = new Vector3(-1, 1, 1); // 反転
        }
    }
}

3. Bullet.cs (弾の移動、衝突判定)

using UnityEngine;

public class Bullet : MonoBehaviour
{
    public float speed = 20f;   // 弾丸の速度
    public Rigidbody2D rb;      // 弾丸のRigidbody2D

    void Start()
    {
        Debug.Log("弾丸生成!"); 
        // Rigidbody2Dコンポーネントを取得してrb変数に代入する
        rb = GetComponent<Rigidbody2D>();

        // プレイヤーの向きを取得
        GameObject player = GameObject.FindGameObjectWithTag("Player");
        if (player != null) {
          PlayerController playerController = player.GetComponent<PlayerController>();
          rb.velocity = playerController.isFacingRight ? transform.right * speed : -transform.right * speed;
        } else {
          rb.velocity = transform.right * speed;
        }
    }

    void OnTriggerEnter2D(Collider2D hitInfo)
    {
        // 衝突したオブジェクトの情報を取得
        Debug.Log(hitInfo.name);

        // プレイヤーとの衝突を無視する
        if (hitInfo.CompareTag("Player"))
        {
            return; // 何もせずに処理を抜ける
        }

        // 敵にダメージを与える処理 (例)
        Enemy enemy = hitInfo.GetComponent<Enemy>();
        if (enemy != null)
        {
            enemy.TakeDamage(20); // 20ダメージを与える (ダメージ量は必要に応じて変更)
        }

        // 弾丸自身を破棄
        Destroy(gameObject);
    }
}

4. Enemy.cs (敵の体力、ダメージ処理)

using UnityEngine;

public class Enemy : MonoBehaviour
{
    public int health = 100;  // 敵の体力

    public void TakeDamage(int damage)
    {
        health -= damage;

        if (health <= 0)
        {
            Die();
        }
    }

    void Die()
    {
        // 敵が倒されたときの処理(例:アニメーション再生、アイテムドロップ、スコア加算など)
        Debug.Log("Enemy Down!"); // とりあえずログ出力
        Destroy(gameObject);
    }
}

5. EnemyController.cs (敵キャラクターの動き)

using UnityEngine;

public class EnemyController : MonoBehaviour
{
    public float speed = 2f; // 敵の移動速度

    private Transform player; // 主人公のTransform

    void Start()
    {
        // 主人公のゲームオブジェクトを探してTransformを取得
        player = GameObject.FindGameObjectWithTag("Player").transform;
    }

    void Update()
    {
        if (player != null)
        {
            // 主人公の方向を計算
            Vector2 direction = (player.position - transform.position).normalized;

            // 主人公に向かって移動
            transform.position = Vector2.MoveTowards(transform.position, player.position, speed * Time.deltaTime);

            // 敵の向きを主人公の方向に向ける (オプション)
            UpdateFacingDirection(direction);
        }
    }
    void UpdateFacingDirection(Vector2 direction)
    {
        // プレイヤーのSpriteの向きを反転させる (必要に応じて)
        if (direction.x > 0)
        {
            transform.localScale = new Vector3(1, 1, 1); // 正面向き
        }
        else if (direction.x < 0)
        {
            transform.localScale = new Vector3(-1, 1, 1); // 反転
        }
    }
}

6. EnemySpawner.cs (敵キャラクターを発生)

using UnityEngine;

public class EnemySpawner : MonoBehaviour
{
    public GameObject enemyPrefab; // 出現させる敵のプレハブ
    public float spawnRadius = 5f; // 出現させる円の半径
    public float spawnInterval = 2f; // 出現間隔(秒)

    private Transform player; // 主人公のTransform

    void Start()
    {
        // 主人公のゲームオブジェクトを探してTransformを取得
        player = GameObject.FindGameObjectWithTag("Player").transform;

        // 一定時間ごとに敵を出現させる
        InvokeRepeating("SpawnEnemy", 0f, spawnInterval);
    }

    void SpawnEnemy()
    {
        if (player != null)
        {
            // 主人公の位置を中心に円周上のランダムな位置を計算
            Vector2 randomCirclePoint = Random.insideUnitCircle.normalized * spawnRadius;
            Vector3 spawnPosition = player.position + new Vector3(randomCirclePoint.x, randomCirclePoint.y, 0f);

            // 敵を出現させる
            GameObject newEnemy = Instantiate(enemyPrefab, spawnPosition, Quaternion.identity);

            // Enemy スクリプトをアタッチ
            newEnemy.AddComponent<Enemy>();
        }
    }
}

重要なポイント:

  • レイヤー設定:
    • Player, Bullet, Enemy など、オブジェクトの種類ごとに専用のレイヤーを作成し、適切に設定します。
    • Edit -> Project Settings -> Physics 2D の Layer Collision Matrix で、レイヤー間の衝突判定を制御します。特に、Player レイヤーと Bullet レイヤーが衝突しないように設定します。
  • FirePoint:
    • FirePoint は弾丸の発射位置と向きを決めるための空のゲームオブジェクトです。
    • Player オブジェクトの子オブジェクトとして作成し、適切な位置に配置します。
  • 弾丸の生成:
    • PlayerControllerShoot() 関数で Instantiate() を使用して弾丸プレハブを生成します。
    • 生成位置は firePoint.position、生成角度は firePoint.rotation を使用します。
  • 弾丸の移動:
    • Bullet スクリプトの Start() 関数で、Rigidbody2D コンポーネントを取得し、rb.velocity に速度を設定します。
    • プレイヤーの向き isFacingRight を参照して、弾丸の進行方向を決定します。
  • 衝突判定:
    • Bullet スクリプトの OnTriggerEnter2D() 関数で衝突判定を行います。
    • hitInfo.CompareTag("Player") でプレイヤーとの衝突を無視します。
    • hitInfo.GetComponent<Enemy>() で敵との衝突を判定し、Enemy スクリプトの TakeDamage() 関数を呼び出してダメージを与えます。
  • オブジェクトの破棄:
    • OnTriggerEnter2D() 内の最後で、Destroy(gameObject) を呼び出して弾丸自身を破棄します。
    • Enemy スクリプトの Die() 関数で、敵が倒されたときに Destroy(gameObject) を呼び出して敵を破棄します。
タイトルとURLをコピーしました