ブログ › Unity

プレイヤー作成~横スクロールシューティング①

(2024/1/8 更新)Unity

はじめに

2Dの横スクロールシューティングを作ってみます。
アセットストアの無料アセットをお借りして背景、キャラクターを表示。
ゲームとしての制御はスクリプトを自作します。
ブラウザでもプレイできるよう弾は自動発射、自機はマウス位置/タップ位置を目指して動く形にします。

今回はプレイヤーキャラクターを作成して移動、弾発射まで進めます。

 ↑このような形になります。

準備

プロジェクト作成

2Dテンプレートでプロジェクト作成

・解説

2Dテンプレートを使ってプロジェクトを作成し、Unityゲーム開発を開始します。

・手順

  1. UnityHUB起動
  2. タブ「プロジェクト」をクリック
  3. ボタン「新しいプロジェクト」をクリック
  4. テンプレート「2D」をクリック
  5. プロジェクト設定「プロジェクト名」を入力
  6. プロジェクト設定「保存場所」を決定
  7. ボタン「プロジェクトを作成」をクリック

素材探し

マイアセットに登録してUnityで開く

・解説

「2D」「無料」でフィルタリングしたところ900件弱のアセットが見つかりました。
見落とすのも嫌なので「サムネイル」を目視して絞り込みます。
それっぽいアセットの概要を開き、概要のサムネイルで希望のものかチェック。

背景、機体、弾などバラバラで集めることになるかと思いましたが、一式揃ったアセットがありました。

「Warped Space Shooter」

勉強やプロトタイプする時にはとても使いやすそうです。
作者さんの他アセットを確認したらどれも好きなレトロ感でした。
お借りします。

・手順

  1. 公式サイト「アセットストア」にアクセス
  2. フィルタ「無料」をチェック
  3. 横スクロールシューティングっぽいタイトル/サムネイルを探す
  4. サムネイルにカーソルを合わせてアイコン「概要を見る」をクリック
  5. サムネイルが作りたいものに合っているか確認
  6. ボタン「完全な詳細を見る」をクリック
  7. タブ「概要」の文章を見て作りたいものに合っているか確認
  8. タブ「パッケージの内容」をクリック
  9. フォルダを開いてファイルをクリック
  10. プレビューに表示された画像が作りたいものに合っているか確認
  11. 使ってみる場合はボタン「マイアセットに登録」をクリック
  12. ボタン「Unityで開く」をクリック

素材取り込み

インポート後のプロジェクト

・解説

Unityのプロジェクトにアセットを取り込みます。
アセットストアで「Unityで開く」をクリックして警告を許可すると、
Unityが前面に出てきて「パッケージマネージャー」というビューが表示されます。
ここでダウンロード、インポートを行ってUnityにアセットを取り込みます。

・手順

  1. パッケージマネージャーのボタン「ダウンロード」をクリック
  2. パッケージマネージャーのボタン「インポート」をクリック

※アセットストアを経由せず、マイアセットから直接取り込む場合

  1. Unityメニューの「ウィンドウ>パッケージマネージャー」をクリック
  2. パッケージマネージャーのドロップダウン「パッケージ」をクリックし、「マイアセット」をクリック
  3. パッケージマネージャーの検索ボックスにキーワードを入力
  4. パッケージマネージャーのアセット名をクリック
  5. パッケージマネージャーのボタン「ダウンロード」をクリック
  6. パッケージマネージャーのボタン「インポート」をクリック

プレイヤー作成

プレイヤー表示

自機の表示

・解説

「Assets>Space Shooter Assets>Artwork>player」にあるplayer1をシーンにドラッグ&ドロップし、位置を(-6, 0, 0)、スケールを(4, 4, 1)とします。

アニメーションは通常画像、上昇画像、下降画像を繰り返し表示するようになっています。
スクリプトもアニメーション設定も無いので、アセットストアの概要動画の動きはスクリプトで再現する必要がありそうです。

画像そのままのサイズでは小さすぎるので4倍にしています。
※インポート設定の「ユニット毎のピクセル数」で楽に制御できると思いますが、
 スプライトのみ表示して全選択するとインスペクターの表示がインポート設定じゃなくなってしまう。。。
 やり方あったら教えてほしいです。

・手順

  1. プロジェクトの「Assets>Space Shooter Assets>Artwork>player>player1」をシーンにドラッグ&ドロップ
  2. インスペクターの「Transform>位置」に(-6, 0, 0)を入力
  3. インスペクターの「Transform>スケール」に(4, 4, 1)を入力

プレイヤー移動

マウスを追って自機が動く

・解説

マウスを追いかけるように自機を移動させるスクリプトを作成します。

・手順

  1. プロジェクトの「Assets」を右クリックし、「作成>C# スクリプト」をクリック
  2. Playerと入力し、ENTERを押す
  3. プロジェクトの「Assets>Player」をヒエラルキーの「player1」にドラッグ&ドロップ
  4. プロジェクトの「Assets>Player」をダブルクリック
  5. Update関数の後に以下のスクリプトを記述
    // 物理更新時に処理
    void FixedUpdate()
    {
        // 移動量
        Vector3 moveVec;

        // プレイヤー移動
        {
            // マウス座標取得
            Vector3 pos = Input.mousePosition;
            // マウス座標をスクリーン座標に変換
            pos.z = -Camera.main.transform.position.z;
            // スクリーン座標をワールド座標に変換
            Vector3 worldPos = Camera.main.ScreenToWorldPoint(pos);
            // 現在位置からマウスワールド位置までの移動量
            moveVec = (worldPos - transform.position) / 30;
            // 徐々にマウス座標に近づくよう、移動量を分割して加算
            transform.position += moveVec;
        }
    }
  1. CTRLを押しながらSキーを押してスクリプト保存
  2. Unityエディタをクリックしてビルド
  1. CTRLを押しながらSキーを押してプロジェクト保存
  1. Unityエディタ上部中央のPlayボタンをクリックしてプレビュー開始
  2. マウスを追いかけるように自機が動くことを確認
  3. Unityエディタ上部中央のPlayボタンをクリックしてプレビュー終了

プレイヤー上昇下降

上下移動時にスプライトを切り替える

・解説

上下移動じにスプライトを切り替えることで、自機をアニメーションさせます。

Y移動量がマイナスの時は下降画像のplayer2、プラスの時は上昇画像のplayer3に切り替えます。
画像はUnityエディタ上で指定します。

・手順

  1. プロジェクトの「Assets>Player」をダブルクリック
  2. Start関数の前に以下のスクリプトを記述
    public Sprite spriteNormal;         // プレイヤー通常スプライト
    public Sprite spriteDown;           // プレイヤー下降スプライト
    public Sprite spriteUp;             // プレイヤー上昇スプライト
  1. FixedUpdate関数内の「プレイヤー移動」処理の後に以下のスクリプトを記述
        // 上下の移動量に応じてスプライトを切り替え
        SpriteRenderer spriteRenderer = GetComponent<SpriteRenderer>();
        if (Mathf.Abs(moveVec.y) < 0.05f)
        {
            // 縦の移動量が0.05未満なら通常スプライト
            spriteRenderer.sprite = spriteNormal;
        }
        else
        {
            if (moveVec.y < 0)
            {
                // 縦の移動量がマイナスなら下降スプライト
                spriteRenderer.sprite = spriteDown;
            }
            else
            {
                // 縦の移動量がプラスなら上昇スプライト
                spriteRenderer.sprite = spriteUp;
            }
        }
  1. CTRLを押しながらSキーを押してスクリプト保存
  2. Unityエディタをクリックしてビルド
  1. ヒエラルキーの「player1」をクリック
  2. プロジェクトの「Assets>Space Shooter Assets>Artwork>player>player1」をインスペクターの「Player>Sprite Normal」にドラッグ&ドロップ
  3. プロジェクトの「Assets>Space Shooter Assets>Artwork>player>player2」をインスペクターの「Player>Sprite Down」にドラッグ&ドロップ
  4. プロジェクトの「Assets>Space Shooter Assets>Artwork>player>player3」をインスペクターの「Player>Sprite Up」にドラッグ&ドロップ
  5. CTRLを押しながらSキーを押してプロジェクト保存
  1. Unityエディタ上部中央のPlayボタンをクリックしてプレビュー開始
  2. マウスを素早く上に動かすと自機の裏面が表示されることを確認
  3. マウスに接近すると通常画像に戻ることを確認
  4. マウスを素早く下に動かすと自機の表面が表示されることを確認
  5. Unityエディタ上部中央のPlayボタンをクリックしてプレビュー終了

弾作成

弾アニメーション

弾を量産するためにプレハブ化する

・解説

「Assets>Space Shooter Assets>Artwork>shoot」にあるスプライト「shoot1」をシーンに配置し、
作られたゲームオブジェクトに「Assets>Space Shooter Assets>Artwork>shoot」にあるアニメーションコントローラー「shoot1」を割り当てます。
ゲーム中にスクリプトで作成するため、プレハブ化してヒエラルキーから削除しておきます。

・手順

  1. プロジェクトの「Assets>Space Shooter Assets>Artwork>shoot>shoot1.png」をシーンにドラッグ&ドロップ
  2. プロジェクトの「Assets>Space Shooter Assets>Artwork>shoot>shoot1.controller」をヒエラルキーの「shoot1」にドラッグ&ドロップ
  3. ヒエラルキーの「shoot1」をプロジェクトの「Assets」にドラッグ&ドロップ
  4. ヒエラルキーの「shoot1」をクリック
  5. Deleteキーを押す

弾の連続作成

弾の連続作成

・解説

定期的に弾を発射するようにPlayerスクリプトを修正します。
オブジェクト作成や削除の処理は時間がかかるため、何度も繰り返すのは良くありません。
今回はプロトタイプレベルなので影響は出ないと思いますが、最悪処理落ちしてしまうためです。

事前に作成しておき、作成時に見える場所に持ってきて、削除時に見えない場所に持っていきます。
最大数は後で変えられるよう変数に持っておきましょう。

・手順

  1. プロジェクトの「Assets>Player」をダブルクリック
  2. 変数定義群の最後に以下の変数を追加
    public GameObject shotPrefab;       // 弾プレハブ
    public int maxShotCount = 20;       // 事前に弾を作成する数
    public float shotSpeed = 30;        // 弾が1秒間に進む距離
    List<GameObject> shotList;          // 弾キャッシュ(事前に作成する弾)
    int nextShotIndex = 0;              // 次に発射する弾キャッシュの位置
  1. Start関数に以下の処理を記述
        // カメラの後ろ位置
        Vector3 hidePos = Camera.main.transform.position - Camera.main.transform.forward;

        // 弾を事前に作成し、カメラの後ろに配置
        shotList = new List<GameObject>();
        for (int i = 0; i < maxShotCount; i++)
        {
            // プレハブから弾を作成
            shotList.Add(Instantiate(shotPrefab));
            shotList[i].transform.position = hidePos;
        }
  1. FixedUpdate関数内の最後に処理を追加
        // 弾をプレイヤー位置に移動
        shotList[nextShotIndex].transform.position = transform.position;
        // 次の弾位置
        nextShotIndex++;
        if (nextShotIndex >= maxShotCount)
        {
            nextShotIndex = 0;
        }
        // 弾移動(どうせ見えないので全部動かす)
        for (int i = 0; i < maxShotCount; i++)
        {
            shotList[i].transform.position += transform.right * shotSpeed * Time.fixedDeltaTime;
        }
  1. CTRLを押しながらSキーを押してスクリプト保存
  2. Unityエディタをクリックしてビルド
  1. ヒエラルキーの「player1」をクリック
  2. プロジェクトの「Assets>shoot1」をインスペクターの「Player>Shot Prefab」にドラッグ&ドロップ
  3. CTRLを押しながらSキーを押してプロジェクト保存
  1. Unityエディタ上部中央のPlayボタンをクリックしてプレビュー開始
  2. 自機の先頭から弾が発射されることを確認
  3. Unityエディタ上部中央のPlayボタンをクリックしてプレビュー終了

弾発射

弾発射

・解説

弾は作られたけど、棒が自機の前に連なっているだけに見えます。
まず、弾作成の瞬間にエフェクトを表示して発射しているような効果を出しましょう。
さらに次の弾が発射されるまでの間隔を広げ。棒のように繋がらないよう修正します。

・手順

  1. プロジェクトの「Assets>Space Shooter Assets>Artwork>flash>flash」をヒエラルキーの「player1」にドラッグ&ドロップ
  2. インスペクターの「Transform>位置」に(0.185, 0, 0)を入力
  3. インスペクターの「Transform>スケール」に(1, 0.75, 1)を入力
  1. プロジェクトの「Assets>Player」をダブルクリック
  2. 変数定義群の最後に以下の変数を追加
    public GameObject shotFlash;        // 発射効果ゲームオブジェクト
    const int FLASH_VIEW_FRAME = 4;     // 発射効果を継続して表示するフレーム数
    public int shotPerSec = 8;          // 1秒間に発射する弾の数
    int shotFrame;                      // 前の弾を発射してからの経過フレーム数
  1. FixedUpdate関数内の処理「弾をプレイヤー位置に移動」の前に以下の処理を追加
        // 1秒間に発射する弾数に応じて「次の弾を発射するまでのフレーム数」を計算
        int shotInterval = 50 / shotPerSec;
  1. FixedUpdate関数内の処理「弾をプレイヤー位置に移動」の前に以下の処理を追加
        // 弾発射
        shotFrame++;
        if (shotFrame >= shotInterval)
        {
            // 次の弾待機を開始するため経過時間を初期化
            shotFrame = 0;

            // 発射効果を表示
            shotFlash.SetActive(true);
        }
        else if (shotFrame >= FLASH_VIEW_FRAME)
        {
            // 発射効果の継続期間が過ぎたら発射効果を非表示
            shotFlash.SetActive(false);
        }
  1. FixedUpdate関数内の処理「弾をプレイヤー位置に移動」を「発射効果を表示」の後に移動
  2. FixedUpdate関数内の処理「次の弾位置」を「弾をプレイヤー位置に移動」の後に移動
            // 弾をプレイヤー位置に移動
            shotList[nextShotIndex].transform.position = transform.position;
            // 次の弾位置
            nextShotIndex++;
            if (nextShotIndex >= maxShotCount)
            {
                nextShotIndex = 0;
            }
  1. CTRLを押しながらSキーを押してスクリプト保存
  2. Unityエディタをクリックしてビルド
  1. ヒエラルキーの「player1」をクリック
  2. ヒエラルキーの「player1>flash」をインスペクターの「Player>ShotFlash」にドラッグ&ドロップ
  3. CTRLを押しながらSキーを押してプロジェクト保存
  1. Unityエディタ上部中央のPlayボタンをクリックしてプレビュー開始
  2. 自機の先頭にある発射効果が弾発射の瞬間だけ表示されることを確認
  3. 弾が1秒間に8発発射されることを確認
  4. 早すぎて納得できないならば、ShotPerSecを1にして確認
  5. Unityエディタ上部中央のPlayボタンをクリックしてプレビュー終了

完成

弾は常に発射され、ゲームビュー内でカーソルを動かすとプレイヤーキャラクターが追いかけてきます。
ヒエラルキーを見ると20個の弾が常に表示されています。
新しく発射されても増えず、画面外に消えても減りません。
見た目も違和感ないので「プレイヤー作成」完了です。