Unity3D で横アクション制御の検証 2

unity20140130-001

■■■ ほぼ理想に近づいてきたデスよ ■■■

カーソルで左右移動、スペースでジャンプ。

そんなわけでジャンプ時に突き抜ける足場判定処理が出来たです。

■■■ 現時点のプロジェクトファイル公開 ■■■

今回は有料アセットを使用していないのでダウンロードしてお試しいただけます。

JumpTest20140130

■■■ 使い方 ■■■

上記 zip ファイルをダウンロードし、JumpTest20140130.unitypackage を任意のフォルダに解凍します。

新規プロジェクトの作成方法」を参考に新規プロジェクトを作成してください。

新規プロジェクト作成後、先ほど展開した JumpTest20140130.unitypackage をダブルクリックします。

パッケージインポートウイザードが開きますので、import をクリックします。

インポート完了したら、Project ビュー jumptest.unity をダブルクリックしてシーンを開きます。

このままでは正常に動きません。プロジェクト設定がパッケージに含めてエクスポートする方法を誰か教えてくださいー

右上のレイヤー編集ボタンをクリックします。 Layers -> Edit Layers… でレイヤーエディタを開き、下記のように設定します。

User Layer 8 : Wall
User Layer 9 : HalfCollider
User Layer 10 : Player

Edit -> Project Settings -> Physics をクリックし、Inspector PhysicsManager の Layer Collision Matrix を Wall x Player を残して全てチェックを外し、設定を完了します。

とりあえず遊んでみましょう、赤い足場はしたからつきぬけてジャンプできます。

■■■ 仕組み説明 ■■■

突き抜ける足場判定は物理演算を使わずに自前で計算しております。そして移動ベクトルが下向きの時だけ判定することで突き抜ける床が実現できます。

using UnityEngine;
using System.Collections;

public class Player : MonoBehaviour {

    public float xspeed = 3f;
    public float jump = 8f;
    public float gravity = -13f;
    float yspeed;
    bool grounded = false;
    GameObject groundcheck1, groundcheck2;
    Rigidbody oRigidbody;

	void Start () {
        yspeed = 0f;
        groundcheck1 = GameObject.Find("groundcheck1");
        groundcheck2 = GameObject.Find("groundcheck2");
        oRigidbody = GetComponent<Rigidbody>();
    }

	void Update () {
        Vector3 v3From, v3To, v3Position;
        Vector3 v3MoveVector = new Vector3(Input.GetAxis("Horizontal") * xspeed, yspeed, 0f) * Time.deltaTime;
        v3Position = transform.localPosition;
        v3From = groundcheck2.transform.position;
        v3To = v3From + v3MoveVector;

        // 床突き抜け補正処理
        RaycastHit oHit;
        bool collision =
            Physics.Linecast(
                v3From, v3To, out oHit,
                1 << LayerMask.NameToLayer("HalfCollider") | 1 << LayerMask.NameToLayer("Wall"));
        if (collision && yspeed <= 0f) {
            // 下向きに移動ベクトルを伸ばしたら衝突したので移動ベクトルを衝突位置までに補正する
            float fMagnitude = v3MoveVector.magnitude;
            float fDivY = (fMagnitude != 0f && oHit.distance < v3MoveVector.magnitude) ? (oHit.distance / fMagnitude) : 0f;
            v3MoveVector *= fDivY;
            yspeed = 0f;
        }
        // 補正した移動ベクトルを加算
        v3Position += v3MoveVector;
        transform.localPosition = v3Position;
        // 接地した状態か判定する
        grounded = (v3MoveVector.y <= 0f) ?
                    Physics.Linecast(
                        groundcheck1.transform.position,
                        groundcheck2.transform.position + new Vector3(0f, -0.1f, 0f),
                        1 << LayerMask.NameToLayer("HalfCollider") | 1 << LayerMask.NameToLayer("Wall")) : false;

        // 接地していればジャンプ処理、そうでなければ重力処理
        if (grounded) {
            if (Input.GetKeyDown(KeyCode.Space)) yspeed = jump;
        } else {
            yspeed += gravity * Time.deltaTime;
        }
        // 物理演算オブジェクトの速度を強制クリアする
        oRigidbody.velocity = Vector3.zero;
    }
}

■■■ 次回予告 ■■■

次回はあれです、せっかくなので上下左右の判定も処理しちゃいます。

そして物理演算の呪縛から解き放たれるのです。

ていうか、これ意味あるのか? てな気もしますが 2D アクションゲーム作るにあたって自前で挙動の特性作ってしまいたい場合には有効なのでは? とか震え声で言ってみたり。

まぁ、特殊な当たり判定処理が実現できたのでこれでヨシとします。

「シェアする」

ツイートツイート