見出し画像

アクションゲームを作ったよのお話

アクションゲームを作りました。上のサイトからPCで遊べます。


操作方法

メニュー
上下移動:WASD、矢印キー 決定:スペース、エンター

プレイヤー操作
左右移動:AD、矢印←→ ジャンプ:スペース ポーズ:P

目的
ステージ奥にあるジュエルを持ち帰り、スタート地点まで戻ったらゴール、ステージクリアになります。ジュエルを所持している間はジャンプ力が減少します。トラップをかいくぐり、ジュエルを奪ってきてください。


ゲームを製作する以上、2Dアクションゲームは一度作っておきたいと思いUnityにて製作に至りました。

本ゲームのコンセプトは「行って帰るサクサクアクション」です。スーパーメトロイドのオープニングステージのような、アクションゲームでしばしば見られる、脱出シーンでステージを逆走するのっていいよな、から始まりました。加えて、1プレイが1分で終わるようにすることで、何度もリトライしやすくサクサクとゲームを攻略できるようなカジュアル性を目指しました。

また、各ステージの導線を少しでも増やし、なるべく攻略パターンを一つには絞らないようにすること、またベストタイムの表示により何度もリトライしたくなるようなゲームを意識して作りました。

キャラクターやステージのアセットは「Kenney」、効果音は「効果音ラボ」より拝借いたしました。

これら以外の、各種スクリプトは全て自作となります。


以下、製作にあたってのお話を少しさせていただきます。特に参考になる部分とかはないと思います。

がんばったところ

今回特に悩んだところはジャンプ、および着地判定です。

ジャンプするだけなら単純ですが、今回はジャンプの押し時間に合わせてジャンプ力が変化、離すと上昇が終了する、ジャンプ調整をやりたくて。

もともとただ上昇するだけのジャンプでしたがベストタイムを出す仕様にした以上は隙のないジャンプでタイムを詰められるようにしたほうが面白いよなというのと、ステージ攻略に不便だと思い仕様変更をしました。

ただいざやってみると全くと言っていいほどにうまくいかず。思ってたよりも単純にはプログラムできず結局インターネットをめぐり参考に。

    //ジャンプ処理
    bool onField; //着地判定に使用
    bool landOnetime = true; //着地時のSEを1度だけ鳴らす
    bool isJump = false; //ジャンプ長押しによる連続ジャンプの制限
    bool jumpUpEnd = false; //ジャンプ調整に使用
    float jumpTime; //ジャンプボタンを押している時間の計測
void AdjustJump()
    {
        if (isDead) return;

        float ySpeed = rigid2D.velocity.y;

        if (onField) 
        {
            //地上にいるときのみジャンプ、およびジャンプ調整の準備
            if (Input.GetKeyDown(KeyCode.Space))
            {
                ySpeed = jumpForce;
                isJump = true;
                aud.PlayOneShot(jumpSound);
            }
            jumpUpEnd = false;
            jumpTime = 0;
        }

        else
        {
            jumpTime += Time.deltaTime;
            if (jumpTime > 0.75f) isJump = false;
            if (Input.GetKey(KeyCode.Space) && jumpTime < 0.3f && !jumpUpEnd)
            {
                //ジャンプ時間を0.3秒に制限

                //ダイヤ所持時はジャンプ力減少
                if (!haveDia) ySpeed = jumpForce;
                else ySpeed = jumpForce * 0.85f;
            }
            if (Input.GetKeyUp(KeyCode.Space) && !jumpUpEnd)
            {
                //ジャンプボタンを離すと上昇終わり
                jumpUpEnd = true;
                isJump = false;
            }
        }

        //Debug.Log(isJump);

        //ジャンプ処理をプレイヤーに反映
        rigid2D.velocity = new Vector2(rigid2D.velocity.x, ySpeed);
    }

一応ジャンプに関わってるコードを載せておきます。このとおりジャンプだけでコメントなしでもけっこうな行を使っています。

ジャンプボタンを離すと上昇が終わり落下するところはロックマンを参考にしました。ジャンプ挙動はいろいろ見て参考にしました。ファミコンのマリオはジャンプ中ボタンを離してもふわっと上昇しますがロックマンは離すと落下でそっちのほうが実装しやすいかもと思って採用。


次に着地判定について。


これは設計してすぐのものですが、プレイヤーの下の細い棒みたいなやつが地面に触れたら着地、としていました。自キャラの脚よりも低いのはそのほうがよりジャンプ、ひいてはプレイが快適になると思いそうしてみました。

「星のカービィ ディスカバリー」のインタビューにてお話のあった「ファジー着地」を参考にしてます、とは言いつつも本質は全く異なるものだし、着地判定を自キャラの位置より下げる手法はままあるものではありますね。


しかしこれで実装すると問題があります。足元にダメージ判定があると着地判定をチェックする棒とダメージ判定がぶつかってプレイヤーが死にます。どうしても接地判定とダメージ判定を共有してしまう、おそらく避けようのない仕様によるものです。

ギミック上、ダメージ判定を持ってる歯車みたいのが足元に来るときがあり、触れてもないのにそれで死ぬのはゲーム体験として好ましいものではないと思いつつもしばらくはそのままでした。ただ改善したいという気持ちもあり。


好ましくない体験

ダメージ判定をトリガー接触でなく物理接触にすれば解決するかもとは思いましたが、それよりもっといい方法はあると思い、Raycastを使用。

もともと使うかは考えてたのですが、引数の多さや使い方をいまいち理解できずにプレイヤーの挙動設計の最初では見送りしてました。でも変な当たり判定で死ぬのは流石にプレイしてて気持ち悪さが勝つなと思い、仕様を変更。


この赤線が地面に触れることで着地判定としました。見えてるところではただの線ですが実際はCircleCastでもうちょっと太いです。Raycastを使用することで足元の当たり判定に触れて死ぬことなくステージを遊ぶことができるようになりました。Raycastによる当たり判定の付け方の勉強にもなってよかったです。


今回の学び

作製にあたり得られた学びをここに書きこんでおきます。

先述のRaycastによる接地判定はまさに学びですね。今後もお世話になる機会は多そうなので。

ステージの作成にTileMapを使ったのは今回初めてです。TileMapの便利さや、逆に少し不便なところを知る機会になりました。

たとえCompositeColliderを入れたとしても自機のコライダーが四角だとどうしても小さい段差ができてそれに引っかかってしまうのは悩みどころでした。


着地判定の話の写真をそのまま流用

前足の丸いコライダーで引っかかっても乗り越えられるようにしました。もっといい解決法はあるかも。

シングルトンも今回初めてやってみました。クリアタイムが表示される以上はベストタイムが残るほうが面白いよな、と思い実装してみました。

ネットで調べても仕組み自体はよくわからず、わからないままにプログラムを書き込んでましたがいざ実行するとその便利さに身をもって体験できました。

シーンをまたぐときの決定SEを鳴らすのにも別途シングルトンを使っています。これ使えばコンフィグとかの設定もできるのかなと考えてます。これも今後よく使いそう。

また、ゲームの構成としてレベルデザインの大変さを感じました。正直最終ステージはあまりいいとは言えないんじゃないかと思っています。難しく作ろうとするといくらでも難しくできるので塩梅の調節は簡単なものではないと考えさせられました。

反省点

無事公開まではしたとはいえ、あまりよくできなかった部分も多少あります。

まずは作成期間です。個人で作ってるものである以上締め切りが存在しないのですが、流石に時間をかけすぎました。正直いつから始めたかわからないぐらいです。いろいろ忙殺されたり単純にサボってたのもあるのでそこは身を引き締めしっかりとやるべきでした。

締め切りを作ること、またギミックやステージは思いついただけ無限に作れてしまう点も含め、12月初めにはとにかく一度打ち切って公開することに決めました。記事ページ作成で文章を書くのに少し時間を使っての公開とはなりましたが。

スクリプトについても一つ大きな問題点が。

プログラム処理のためのステージ番号の設定が全く思いつかずこんなクソコードに。evevtSystemで選択してるオブジェクト、今回はボタンから数字を直接取得したかったのですがやり方がわからず。ここはもっとスマートにしたい悔しい点です。

せめて0~ステージ数を範囲にしたfor文で番号を設定すればよかった。本当に悔しい。

やりたいこと

製作自体は終わりましたがアクションゲームとしてやりたいことはたくさんありました。ただそれだと製作期間が延びに延びてしまうので今回打ち止めしたのでやらなかったのですが。

ステージギミックで実装したかったものが多かったですね。射撃で攻撃してくる敵や、スイッチを押すことで実体化/透明化するブロック、動く床など様々です。

特に動く床についてはどういう挙動させればいいのだろうと考えてます。単純に床だけ動かしても上に乗ったプレイヤーには慣性などなくそのまま落下しそうだし。そういったチャレンジも今後やってみたいです。

ただアップデートして実装、の予定は今のところありません。それよりも新しくゲームを作りたいと思うので。まだ企画が頭でちょっとできてるぐらいですが。


おわりに

以上にて本ゲームの紹介、および製作にあたっての話を書かせていただきました。至らぬ点も多々ありますがぜひプレイしていただけたら幸いです。

今後もいろいろゲームを作ってみたいので、また機械があればぜひよろしくお願いいたします。



この記事が気に入ったらサポートをしてみませんか?