『UNITYゲーム プログラミング・バイブル』「ENTRY No.04 昼と夜が流れる オープンワールド」学習記録1

Unityゲーム プログラミング・バイブル

Unityゲーム プログラミング・バイブル

序文

『UNITYゲーム プログラミング・バイブル』6日目?

昨日は全然頭が回らず更新できませんでした…。

進捗

(学習時間:2.5時間)

コード実装部分

\180715UnityGameProgrammingBible\Assets\Unity_Bible\03_Char_Control\Script\BasicCharCont.cs
(コメント書いた)
(ENTRY No.03)

using UnityEngine;
using System.Collections;

public class BasicCharCont : MonoBehaviour {
    private float walkSpeed = 2.0f; // 歩行速度
    private float runSpeed = 4.0f; // 走行速度

    private Vector3 movement;   // 移動するベクター

    private float gravity = 20.0f; // キャラへの重力
    private float speedSmoothing = 10.0f;   // 回頭するときの滑らかさ
    private float rotateSpeed = 500.0f; // 回頭の速度
    private float runAfterSeconds = 0.1f;   // 走り終わったとき止まるまでの時間(秒)

    // 動くべき方向
    private Vector3 moveDirection = Vector3.zero;   // カレント移動方向
    private float verticalSpeed = 0.0f;    // カレント垂直方向速度
    private float moveSpeed = 0.0f;    // カレント水平方向速度

    private CollisionFlags collisionFlags;    //  controller.Move が返すコリジョンフラグ:キャラが何かにぶつかったとき使用

    private float walkTimeStart = 0.0f;    // 歩き始める速度

    // Use this for initialization
    void Start () {
        // 動くべき方向(向いている方向)をワールド座標でセットする
        moveDirection = transform.TransformDirection(Vector3.forward);  // キャラの移動方向をキャラの向いている方向にセットする
    }
    
    // Update is called once per frame
    void Update () {
        // カメラのtransformコンポーネントを取得
        Transform cameraTransform = Camera.main.transform;  // カメラの向いている方向を得る
        // カメラから見た前方方向を取得して、ワールド座標に変換する
        Vector3 forward = cameraTransform.TransformDirection(Vector3.forward);  // camera の x-z 平面から forward ベクターを求める 
        // キャラクターは水平移動のみなのでY方向は無視する
        forward.y = 0;  // Y方向は無視:キャラは水平面しか移動しないため
        // カメラ前方方向変数を正規化する
        forward = forward.normalized;   // 方向を正規化する
        // forward方向から時計回りに45度方向がright(これも正規化されている)
        Vector3 right = new Vector3(forward.z, 0, -forward.x);    // 右方向ベクターは常にforwardに直交

        // 垂直方向への入力値
        float v = Input.GetAxisRaw("Vertical"); // マウスもしくはコントローラスティックの垂直方向の値
        // 水平方向への入力値
        float h = Input.GetAxisRaw("Horizontal");   // マウスもしくはコントローラスティックの水平方向の値

        // 左右の入力は水平方向(X軸)の移動に対応し
        // 上下の入力は奥行方向(Z軸)の以上に対応する
        // 入力された移動方向を計算する
        Vector3 targetDirection = h * right + v * forward;  // カメラと連動した進行方向を計算:視点の向きが前方方向

        // キャラクターが接地しているとき
        if ((collisionFlags & CollisionFlags.CollidedBelow) != 0)   // キャラは接地しているか?:宙に浮いていないとき
        {
            // 移動入力キーが入っているとき
            if (targetDirection != Vector3.zero) // キャラは順方向を向いていないか?:つまり回頭している場合
            {
                // このフレームで動くべき方法を計算する(向きは計算していないことに注意)
                // 現在の移動速度が遅いとき(1.8f以下)は
                // walkSpeed : 2.0f
                if (moveSpeed < walkSpeed * 0.9) // ゆっくり移動か?
                {
                    Debug.Log("即時ターン");
                    // 即座に移動方向を変更する
                    moveDirection = targetDirection.normalized; // 止まっているときは即時ターン
                }
                // 有働速度が早いときは
                else  // 移動しているときはスムースにターン
                {
                    // スムーズにターン
                    Debug.Log("スムーズターン");
                    // 移動方向を自然に変更する
                    // Mathf.Deg2Radは度数からラジアン角に変換するらしい
                    moveDirection = Vector3.RotateTowards(moveDirection, targetDirection, rotateSpeed * Mathf.Deg2Rad * Time.deltaTime, 1000);
                    // 正規化処理
                    moveDirection = moveDirection.normalized;
                }
            }

            // フレームを考慮した向くスピード
            // speedSmoothing:10.0f
            float curSmooth = speedSmoothing * Time.deltaTime;     // 向きをスムースに変更

            // 移動速度を1f以上にしない
            float targetSpeed = Mathf.Min(targetDirection.magnitude, 1.0f); // 最低限のスピードを設定

            // 歩く速度と走る速度の切り替え:最初は歩いてで時間がたつと走る
            // あるき始めてから0.1f(runAfterSeconds)経ったところで走り始める
            if (Time.time - runAfterSeconds > walkTimeStart)
                targetSpeed *= runSpeed;
            else
                targetSpeed *= walkSpeed;

            // 移動速度をなめらかに変化させる
            moveSpeed = Mathf.Lerp(moveSpeed, targetSpeed, curSmooth);

            // Animatorコンポーネントを取得する
            Animator animator = GetComponent<Animator>();   // Animator コンポーネントを得る
            // spdパラメータにmoveSpeedをセットする
            animator.SetFloat("spd", moveSpeed); // Animator に移動速度のパラメータを渡す
            // fallパラメータをfalseにする
            animator.SetBool("fall", false);    // Animator に落下フラグのパラメータを渡す:落下していない

            // moveSpeedが0.6以下なら
            if (moveSpeed < walkSpeed * 0.3)    // まだ歩きはじめ
                walkTimeStart = Time.time;  // その時間を保存しておく

            verticalSpeed = 0.0f;   // 垂直方向の速度をゼロに設定
        }
        else // 宙に浮いている
        {
            // 重力を考慮した落下速度を設定
            verticalSpeed -= gravity * Time.deltaTime;  // 重力を適応
            if (verticalSpeed < -4.0)   // 落ちる速度が一定を超えたら
            {
                Animator animator = GetComponent<Animator>();   // Animator コンポーネントを得る
                animator.SetBool("fall", true);   // Animator に落下フラグのパラメータを渡す:落下している
            }
        }

        // 移動量を計算する
        movement = moveDirection * moveSpeed + new Vector3(0, verticalSpeed, 0);   // キャラの移動量を計算
        movement *= Time.deltaTime;

        // CharacterControllerコンポーネントを取得
        CharacterController controller = GetComponent<CharacterController>();   // キャラクターコントローラコンポーネントを取得
        // キャラクターを動かす(戻り値は衝突判定)
        collisionFlags = controller.Move(movement);   // キャラを移動をキャラクターコントローラに伝える

        // キャラクターが設置しているとき
        if ((collisionFlags & CollisionFlags.CollidedBelow) != 0)   // 宙に浮いていない場合
        {
            // 向きを変える
            transform.rotation = Quaternion.LookRotation(moveDirection);       // 移動方向に回頭:浮いていると回頭しない
        }
    }
}

実行結果

(ENTRY No.04)
f:id:yjkym:20180718153539p:plain センスがないわー

感想

ENTRY No.03のスクリプトの解読とENTRY No.04のTerrain(テレイン)の操作。

No.03はスクリプトの解読までやったけど、そこまでやるといつまでも終わらなくなりそうなので、やっぱり書籍の内容を重視して進めていくことにしよう。
勉強にはなるんだろうけど…。

しかし、このスクリプトすごく細かい動作まで制御してるねぇ。
こういうやつこそコンポーネントひとつでえいやっ!っていい感じに実装してくれたらいいのに。

いまだに学習のペースがつかめないなぁ。

カロリーメイトください。

BGM

MASTER LOW / PEQUU

www.youtube.com なんでこんな再生されてんだ?と思ったら最近逮まったらしい

NG集(おまけ)

www.youtube.com No.4のサンプルは最新版のUnityだと落下する模様。
本当に互換性悪いんだねぇ。