ゴマちゃんフロンティア

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

【開発メモ】ステージオブジェクト「トランポリン」の実装

time 2016/08/20

【2017/05/31】
記事内容の修正・補足項目の追加を行いました。

というわけで、世界中がリオ五輪で盛り上がっている今日この頃!
便乗するわけではありませんが、こんなものを実装してみました!

shot2ss20160820213023487

所謂「トランポリン」です!
上に乗ると自動的にジャンプし、ジャンプボタンを押すと大ジャンプします。
割とユニークなギミックなためか、最近のゲームでは見かけなくなった気がします。

既に似たようなシステムとして、「ジャンプエリア」というものを作ってあります。
エリア内に入った状態でジャンプすると大ジャンプができます。
トランポリンとの違いは「判定なのでゲーム上では見えない」「入ってもオートでジャンプせず、手動入力した場合に否応なく大ジャンプ」といった感じです。
トランポリンを作れば要らない気もしますが、消す必要もないのでとりあえず残しておく予定です。

トランポリンのモデリングとジャンプ制御

物がないと始まらないので、トランポリンをモデリングしてみます。

shot2ss20160820213813901

うーん・・・何だかただの机に見えなくもない微妙な感じです。
まあモデリングが下手なのは今に始まったことではないので、気にせずいきます!

shot2ss20160820213611949

Unityへインポート後、各種コライダーを設定します。
外枠部分にMeshCollider、中央部分にBoxColliderを追加し、大きさや位置を微調整します。
本当は円形に合わせてコライダーを設定できればよかったのですが、楕円形のコライダーを作る方法が分からなかったので、BoxColliderでなるべく合うように調整しました。
キャラクターとトランポリンの大きさ的にこれでも問題なかったです。

トランポリンを制御するためのスクリプトを作成します。
ひとまず、「上に乗ったときに自動でジャンプする」動きを目指してみます。

using UnityEngine;
using System.Collections;

public class Trampoline : MonoBehaviour {

    public float jumpHeight;
    public float enemyJumpHeight;

    void OnTriggerEnter(Collider c) {
        if (c.gameObject.tag == "Player") {
            CharacterMotor charMotor = c.GetComponent<Player>().getCharacterMotor();

            charMotor.movement.velocity.y = 0;
            iTween.Stop(c.gameObject);
            charMotor.movement.velocity.y = jumpHeight;
        }

        if (c.gameObject.tag == "Enemy") {
            Rigidbody rb = c.GetComponent<Rigidbody>();
            iTween.Stop(c.gameObject);
            rb.velocity = new Vector3(rb.velocity.x, enemyJumpHeight, rb.velocity.z);
        }
    }
}

プレイヤーキャラはCharacterMotor、敵キャラはRigibodyを使用して制御しているため、処理を分ける必要があります。
ジャンプ時に余計な加速度が掛かっている場合、一度リセットしないと想定以上に吹っ飛んでしまったりします。
velocity.yを0に設定」「iTween.Stop()で余計なiTweenを停止」はそのためです。
前者はともかく、後者は移動関係以外のiTweenも止まってしまったりするので、他にiTweenを使っている場合は気を付ける必要がありそうです。

ジャンプボタン押下で大ジャンプする処理

トランポリンと言えば、ジャンプボタン押下時に大ジャンプするものが大半です。
ということで、上のスクリプトを少し修正します。

using UnityEngine;
using System.Collections;

public class Trampoline : MonoBehaviour {

    public float jumpHeight;
    public float inputJumpHeight;

    public float enemyJumpHeight;

    void OnTriggerEnter(Collider c) {
        if (TagUtility.getParentTagName(c.gameObject) == "Player") {
            CharacterMotor charMotor = c.GetComponent<Player>().getCharacterMotor();

            charMotor.movement.velocity.y = 0;
            iTween.Stop(c.gameObject);

            if (Input.GetButton("Jump")) {
                charMotor.movement.velocity.y = inputJumpHeight;
            } else {
                charMotor.movement.velocity.y = jumpHeight;
            }
        }

        if (TagUtility.getParentTagName(c.gameObject) == "Enemy") {
            Rigidbody rb = c.GetComponent<Rigidbody>();
            iTween.Stop(c.gameObject);
            rb.velocity = new Vector3(rb.velocity.x, enemyJumpHeight, rb.velocity.z);
        }
    }
}

超シンプルに「コライダー判定時にジャンプボタンが押されているか」で行きます。
また、自動ジャンプと入力時のジャンプでフィールドを分け、区別できるようにします。
敵には入力で大ジャンプなんてないのでそのままです。

20160820_01

実際に動かすとこんな感じに。
モーションとかはさておき、挙動は問題なさそう。

ただし問題があり、2段ジャンプが有効の場合は2段が優先されてしまい、トランポリンの大ジャンプがなくなってしまいます。
今の実装の2段ジャンプはバグの温床になりえるので、いっそ無効化してしまおうかと思っていたりします。
本格的にやるならトランポリンのジャンプ専用モーションを作り、その間2段ジャンプのステートには遷移しないようにすればいけそうです。

まとめ

そんなわけで、トランポリンと使用時のジャンプ制御について作成してみました!
これでステージを作る際に高低差を激しくしても大丈夫ですね。

【追記】Playerクラスのサンプル

Playerクラスのサンプルを記載します。
使っているものを載せるのが理想ですが、先日リファクタした際にかなり手を入れてしまい、記載することができなくなりました。
以下、必要な部分のみを記載した例ということでご了承ください。

using UnityEngine;

public class Player : MonoBehaviour {

    protected CharacterMotor characterMotor;

    void Start () {
        characterMotor = this.GetComponent<CharacterMotor>();
    }

    public CharacterMotor getCharacterMotor() {
        return this.characterMotor;
    }
}

これをCharacterMotorコンポーネントを設定したプレイヤーキャラクターに付けることで動作するかと思います。

スポンサーリンク

down

コメントする



ツイッター