LoginSignup
1
0

Unityのキャラクターをキーボード操作できるようになるまでにやったこと

Last updated at Posted at 2024-04-18

はじめに

本記事では、VRMフォーマットで作成されたキャラクターを、キーボード操作で動かせるようになるまでに必要なことなどをつらつらっとメモっています。

さらに、NavMesh 使って、自動巡回できるようにもしたい。

前提とする環境

  • Windows 環境:Windows 10/11
  • Linux 環境:Ubuntu 20.04 LTS
  • Mac 環境
    • Intel
      • macOS Catalina ver.10.15.7 以降
    • Applesilicon

キャラクタの3Dモデル

3Dモデル(VRM ファイル)は自作するか、入手しておく必要があります。

入手先としては、この辺りが参考になるかも。

※VRoid Hubは、3Dキャラクターのためのプラットフォームです。

ステップ

  1. Unityを起動する
  2. UniVRMをダウンロードする
  3. UnityにUniVRM unitypackageを Import する
  4. VRMファイルをインポートして、変換する
  5. キャラクタ操作スクリプトの設計をする
  6. AnimationControllerを作成する
  7. Unityスクリプトを作成する
  8. キャラクタに諸々アタッチして動作チェック

VRMファイルをインポートして、変換する

Unity の Scenes 直下に、Model フォルダを作成して、VRMファイルを D&D します。

スクリーンショット 2024-04-18 11.07.13.png

(上図はmitone.vrmというファイルを配置したもの)

mitonをクリックして、Inspectorビューを開き、Migrate To Vm1 をチェックし、Apply をクリック。

スクリーンショット 2024-04-18 11.08.06.png

成功すると、キャラクタが見えるようになる!

スクリーンショット 2024-04-18 11.09.41.png

キャラクタ操作スクリプトの設計をする

キャラクタはキーボードで操作します。
操作方法は、以下です。

  • 上下キー
    • 前進、後進する
  • 左右キー
    • 方向を変更する
  • スペースキー
    • ジャンプする

プログラムの処理フローは以下の流れです。

スクリーンショット 2024-04-18 11.41.33.png

キーボード入力は、Unityスクリプトがモニタリングします。そして、入力されたキー内容に応じて AnimationControllerの状態遷移とキャラクタの動き(Motion)を切り替えます。

speed_v、speed_h、jumpはそれぞれ、Animation Controllerへの入力パラメータです。

  • speed_v(-1〜1の値)
    • 上下キー操作の結果:下は負の値、上は正の値
  • speed_h(-1〜1の値)
    • 左右キー操作の結果:左は負の値、右は正の値
  • jump(true/false)
    • スペースキー操作の結果:trueはジャンプし、falseはジャンプ解除する

AnimationControllerを作成する

Unityの「Animation Controller」は、キャラクターやオブジェクトのアニメーション状態を管理し、遷移を制御するためのツールです。これを使うと、異なるアニメーションクリップ間で滑らかに遷移するための条件やルールを設定できます。

作り方は、プロジェクトビューで、コンテキストメニューから、Create -> Animation Controllerをクリックです(下図)。

スクリーンショット 2024-04-18 11.52.11.png

状態設計と実装

ダブルクリックすると、下図のように状態が3つ見えます。

スクリーンショット 2024-04-18 11.56.32.png

今回は、下図のような状態遷移にします。

スクリーンショット 2024-04-18 12.06.56.png

初期状態は、Locomotionで、ここで上下・前後移動の動きを実現する状態です。Jumpは、キャラクタをジャンプさせる状態です。

Locomotionは、下図のようにFrom New Blend Treeで作成します。

スクリーンショット 2024-04-18 12.25.10.png

Jumpは、下図のようにEmptyで作成します。

スクリーンショット 2024-04-18 12.26.21.png

次に、入力パラメータを設計内容に従って、それぞれ追加します。

そして、状態遷移トリガを追加します。

Locomotion:jumpがtrueの場合に、Jumpに遷移
スクリーンショット 2024-04-18 13.02.58.png

Has Exit Timeのチェックを外す必要があります。(理由はまだわかっていません...)

Jump:jumpがfalseの場合に、Locomotionに遷移
スクリーンショット 2024-04-18 13.04.06.png

モーション設定

今回利用するモーションとしては、ユニティちゃんを利用します。

最新のものをダウンロードして、Import します。

Jump のモーション設定

Jumpを選択して、Motionをクリックして、JUMP0を選択します。

スクリーンショット 2024-04-18 12.28.03.png

Locomotion のモーション設定

Locomotionの状態では、上下・前後の移動のモーションを入力パラメータに応じて切り替えます。

そのための設定が、下図のものです。

スクリーンショット 2024-04-18 12.35.08.png

設定方法の詳細はこちらが参考になります。

Unityスクリプトを作成する

今回作成したUnityスクリプトは以下のものです。

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

public class CharacterOperation : MonoBehaviour
{

	// Animator コンポーネント
	private Animator animator;

	// 設定したフラグの名前
	private const string key_isJump = "jump";
	private Rigidbody my_body;

	// Start is called before the first frame update
	void Start()
	{
		this.animator = GetComponent<Animator>();
		my_body = GetComponent<Rigidbody>();

	}
	float speed = 2.0f;
	void Update()
	{
		var h = Input.GetAxis("Horizontal");
		var v = Input.GetAxis("Vertical");
		//Debug.Log("h=" + h + " v=" + v);
		if (Mathf.Abs(h) > 0.01f || Mathf.Abs(v) > 0.01f)
		{
			if (v < 0)
			{
				v = v / 1.5f;
			}
			var localVelocity = new Vector3(0, 0, v);
			var worldVelocity = transform.TransformDirection(localVelocity);
			my_body.velocity = worldVelocity * speed;

			//向き操作
			if (h > 0)
			{
				transform.Rotate(0, 0.1f, 0);  // 右に0.1度回転
			}
			else if (h < 0)
			{
				transform.Rotate(0, -0.1f, 0);  // 左に0.1度回転
			}
			//アニメーション操作
			//Debug.Log("x=" + my_body.velocity.x + " z=" + my_body.velocity.z);
			animator.SetFloat("speed_v", v);
			animator.SetFloat("speed_h", h);

		}
		if (Input.GetKey(KeyCode.Space))
		{
			this.animator.SetBool(key_isJump, true);
		}
		else
		{
			this.animator.SetBool(key_isJump, false);
		}
	}
}

キャラクタに諸々アタッチして動作チェック

まずは、キャラクタをシーンビューに D&D します。

スクリーンショット 2024-04-18 12.41.00.png

次に、物理オブジェクト RigidBody を割り当てます。この時、ContraintsのFreeze ROtation のXとZにチェックを入れます。(これやっとかないと移動する時に倒れちゃうので)

さらに、コライダー(Capsule Collider)を割り当てます。この時、キャラクタのサイズに合わせてパラメータ調整します。

スクリーンショット 2024-04-18 12.45.12.png

スクリーンショット 2024-04-18 12.45.20.png

次に、先ほど作成したスクリプトをアタッチします。

スクリーンショット 2024-04-18 12.45.53.png

最後に、AnimationControllerを割り当て終了です。

スクリーンショット 2024-04-18 12.46.37.png

デモ

こんな感じで動きます。

自動巡回させるためのコード

Unity の NavMesh を使うと簡単に実現できます。

インストール

Unityのパッケージマネージャで NavMesh をインストールする必要があります。

方法

  • 移動領域に、NavMeshSurfaceアタッチして Bake する
  • 障害物を置きたい場合は、NavMeshObstacleをアタッチして Curve にチェックをいれる
  • 移動させたいオブジェクトに NavMeshAgentをアタッチ。Speedで移動速度をコントロールできる

プログラム

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

public class CharacterOperation : MonoBehaviour
{

	// Animator コンポーネント
	private Animator animator;
	public Transform[] goals;
	private NavMeshAgent agent;

	// 設定したフラグの名前
	private const string key_isJump = "jump";
	private Rigidbody my_body;
	private int curr_goal_inx = 0;

	// Start is called before the first frame update
	void Start()
	{
		this.animator = GetComponent<Animator>();
		my_body = GetComponent<Rigidbody>();
		agent = this.GetComponent<NavMeshAgent>();
		if (agent == null)
        {
			throw new System.Exception("can not find Agent");
        }
		agent.destination = goals[0].position;

	}
	private void Update()
    {
		Vector3 velocity = agent.velocity;

		Vector3 localVelocity = transform.InverseTransformDirection(velocity);

		// ローカル速度のz成分とx成分をアニメーターに設定
		animator.SetFloat("speed_v", localVelocity.z);
		animator.SetFloat("speed_h", localVelocity.x);
		if (agent.remainingDistance < 0.5f)
        {
			curr_goal_inx++;
			if (curr_goal_inx >= this.goals.Length)
            {
				curr_goal_inx = 0;
            }
			agent.destination = goals[curr_goal_inx].position;
		}
	}
}

最後に

ここで利用させていただきましたVRMファイルは、株式会社プラスプラス様からご提供いただいたものを使用しております。ご協力いただき誠にありがとうございます。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0