[Unity] Character Controller メモ(非エンジニア)

Character Controller

オブジェクトの移動と衝突判定を行えるComponent

プロパティ

Slope Limit 登ることができる傾斜角の限界値 値以上の傾斜は登れない
ただし傾斜角値以上でも着地はできるのでジャンプを使えば登れてしまう

Step Offset 登ることができる段差の高さ 値を大きくすると以下のエラーが発生する可能性がある (Height + Radius * 2)より小さい値にすればよい
Step Offset must be less or equal to <scaled Height> + <scaled Radius> * 2

Skin Width 接地面までの距離 値が大きいとオブジェクトが浮いているように見える その時はこの値を小さくするか CenterのYで位置を上にずらすと良い

Min Move Distance 移動値の切り捨て この値以下の移動値を無視する

Center 当たり判定の中心位置 (0,0,0)はAddComponentされているオブジェクトの原点位置
原点位置が足元の場合、Heightの半分の値をYに入れれば接地面が足元にくる HeightがRadiusより小さい場合はRadiusと同じ値をYに入れれば接地面が足元にくる

Radius 当たり判定の半径

Height 当たり判定の高さ Radiusより小さい値にすると無視される

以下公式マニュアルの引用

Slope Limit コライダーが、指定した値以下の勾配(単位は度)のみを登るよう制限します。

Step Offset 指定された値よりも地面に近い場合にのみ、キャラクターが階段を登ります。キャラクターコントローラーの高さより大きくした場合エラーが発生します。

Skin width 2 つのコライダーが、Skin Width の深さまで互いに食い込みます。Skin Width が大きくなると、ジッタが減ります。Skin Width が小さいと、キャラクターが動けなくなる場合があります。値を Radius の 10% に設定しておくとよいでしょう。

Min Move Distance キャラクターが指定された値未満で動こうとしても、まったく動きません。これは、ジッタを減らすのに利用できます。ほとんどの場合、この値は 0 のままにしておいてください。

Center これにより、ワールド空間でカプセルコライダーをオフセットしますが、キャラクターがどのように旋回するかには影響しません。

Radius カプセルコライダーのローカル半径。これは基本的にコライダーの幅となります。

Height キャラクターの カプセルコライダー の高さ。この値を変更すると、正負の方向で Y 軸に沿ってコライダーが拡大縮小されます。

https://docs.unity3d.com/ja/2019.4/Manual/class-CharacterController.html

移動する

以下のScriptをCharacterControllerをつけているオブジェクトにAddComponentする
AddComponentできない時はScriptのクラス名とファイル名が同じになっているか確認する

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SampleScript : MonoBehaviour // クラス名はファイル名と同じにする
{
    //CharacterController型の変数の宣言
    private CharacterController _CharaCon;
    //移動値用の変数の宣言 vectro3型はxyzの3つの値を持てる
    private Vector3 _MoveDirection = Vector3.zero;
    
    void Start()
    {
        // AddComponentされているCharacterControllerを取得して_CharaConに代入
        _CharaCon = this.GetComponent<CharacterController>();
    }

    void Update()
    {
        //--------------------
        // 落下の処理
        //--------------------
        // 地面に接地している時
        if (_CharaCon.isGrounded){
            // Yの移動値(落下速度)を戻す
            if(_MoveDirection.y < -0.1f){
                _MoveDirection.y = -0.1f;
            }
        }
        // 地面から離れている時
        else if (!_CharaCon.isGrounded){
            // Yの移動値(落下速度)がー5以上の時
            if(_MoveDirection.y > -5){
                // Yの移動値(落下速度)の加算
                _MoveDirection.y -= 0.5f;
            }
            // ↑キーを押していない時
            if (!Input.GetKey(KeyCode.UpArrow)){
                // 移動値の反映
                _CharaCon.Move(_MoveDirection * Time.deltaTime);
            }
        }
        

        //--------------------
        // 移動の処理
        //--------------------
        // ↑キーを押している時
        if (Input.GetKey(KeyCode.UpArrow))
        {
            // 移動速度の値
            float speed = 1;
            // オブジェクトの向きと移動速度を掛けて変数へ代入
            Vector3 velocity = this.transform.rotation * new Vector3(0, 0, speed);
            // 移動値を代入
            _MoveDirection = new Vector3 (velocity.x, _MoveDirection.y, velocity.z);
            // 移動値の反映
            _CharaCon.Move(_MoveDirection * Time.deltaTime);
            // 移動値のリセット
            _MoveDirection.x = 0;
            _MoveDirection.z = 0;
        }

        //--------------------
        // オブジェクトの回転の処理
        //--------------------
        //→キーが押されていて←キーが押されていない時
        if (Input.GetKey(KeyCode.RightArrow) && !Input.GetKey(KeyCode.LeftArrow)){
            // オブジェクトの回転
            this.transform.Rotate(Vector3.up, 5.0f);
        }
        //←キーが押されていて→キーが押されていない時
        else if (Input.GetKey(KeyCode.LeftArrow) && !Input.GetKey(KeyCode.RightArrow)){
            // オブジェクトの回転
            this.transform.Rotate(Vector3.up, -5.0f);
        }

        //--------------------
        // ジャンプの処理
        //--------------------
        // 地面に接地している時
        if(_CharaCon.isGrounded)
        {
            // Jキーを押した時
            if(Input.GetKeyDown(KeyCode.J)){
                // Yの移動値にジャンプの値を代入
                _MoveDirection.y = 8.0f;
                // ↑キーを押していない時
                if (!Input.GetKey(KeyCode.UpArrow)){
                    // 移動値の反映
                    _CharaCon.Move(_MoveDirection * Time.deltaTime);
                }
            }
        }
    }
}

Scriptの補足説明

private CharacterController _CharaCon;
_CharaConという名前の変数をCharacterController型で宣言

private Vector3 _MoveDirection = Vector3.zero;
_MoveDirectionという名前の変数をVector3型で宣言
Vector3.zeroはnew Vector3(0,0,0)と同義

_CharaCon = this.GetComponent<CharacterController>();
オブジェクトにAddComponentされているCharacterControllerを取得して
変数_CharaConに代入
this.はこのScriptがAddComponentされているオブジェクトを指定している

_CharaCon.isGrounded
変数_CharaConに入っているCharacterControllerが接地しているかを取得
接地していれば true 接地していなければ false

_MoveDirection.y = -0.1f;
_MoveDirectionのYの値に-0.1を代入
整数でない値のときは基本的にfをつける(floatのf)
接地後に落下速度をリセットしている
リセットしないとジャンプせずに床から落下した場合に最速状態で落下する

_MoveDirection.y -= 0.5f;
上記は_MoveDirection.y = _MoveDirection.y - 0.5f;と同義
落下速度をどんどん速くしていっている

Input.GetKey(KeyCode.UpArrow)
上キーを押しているかを取得
押している場合は true 押していなければ false
if文で先頭に!をつけるとfalseかどうかチェックする
Input.GetKey(KeyCode.○○) ○○を押している時
Input.GetKeyDown(KeyCode.○○) ○○を押した時
Input.GetKeyUp(KeyCode.○○) ○○を離した時

UnityはInput ManagerからInput Systemに移行しようとしているので数年後のバージョンは上記のInput.GetKeyはよろしくないかもしれない

_CharaCon.Move(_MoveDirection * Time.deltaTime);
CharacterControllerに移動値を反映する
この処理がないとCharacterControllerは動かない
Time.deltaTimeについては以下を参考にしてみてください

Vector3 velocity = this.transform.rotation * new Vector3(0, 0, speed);
オブジェクトの角度に移動用の値を掛けて変数に代入している
この場合はZ軸を正面としている X軸が正面の場合はXのところにspeedを入れる

_MoveDirection.x = 0;
_MoveDirection.z = 0;
移動値のリセット
移動値をそのままにしておくと移動し続ける事になる
例えば、移動を止めた後にジャンプを行うとY移動値の反映とともにXZの移動値も反映されてしまうので移動が終わったら移動値のリセットを行わなければならない
ここでは移動値の反映の直後にリセットを行なっている

this.transform.Rotate(Vector3.up, 2.5f);
オブジェクトの現在の角度に任意の角度を加算する
Vector3.upはオブジェクトの上面を指し
どの面を指定するかで回転軸が変わる

Vector3.forward 正面
Vector3.back 背面
Vector3.up 上面
Vector3.down 下面
Vector3.right 右面
Vector3.left 左面

CharacterControllerのプロパティの値を変更

無闇に変更するものではないが一応変更可能
特にMin Move Distanceを移動値以上にすると動かなくなるので注意

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SampleScript2 : MonoBehaviour // クラス名はファイル名と同じにする
{
    //CharacterController型の変数の宣言
    private CharacterController _CharaCon;

    void Start()
    {
        // AddComponentされているCharacterControllerを取得して_CharaConに代入
        _CharaCon = this.GetComponent<CharacterController>();

        // Slope Limit
        _CharaCon.slopeLimit = 50;
        // Step Offset
        _CharaCon.stepOffset = 0.5f;
        // Skin Width
        _CharaCon.skinWidth = 0.1f;
        // Min Mouse Distance
        _CharaCon.minMoveDistance = 0.01f;
        // Center
        _CharaCon.center = new Vector3(0, 0.5f, 0);
        // Radius
        _CharaCon.radius = 0.5f;
        // Height
        _CharaCon.height = 0.5f;
    }
}

CharacterControllerのOn/Off

Offにすることはまずないが一応できる

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SampleScript3 : MonoBehaviour // クラス名はファイル名と同じにする
{
    //CharacterController型の変数の宣言
    private CharacterController _CharaCon;

    void Start()
    {
        // AddComponentされているCharacterControllerを取得して_CharaConに代入
        _CharaCon = this.GetComponent<CharacterController>();
    }
    void Update()
    {
        // Sキーを押した時かつCharacterControllerがOnの時
        if(Input.GetKeyDown(KeyCode.S) && _CharaCon.enabled){
            // CharacterControllerをOffにする
            _CharaCon.enabled = false;
        }
        // Sキーを押した時かつCharacterControllerがOffの時
        else if(Input.GetKeyDown(KeyCode.S) && !_CharaCon.enabled){
            // CharacterControllerをOnにする
            _CharaCon.enabled = true;
        }
    }
}

勉強中ですので説明が間違っている可能性があります自分でも調べて確認してみてください

この記事が気に入ったらサポートをしてみませんか?