Unity

【Unity】キーボードでキャラクターを操作する

投稿日:2020年9月30日 更新日:

概要

以前に以下の記事でUnityの新規プロジェクトの作成からUnity Assetとして提供されているキャラクターオブジェクトの「Robot Kyle」をSceneへ配置するところまでの流れを紹介しました。

今回はその続きとしてキーボード入力でRobot Kyleを操作する方法について紹介していきます。

体系的にUnityを理解したい場合は本で勉強するのもおすすめです。


環境

  • Windows10
  • Unity 2020.1.f1


目的

キーボード入力からRobotKyleの操作の実現を目指します。具体的には以下を行えるようにしたいと思います。

  • キーボードの↑↓ボタンで前後に進む
  • キーボードの←→ボタンで方向転換する
  • スペースキーでジャンプする
  • Shift + ↑↓ボタンでダッシュで前後に進む

今回はキャラクターにアニメーションは付けずに、初期姿勢のまま位置と姿勢のみ動かす、というところまでを目指します。

Step1 : コンポーネント類の追加

Robot Kyleを動かすにあたり物理計算を行うためのRigidbodyと、衝突を管理するためのColliderのコンポーネントを設定していきます。

Rigidbodyの追加

まずはRigidbodyを追加します。
HierachyからRobot Kyleを選択し、InspectorタブからAdd Componentを選択します。

検索ボックスが現れますので”rigid”などと打ってRigidbodyが出てきたら選択します。

Rigidbodyのパラメータはデフォルトのままで問題ありません。


Colliderの追加

同様にColliderも追加していきます。Add Componentから”collider”と入力し、Capsule Colliderを選択します。

Capsule Colliderの設定値はうまいくRobot Kyleの体が収まるくらいに調整するのが良いです。ここでは以下のように設定しています。

Y0.9
Radius0.3
Height1.8
Capsule Collider設定


Step2 : Main Cameraの設定

次にMain Cameraの設定を行います.
HierarchyのMain Cameraをドラッグ&ドロップでRobot Kyleの配下に配置します。

次に、Main CameraのInspectorでTransformを調整します。

ここは好みになりますが、私の場合はRobot Kyleのなるべく全身を映るようにしたかったため、以下のように設定してあります。

X : 0
Y : 1.5
Z : -2.5


Step3: 操作スクリプトの作成

ProjectタブのAsset上で右クリックし、Create > C# Scriptからscriptファイルを新規作成し、PlayerConという名前を付けます。

作成したスクリプトに操作の部分を書いていくのですが、大まかに以下の方針で進めることにしました。

  • 移動はTransform.positionを使用して制御する。
  • ジャンプ中に空中で移動はできないようにする
  • 斜め前にもジャンプできるようにする
  • 二段ジャンプは禁止する

スクリプト全体

【PlayerCon.cs】

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

public class PlayerCon : MonoBehaviour
{
    // Start is called before the first frame update

    //キャラクターの操作状態を管理するフラグ
    [SerializeField] public bool onGround = true;
    [SerializeField] public bool inJumping = false;

    //rigidbodyオブジェクト格納用変数
    Rigidbody rb;

    //移動速度の定義
    float speed = 6f;

    //ダッシュ速度の定義
    float sprintspeed = 9f;

    //方向転換速度の定義
    float angleSpeed = 200;

   //移動の係数格納用変数
    float v;
    float h;

    void Start()
    {

//Shift+上下キーでダッシュ、上下キーで通常移動,それ以外は停止
        if (Input.GetKey(KeyCode.UpArrow) && Input.GetKey(KeyCode.LeftShift))
            v = Time.deltaTime * sprintspeed;
        else if (Input.GetKey(KeyCode.DownArrow) && Input.GetKey(KeyCode.LeftShift))
            v = -Time.deltaTime * sprintspeed;
        else if (Input.GetKey(KeyCode.UpArrow))
            v = Time.deltaTime * speed;
        else if (Input.GetKey(KeyCode.DownArrow))
            v = -Time.deltaTime * speed;
        else
            v = 0;

        //移動の実行
        if (!inJumping)//空中での移動を禁止
        {
            transform.position += transform.forward * v;
        }

        //スペースボタンでジャンプする
        if (onGround)
        {
            if (Input.GetKey(KeyCode.Space))
            {
                //ジャンプさせるため上方向に力を発生
                rb.AddForce(transform.up * 8, ForceMode.Impulse);
                //ジャンプ中は地面との接触判定をfalseにする
                onGround = false;
                inJumping = true;

                //前後キーを押しながらジャンプしたときは前後方向の力も発生
                if (Input.GetKey(KeyCode.UpArrow))
                {
                    rb.AddForce(transform.forward * 6f,ForceMode.Impulse);
                }
                else if (Input.GetKey(KeyCode.DownArrow))
                {
                    rb.AddForce(transform.forward * -3f, ForceMode.Impulse);
                }
            }
        }

        
        //左右キーで方向転換
        if (Input.GetKey(KeyCode.RightArrow))
            h = Time.deltaTime * angleSpeed;
        else if (Input.GetKey(KeyCode.LeftArrow))
            h = -Time.deltaTime * angleSpeed;
        else
            h = 0;
        
        //方向転換動作の実行
        transform.Rotate(Vector3.up * h);

    }
    //地面に接触したときにはonGroundをtrue、injumpingをfalseにする
    void OnCollisionEnter(Collision col)
    {
        if(col.gameObject.tag=="Ground")
        {
            onGround = true;
            inJumping = false;
        }
    }
}

スクリプトの中身について順を追って紹介します。

void Start部

今回、Playerの回転を止める際とジャンプするための力を発生させるためにRigidbodyを使用します。そのため初めにPlayerのRigidbody関連のオブジェクトを取得しておきます。

rb = this.GetComponent<Rigidbody>();
rb.constraints = RigidbodyConstraints.FreezeRotation;

void Update部

前後方向の移動速度定義

押下しているキーに応じて前後方向の速度を変化させています。
Shiftと方向ボタンを押したときはダッシュ速度(sprintspeed)、方向ボタンの場合は通常移動速度(speed)を使用しています。

        if (Input.GetKey(KeyCode.UpArrow) && Input.GetKey(KeyCode.LeftShift))
            v = Time.deltaTime * sprintspeed;
        else if(Input.GetKey(KeyCode.DownArrow) && Input.GetKey(KeyCode.LeftShift))
            v = -Time.deltaTime * sprintspeed;
        else if(Input.GetKey(KeyCode.UpArrow))
            v = Time.deltaTime * speed;
        else if(Input.GetKey(KeyCode.DownArrow))
            v = -Time.deltaTime * speed;
        else
            v = 0;
       //移動の実行
        if (!inJumping)//空中での移動を禁止
        {
            transform.position += transform.forward * v;
        }


方向転換

  • 方向転換のベクトル定義
  • transform.Rotateで回転
        //左右キーで方向転換
        if (Input.GetKey(KeyCode.RightArrow))
            h = Time.deltaTime * angleSpeed;
        else if (Input.GetKey(KeyCode.LeftArrow))
            h = -Time.deltaTime * angleSpeed;
        else
            h = 0;


ジャンプ

ジャンプする条件としてスペースキーの押下とキャラクターが地面に接触していることとしています。これにより空中での二段ジャンプを禁止しています。

Addforceを使用して上方向の力を発生させることでジャンプをさせています。また、前後方向キーを押しながらスペースキーを押すことで、前方向の力も同時に発生させ、斜め前にジャンプするようにしています。後ろ向きの場合は少し力を弱めています。

        //スペースボタンでジャンプする
        if (Input.GetKey(KeyCode.Space) && onGround)
        {
            //ジャンプ時の初期速度を0に設定
            rb.velocity = new Vector3(0, 0, 0);

            //ジャンプさせるため上方向に力を発生
            rb.AddForce(transform.up * 300);

            //前方向キーを押しながらのジャンプの時には後方向に力を発生させる
            if (Input.GetKey(KeyCode.UpArrow))
                rb.AddForce(transform.forward * 180);

            //後ろ方向キーを押しながらのジャンプの時には後方向に力を発生させる
            else if (Input.GetKey(KeyCode.DownArrow))
                rb.AddForce(transform.forward * -100);

            //ジャンプ中は地面との接触判定をfalseにする
            onGround = false;
        }


OnCollisionEnter部

予め地面にGroundタグをつけておき、キャラクターが地面と接触した場合にはonGroundをtrueにします。また、inJumpingをfalseにします。

    //地面に接触したときにはonGroundをtrue、injumpingをfalseにする
    void OnCollisionEnter(Collision col)
    {
        if(col.gameObject.tag=="Ground")
        {
            onGround = true;
            inJumping = false;
        }
    }
 注意事項:TerrianにGroundタグが付いていること、Robot KyleのCapsule Colliderのis Trigerにチェックが入っていないこと 

まとめ

今回はキーボードでRobot Kyleを動かすところまでを実践しました。ただ、この状態だとまだアニメーションがついていないので、味気ないです。次回はさらにこのスクリプトを改良し、アニメーションをつけていきたいと思います。

以上

-Unity

執筆者:


comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

関連記事

【Unity】mixamoのアニメーションが動かない場合の対処

Contents1 概要2 環境3 最初にやったこと3.1 FBXのダウンロード3.2 インポートとRigの設定4 困ったこと5 原因と対処方法6 分かったこと 概要 ハイクオリティな3Dキャラクター …

【Unity】 Standard Assetsのダウンロードとインポート

Contents1 目的2 環境3 Step1 : Asset Storeを開く4 Step2 : Standard Assetsのインストール5 まとめ 目的 UnityでStandard pack …

【Unity】ゲームパッド(F310)とInput Managerとの対応まとめ

Contents1 概要2 結論3 マッピングの確認方法3.1 使用した設定3.2 使用したスクリプト 概要 Unityでロジクール製のF310でキャラクター操作する際に、F310の各ボタンをInpu …

UnityでPostProcessManager.cs(425,66): error CS0117: ‘EditorSceneManager’ does not contain a definition for ‘IsGameObjectInMainScenes’が出た時の対処法

Contents1 概要2 環境3 発生状況4 対処方法5 まとめ 概要 UnityのAsset StoreからParticle Packageをダウンロードしてimportしたところ、以下のエラーが …

【Unity】キャラクターにSimpleAnimationでアニメーションをつける

Contents1 概要2 環境3 使用するキャラクタオブジェクト4 Step1 : Animationの 入手5 Step2 : SimpleAnimationの取得6 Step3 : Inspec …

言語切り替え

カテゴリー