【Unity】Project TCC で遊ぼう~UC-01-06 TwinStickControl: ツインスティックによる移動と視線制御を実装する~

UC-01-06 TwinStickControl Unity
UC-01-06 TwinStickControl

Unity の Project TCC を触って、Unity の機能を学んでいきましょう。

Project TCC で遊ぼう~UC-01-06 TwinStickControl: ツインスティックによる移動と視線制御を実装する~

UC-01-06 TwinStickControl
UC-01-06 TwinStickControl

UC-01-06 TwinStickControl

変更点の確認

UC-01-06_TwinStick_Control シーンを開きます。
Unityエディター上で再生して、ユニティちゃんの向きを変えてみましょう。

UC-01-05_Move_Jump_Crouch シーンと違うところは、Player オブジェクトの Script Machine に Rotation Control の処理が追加されています。
キャラクターがマウスポインターのある方向を向きます。

Script Machine
Script Machine

シーンの複製

UC-01-05_Move_Jump_Crouch_Copy シーンを複製して、UC-01-06_TwinStick_Control_Copy という名前にします。

Input Action Asset の設定

Assets/TCC/Scenes/01_Move/Data_UC-01-05_Move_Jump_Crouch_Copy フォルダを複製して、Data_UC-01-06_TwinStick_Control_Copy という名前にします。
フォルダの中身の名前も変更します。

Input Action Asset の複製
Input Action Asset の複製

Data_UC-01-06_TwinStick_Control_Copy を選択して、インスペクターから Edit asset をクリックして Input Actions の設定を行います。
MousePosition を取得できるようにします。

Input Actions の設定
Input Actions の設定

Player オブジェクトの Player Input コンポーネントにある Actions に Input Action Asset を設定します。

Player Input の設定
Player Input の設定

Animator の設定

Player オブジェクトの Animator コンポーネントの Controller に UC-01-06_TwinStick_Control を設定します。

Animator の設定
Animator の設定

CursorPositionControl コンポーネントの追加

Player オブジェクトに CursorPositionControl コンポーネントを追加します。

CursorPositionControl の追加
CursorPositionControl の追加

C# スクリプトの作成

Player オブジェクトにくっ付いている MyWalkTest にプログラムを追加していきます。
MyWalkTest の内容はこちらになります。
TurnPriority でどちらの方向を向かせるかを制御しています。

using Unity.TinyCharacterController;
using Unity.TinyCharacterController.Check;
using Unity.TinyCharacterController.Control;
using UnityEngine;
using UnityEngine.InputSystem;

public class MyWalkTest : MonoBehaviour {
    private MoveControl m_rMoveControl;
    private JumpControl m_rJumpControl;
    private GroundCheck m_rGroundCheck;
    private HeadContactCheck m_rHeadContactCheck;
    private CursorPositionControl m_rCursorPositionControl;
    private Animator m_rAnimator;
    private PlayerInput m_rPlayerInput;
    private CharacterSettings m_rCharacterSettings;
    private InputAction m_rMove;
    private InputAction m_rSprint;
    private InputAction m_rJump;
    private InputAction m_rCrouch;
    private InputAction m_rMousePosition;
    private float m_fDefaultHeight;

    void Awake() {
        TryGetComponent<MoveControl>(out m_rMoveControl);
        TryGetComponent<JumpControl>(out m_rJumpControl);
        TryGetComponent<GroundCheck>(out m_rGroundCheck);
        TryGetComponent<HeadContactCheck>(out m_rHeadContactCheck);
        TryGetComponent<CursorPositionControl>(out m_rCursorPositionControl);
        TryGetComponent<Animator>(out m_rAnimator);
        TryGetComponent<PlayerInput>(out m_rPlayerInput);
        TryGetComponent<CharacterSettings>(out m_rCharacterSettings);
        if (m_rPlayerInput != null) {
            m_rMove = m_rPlayerInput.actions["Move"];
            m_rSprint = m_rPlayerInput.actions["Sprint"];
            m_rJump = m_rPlayerInput.actions["Jump"];
            m_rCrouch = m_rPlayerInput.actions["Crouch"];
            m_rMousePosition = m_rPlayerInput.actions["MousePosition"];
        }
    }

    private void Start() {
        if (m_rCharacterSettings != null) {
            m_fDefaultHeight = m_rCharacterSettings.Height;
        }
    }

    private void OnEnable() {
        if (m_rJumpControl != null) {
            m_rJumpControl.OnJump.AddListener(OnJumpStart);
        }
        if (m_rPlayerInput != null) {
            m_rMove.performed += OnMove;
            m_rMove.canceled += OnMoveStop;
            m_rSprint.performed += OnSprint;
            m_rSprint.canceled += OnSprintStop;
            m_rJump.started += OnJump;
            m_rCrouch.started += OnCrouch;
            m_rMousePosition.performed += OnMousePosition;
        }
    }

    private void OnDisable() {
        if (m_rJumpControl != null) {
            m_rJumpControl.OnJump.RemoveListener(OnJumpStart);
        }
        if (m_rPlayerInput != null) {
            m_rMove.performed -= OnMove;
            m_rMove.canceled -= OnMoveStop;
            m_rSprint.performed -= OnSprint;
            m_rSprint.canceled -= OnSprintStop;
            m_rJump.started -= OnJump;
            m_rCrouch.started -= OnCrouch;
            m_rMousePosition.performed -= OnMousePosition;
        }
    }

    private void Update() {
        if (m_rAnimator != null) {
            if (m_rMoveControl != null) {
                float fSpeed = m_rMoveControl.CurrentSpeed;
                m_rAnimator.SetFloat("Speed", fSpeed);
                float fDampTime = 0.1f;
                float fDeltaTime = Time.deltaTime;
                float fSideStep = m_rMoveControl.LocalDirection.x;
                m_rAnimator.SetFloat("SideStep", fSideStep, fDampTime, fDeltaTime);
                float fForward = m_rMoveControl.LocalDirection.z;
                m_rAnimator.SetFloat("Forward", fForward, fDampTime, fDeltaTime);
            }
            if (m_rGroundCheck != null) {
                m_rAnimator.SetBool("IsGround", m_rGroundCheck.IsOnGround);
            }
            if (m_rCharacterSettings != null) {
                if (m_rAnimator.GetBool("IsCrouch")) {
                    m_rCharacterSettings.Height = m_fDefaultHeight / 1.5f;
                }
                else {
                    m_rCharacterSettings.Height = m_fDefaultHeight;
                }
            }
        }
    }

    private void OnMove(InputAction.CallbackContext context) {
        if (m_rMoveControl == null) {
            return;
        }
        Vector2 value = context.ReadValue<Vector2>();
        m_rMoveControl.Move(value);
    }

    private void OnMoveStop(InputAction.CallbackContext context) {
        if (m_rMoveControl == null) {
            return;
        }
        Vector2 value = context.ReadValue<Vector2>();
        m_rMoveControl.Move(value);
    }

    private void OnSprint(InputAction.CallbackContext context) {
        if (m_rMoveControl == null) {
            return;
        }
        m_rMoveControl.MoveSpeed = 4f;
        m_rMoveControl.TurnPriority = 10;
    }

    private void OnSprintStop(InputAction.CallbackContext context) {
        if (m_rMoveControl == null) {
            return;
        }
        m_rMoveControl.MoveSpeed = 1.2f;
        m_rMoveControl.TurnPriority = 0;
        if (m_rCursorPositionControl != null) {
            m_rCursorPositionControl.TurnPriority = 0;
        }
    }

    private void OnJump(InputAction.CallbackContext context) {
        if (m_rJumpControl == null) {
            return;
        }
        m_rJumpControl.Jump(true);
    }

    private void OnJumpStart() {
        if (m_rAnimator != null && m_rJumpControl != null) {
            if (m_rJumpControl.AerialJumpCount >= 1) {
                m_rAnimator.Play("DoubleJump");
            }
            else {
                m_rAnimator.Play("JumpStart");
            }
        }
    }

    private void OnCrouch(InputAction.CallbackContext context) {
        if (m_rAnimator != null) {
            if (m_rAnimator.GetBool("IsCrouch")) {
                if (m_rHeadContactCheck != null && !m_rHeadContactCheck.IsObjectOverhead) {
                    m_rAnimator.SetBool("IsCrouch", false);
                    if (m_rMoveControl != null) {
                        m_rMoveControl.MoveSpeed = 1.2f;
                    }
                }
            }
            else {
                m_rAnimator.SetBool("IsCrouch", true);
                if (m_rMoveControl != null) {
                    m_rMoveControl.MoveSpeed = 0.8f;
                }
            }
        }
    }

    private void OnMousePosition(InputAction.CallbackContext context) {
        if (m_rMousePosition != null && m_rCursorPositionControl != null) {
            Vector2 vecMousePos = m_rMousePosition.ReadValue<Vector2>();
            m_rCursorPositionControl.LookTargetPoint(vecMousePos);
            m_rCursorPositionControl.TurnPriority = 10;
        }
    }
}

動作確認

Unityエディターで再生して、動作確認します。
ユニティちゃんがマウスポインターのほうを向きます。
走っている時は、走っている方向を向きます。

まとめ

Project TCC のキャラクターの向きを変えるサンプルを Visual Scripting から C# スクリプトに変換して動かしてみました。
マウスポインターの位置を取得してゲーム内に反映させることが出来ました。

コメント

タイトルとURLをコピーしました