ゴマちゃんフロンティア

気まぐれと勢いで作るUnityゲーム開発日記です

【開発メモ】ステージ外へ落下した際の処理について

time 2016/07/13

というわけで、今回はタイトル通り、「ステージ外へ落下した際の処理」について考えてみます。

shot2ss20160713230800516

この処理がないと落下しても亜空間を移動できたり、落下後に復帰できなくなってしまいます。
ゲームとしての体裁を保つためには必須の処理ですが、全然作っていなかったので実装してしまおうと思います!

実際の処理はゲーム内容によって大きく異なる部分かと思われます。
落下時は即死するのか、ダメージを受けるだけなのか、その場合どこに戻されるのか・・・とかですね。
まあ見ての通り堅苦しいゲームではないので、ペナルティは軽めにする予定です。

判定用オブジェクト作成とスクリプト設定

「落下時は一定ダメージを受けて特定の地点へ移動」 で実装してみます。
残機というシステムを入れるつもりがないこと、その上で落下=即死では難易度が高くなると感じたためです。

shot2ss20160713231310804

まず、「触れると落下した扱いになる」判定を作ります。
落下判定をする場所に配置する他、ステージ全体の下に大き目の判定で配置し、イレギュラーな挙動をしてしまった場合でも落下扱いにして戻ってこれるようにします。

次に「落下後に戻される場所」として空のオブジェクトを作成し、上で作成した判定の子オブジェクトにします。
子オブジェクトにしなくても問題はありませんが、セットで管理しやすくなるのでオススメです。
戻ってくる位置として使うだけなので、Transform 以外のコンポーネントは不要です。

その後、判定を作ったオブジェクト(=親オブジェクト)にスクリプトを設定します。

using UnityEngine;
using System.Collections;

public class DamageReturnArea : MonoBehaviour {

    public float power;

    private Transform returnPoint;

    void Start() {
        returnPoint = transform.FindChild("ReturnPoint");
    }

    private void OnTriggerEnter(Collider c) {
        string tag = TagUtility.getParentTagName(c.gameObject);

        if (tag == "Player") {
            c.GetComponent<Player>().forceDownDamage(this);
            StartCoroutine("returnCharacter", c.gameObject);
        }
    }

    private IEnumerator returnCharacter(GameObject character) {
        yield return new WaitForSeconds(1f);

        character.transform.position = returnPoint.position;
    }
}

TagUtility に関しては以下の記事をご参照下さい。

【Unity】タグの階層表示と判定方法について

判定に入ったのがプレイヤーキャラだった場合は StartCoroutine() を実行し、一定時間後に returnPoint に戻します。
ダメージ処理は forceDownDamage() から Player クラスで行っています。
Player クラスまで載せると長い上に他と絡み合っていて面倒なので、ここでは割愛します。

ちなみにエリアとして作った関係上、マグマや針びっしりの床などでも同様の処理ができます。
一般的なアクションゲームでよくある即死トラップ系はステージ外落下と同じ扱いにしてしまう予定です。

落下時のカメラワークについて

現状のカメラアングルはプレイヤーの位置に合わせて追従します。
mainCamera をプレイヤーと同位置に追従させているオブジェクトの子オブジェクトとして設定し、位置・角度を調整しています。
そのスクリプトは以下の記事に載せてあります。

【Unity】「ProBuilder Basic」を使ったシンプルなステージ作成

ただし、落下時にカメラに対して何も処理をしていないため、落下後も追従しっぱなしです。
この手のゲームでステージ外落下後もプレイヤーを追従するカメラなんてほとんどないでしょう。

そんなわけで、落下判定に触れた際はカメラをプレイヤーを追従しないようにします。
今は CameraController というスクリプトからカメラを制御しており、上記の追従もここで行っているので、フラグを持たせて切り替えてしまいます。
上で載せたスクリプトを少し修正します。

using UnityEngine;
using System.Collections;

public class DamageReturnArea : MonoBehaviour {

    public float power;

    private Transform returnPoint;
    private CameraController cameraController;

    void Start() {
        returnPoint = transform.FindChild("ReturnPoint");
    }

    void Update() {
        cameraController = GameObject.FindGameObjectWithTag("PlayerManager").GetComponent<CameraController>();
    }

    private void OnTriggerEnter(Collider c) {
        string tag = TagUtility.getParentTagName(c.gameObject);

        if (tag == "Player") {
            c.GetComponent<Player>().forceDownDamage(this);
            StartCoroutine("returnCharacter", c.gameObject);

            // カメラアングルを固定
            cameraController.fixCamera = true;
        }
    }

    private IEnumerator returnCharacter(GameObject character) {
        yield return new WaitForSeconds(1f);

        cameraController.fixCamera = false;
        character.transform.position = returnPoint.position;
    }
}

カメラの方はフィールドに fixCamera を追加し、「transform.position = player.transform.position」の前に if 文を追加して制御します。
以下は CameraController の Update() 内です。

void Update() {
    // キャラクターを見失った場合再取得
    if (player == null) {
        player = GameObject.FindGameObjectWithTag("Player");
    }

    if (!fixCamera) {
        transform.position = player.transform.position;
    }
}

最終的にはこんな感じになりました!

20160714_01

よくあるアクションゲームのようなカメラワークになった気がします。
とりあえず十分な出来です。

まとめ

そんなわけで、落下時の処理について考えてみました!
実装の雰囲気だけ見ると、「メトロイドプライム」シリーズや、「伝説のスタフィー」シリーズの処理に似ています。
(後者はエリアの初めまで戻るので、そこまで似ているわけでもないかも)
まあ最近のゲームはダークソウルとか硬派なものを除くと、どれもこんな感じだったりしますが。

今日のイラスト

久しぶりにランパを描いてみました。
イラストを描くこと自体が数ヶ月ぶりだったりします。
何かバランスが変ですが、パッと見の出来はまあまあな感じ。

ranpa30

そのうちTwitterで「ランパの台詞集bot」みたいなものを作ろうかと考えていたりします。
いろいろと下準備が必要になりそうなので、暇なときにやっていく感じ・・・でしょうか。

スポンサーリンク

down

コメントする



ツイッター