【UnityC#講座】ユニティちゃんをスカイリム風に操作する

Unity2018.1.5f1
Windows10

以前ユニティちゃんを操作できるようにしました。

【UnityC#講座】3D人型モデルの動かし方をユニティちゃんで学ぶ【Animator】

今回はその時とは別の操作方法にします。

名作オープンワールドRPG「スカイリム」のようにマウスで方向を変えてそれを基準に前後左右、ジャンプ、そして攻撃と高速移動を設置します。
さあ、まずはプロジェクト「SkyrimController」を作ってください。

■ユニティちゃんをセットする

以前と重複になりますがまずはユニティちゃんをアセットストアからダウンロードします。

ユニティちゃんライセンス

この作品はユニティちゃんライセンス条項の元に提供されています

ProjectからunitychanをHierarchyかSceneにドラッグ&ドロップしてください。

UnityChan > Models > unitychan

次にユニティちゃんが乗る地面ですが、以前はPlanですが今回はTerrainを使います。

Hierarchy > 3D Object > Terrain

ユニティちゃんがTerrainにちゃんと乗るようにしておいてください。
あとタグの設定もしておきましょう。

SkyrimController/Terrainのタグ

SkyrimController/Add Tag

Inspector > Tag > Add Tag > Tags & Layer > Tags > +

SkyrimController/タグ設定

を押して出てきた欄にGroundを追加します。
ついでに後で使うEnemyも作っておきましょう。

SkyrimController/Terrainにタグ設定

最後にTerrainにGroundのTagを設定して出来上がりです。

次にユニティちゃんにCapsule ColliderとRigidbodyを追加します。
Hierarchyのunitychanにクリックし、そのInspectorからAdd Componentをクリック、Capsule ColliderとRigidbodyを検索してください。

Capsule Colliderはこのようにしましたが厳密にこの通りにする必要はありません。

SkyrimController/CapsuleCollider SkyrimController/CapsuleColliderとユニティちゃん

RigidbodyはConstraintsのFreeze Rotationのチェックボックスをすべてチェックしてください。
これで不要な回転をしなくなります。

SkyrimController/Rigidbody/ConstraintsのFreeze Rotation

■Animatorの設定をする

これも以前したことで説明は重複になるのでざっと説明します。
詳しい説明が見たい人はこの記事を見てください。

【UnityC#講座】3D人型モデルの動かし方をユニティちゃんで学ぶ【Animator】

SkyrimController/Animator Controller/ステートマシン

1.Animator Controllerを開く。

Project > Create > Animator Controller

名前は「SkyrimAnime」にしました。
ウィンドウが小さくて扱いづらい時はAnimatorのタブをウィンドウの外に持ち出すと別画面として使えます。
マウスのホイールでズームを操れます。
ウィンドウの中身を動かしたいときはホイールをクリックしたまま動かします。

2.罫線上で右クリックし、

Create State > Empty

とすると長方形のもの、ステートマシンが出てきます。
9つ出してInspectorから以下の通りに名前をつけてください。

Idle
Front
Back
Right
Left
Jump
Sprint
Attack

そしてそれぞれにInspectorのMotionにアニメーションを以下の通りに入れます。

Idle → WAIT00
Front → RUN00_F
Back → WALK00_B
Right → WALK00_R
Left → WALK00_L
Jump → JUMP00
Sprint → POSE29
Attack → POSE26

SkyrimController/Animator Controller/Transition追加

3.Idleを中心にそれぞれのステートマシンを矢印、Transitionでつなぐ。

各ステートマシンを右クリック、Make Transitionをクリックしてつなぎたいステートマシンをクリックします。
もし間違えてつないでしまった場合、TransitionのInspectorのTransitionsの「-」をクリックすると消すことができます。

SkyrimController/Animator Controller/Parametersを設定

4.Parametersを設定する。

Animatorウィンドウの左上にParametersがあるのでクリック、次にBoolをクリックし名前を入れます。
名前は分かりやすくステートマシンと同じで良いでしょう。
Idle以外の7つのParametersを全てBoolで設定してください。

SkyrimController/Animator Controller/TransitionにParametersを設定

5.TransitionにParametersを設定していく。

矢印をクリックし、InspectorのConditionsの+マークをクリックしてください。
そこで先ほど設定したParametersを設定していきます。
Idleつながっている先のステートマシンと同じ名前のParametersを設定します。
そしてTrueとFalseは以下のようにしてください。

Idle → 各ステートマシン True
各ステートマシン → Idle False

SkyrimController/Animator Controller/InspectorのHas Exit Time

あとInspectorのHas Exit Timeのチェックボックスを全て外します。

SkyrimController/Animator/Apply Root Motion

さて、できたAnimator Controllerをユニティちゃんにあてましょう。
Hierarchyのユニティちゃんをクリックし、そのInspectorのAnimatorのControllerの欄に入れます。
そしてApply Root Motionのチェックを外してください。

■スクリプトを作る

Project > Create > C# Script

これで作ったファイルを作り、名前は「SkyrimController」にします。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SkyrimController : MonoBehaviour {
//Rigidbodyはジャンプと高速移動に使います
Rigidbody rb;
//移動スピード
public float speed = 2f;
//Animatorを入れる変数
private Animator animator;
//Terrainに触れているか判定するため
public bool ground = true;
//走る動作を止めるため
public bool moving = true;
//マウスでどれだけ動かすか
//publicをつけるとInspectorから変えられる
//horizontalは横、verticalは縦
public float horizontalSpeed = 2.0F;
public float verticalSpeed = 2.0F;
//Main Cameraを入れる
public Camera camera;
//2か所のカメラの位置を入れ替える
bool cameraPos;
//カメラの位置を一度だけ指定する
bool cameraMove;
//音声ファイルを入れる
public AudioClip audioClip1;
//音声システムを使う
AudioSource audioSource;
//左足と右足に付ける足音出すPrefabを入れる
public GameObject legLeft;
public GameObject legRight;
//敵を判定し対処するオブジェクトを入れる
public GameObject attackObj;
void Start()
{
rb = GetComponent<Rigidbody>();
animator = GetComponent<Animator>();
cameraPos = true;
cameraMove = true;
audioSource = gameObject.AddComponent<AudioSource>();
attackObj.SetActive(false);
}
void Update()
{
//マウスでユニティちゃんとCameraの向きを変える
float h = horizontalSpeed * Input.GetAxis("Mouse X");
float v = verticalSpeed * Input.GetAxis("Mouse Y");
transform.Rotate(0, h, 0);
camera.transform.Rotate(v, 0, 0);
//Cameraの位置切り替え、二通りだけなのでtrueが三人称、falseが一人称にしました
if (cameraPos == true)
{
//Cameraの位置を指定するのは1回だけにする
if (cameraMove == true)
{
//localPosition,localRotationは親の位置、角度を軸に指定する
camera.transform.localPosition = new Vector3(0, 1, -3.5f);
camera.transform.localRotation = Quaternion.Euler(0, 0, 0);
cameraMove = false;
}
//Cameraが縦に角度を変えるとき位置も縦に変わる
camera.transform.Translate(0, v * 0.05f, 0);
}
else
{
if (cameraMove == false)
{
camera.transform.localPosition = new Vector3(0, 1.3f, 0.2f);
camera.transform.localRotation = Quaternion.Euler(0, 0, 0);
cameraMove = true;
}
}
//地面への設置と移動が許可されていないと作動しない
if (ground == true && moving == true)
{
//ジャンプアニメのオフはここでやりました
animator.SetBool("Jump", false);
//Fキーを押すと変数が切り替わりCameraの位置も変わります
if (Input.GetKeyDown(KeyCode.F))
{
cameraPos = !cameraPos;
}
//WSDAキーでの移動は各キーを押すこととZキー押していないことが条件
if (Input.GetKey(KeyCode.W) &&
!Input.GetKeyDown(KeyCode.Z))
{
//前移動のアニメーション再生
animator.SetBool("Front", true);
//Time.deltaTimeでキー押している時間で移動距離決まる
transform.position += transform.forward * speed * Time.deltaTime;
//足音を出すPrefabを出す関数、下のpublic void LegOn()の中身を呼ぶ
LegOn();
}
else if (Input.GetKey(KeyCode.S) &&
!Input.GetKeyDown(KeyCode.Z))
{
animator.SetBool("Back", true);
transform.position -= transform.forward * speed * Time.deltaTime;
LegOn();
}
else if (Input.GetKey(KeyCode.D) &&
!Input.GetKeyDown(KeyCode.Z))
{
animator.SetBool("Right", true);
transform.position += transform.right * speed * Time.deltaTime;
LegOn();
}
else if (Input.GetKey(KeyCode.A) &&
!Input.GetKeyDown(KeyCode.Z))
{
animator.SetBool("Left", true);
transform.position -= transform.right * speed * Time.deltaTime;
LegOn();
}
//Zキーを押すとコルーチンを呼ぶ、下のpublic IEnumerator SprintCoro()の中身を呼ぶ
else if (Input.GetKey(KeyCode.Z))
{
StartCoroutine("SprintCoro");
}
//設定されているキーを押さないとIdle状態になる、public void AnimeCancel()の中身を呼ぶ
else
{
AnimeCancel();
}
//スペースキーを押すことと地面に設置しているとジャンプをする
if (Input.GetKeyDown(KeyCode.Space) && ground == true)
{
ground = false;
//WSDA押しながらジャンプをすると対応する方向へ
if (Input.GetKey(KeyCode.W))
{
//ユニティちゃんのRigidbodyに対しforwardが前方、upが上方に力を加える
rb.AddForce(transform.forward * 500);
rb.AddForce(transform.up * 500);
}
else if (Input.GetKey(KeyCode.S))
{
rb.AddForce(transform.forward * -500);
rb.AddForce(transform.up * 500);
}
else if (Input.GetKey(KeyCode.D))
{
rb.AddForce(transform.right * 500);
rb.AddForce(transform.up * 500);
}
else if (Input.GetKey(KeyCode.A))
{
rb.AddForce(transform.right * -500);
rb.AddForce(transform.up * 500);
}
//WSDA押していないとその場で垂直にジャンプする
else
{
rb.AddForce(transform.up * 500);
}
}
//マウス左クリックで攻撃のコルーチンを呼ぶ、右クリックは(1)、真ん中クリックは(2)
if (Input.GetMouseButton(0))
{
StartCoroutine("AttackCoro");
}
}
}
//AnimeCancel();で呼べる前後左右移動のアニメをオフにする関数
public void AnimeCancel()
{
animator.SetBool("Front", false);
animator.SetBool("Back", false);
animator.SetBool("Right", false);
animator.SetBool("Left", false);
}
//LegOn();で呼べる足音出すPrefabを表示する関数
public void LegOn()
{
legLeft.SetActive(true);
legRight.SetActive(true);
}
//旋風の疾走のコルーチン
public IEnumerator SprintCoro()
{
//旋風の疾走後の足音が嫌なので足音のPrefabを非表示にします
legLeft.SetActive(false);
legRight.SetActive(false);
//移動アニメをオフにすることでWSDAキー押しながらでも旋風の疾走アニメをオンにできる
AnimeCancel();
animator.SetBool("Sprint", true);
//効果音を出す
audioSource.PlayOneShot(audioClip1);
//WSDAキーでの移動をできないようにする
moving = false;
//前方に一定の速度×20で移動
rb.velocity = transform.forward * 20;
//Rigidbodyに働きかけて無重力にするため空中でもまっすぐ移動します
rb.useGravity = false;
//1秒経ってから次のスクリプトを行う
yield return new WaitForSeconds(1.0f);
animator.SetBool("Sprint", false);
//移動速度を一旦0にする
rb.velocity = transform.forward * 0;
//Rigidbodyの重力を復活させる
rb.useGravity = true;
//これで再びWSDAキーで移動できる
moving = true;
}
//攻撃を行う
public IEnumerator AttackCoro()
{
//WSDA押しながら攻撃アニメ再生するには移動アニメをオフにする必要あり
AnimeCancel();
animator.SetBool("Attack", true);
moving = false;
yield return new WaitForSeconds(0.3f);
//左クリックしてから0.3秒後に攻撃判定するオブジェクトが表示される
attackObj.SetActive(true);
//蹴りの動作をして0.5秒後に攻撃判定するオブジェクトは消え蹴り動作終わりに
yield return new WaitForSeconds(0.5f);
attackObj.SetActive(false);
animator.SetBool("Attack", false);
moving = true;
}
//他のColliderに接している間ずっと発動
void OnCollisionStay(Collision col)
{
//Groundタグが付いているもの、今回は地面のTerrainに接している間ずっとground変数はtureになっている
if (col.gameObject.tag == "Ground")
{
//WSDAZスペースキーが効きます
ground = true;
}
}
//他のColliderと離れた時に発動
void OnCollisionExit(Collision col)
{
//GroundタグのTerrainから離れたらジャンプアニメーションをします
if (col.gameObject.tag == "Ground")
{
//WSDAZスペースキーが効かなくなります
ground = false;
animator.SetBool("Jump", true);
AnimeCancel();
}
}
}
view raw 07a.cs hosted with ❤ by GitHub

スポンサーリンク

W 前進
S 後進
D 右移動
A 左移動
スペース ジャンプ
Z 旋風の疾走
マウス左クリック 攻撃

できたらそれをHierarchyのunitychanにドラッグ&ドロップしてください。
ここで一旦動かしてみたいところでしょうが、まだ準備ができていません。
次はInspectorからSkyrimControllerの設定をします。

■カメラと効果音をセットする

SkyrimController/Inspector/空

これはHierarchyのunitychanのInspectorのSkyrimControllerです。
Camera、AudioClip、LegLeft、LegRight、AttackObjを上から順に設定していきます。

1.Camera

まずはHierarchyの最初からあるMain Cameraをunitychanにドラッグ&ドロップしてください。
画像のようになればOKです。

SkyrimController/Main Cameraをユニティちゃんの子に

次にまたMain Cameraを今度はSkyrimControllerにドラッグ&ドロップします。
まずunitychanをクリックし、InspectorのCameraの欄に向けてドラッグ&ドロップします。

2.AudioClip

こちらはまずInspectorのSkyrimControllerのAudioClipの文字の頭についている三角をクリックします。
するとSizeという欄に数字を入れられるので「2」と入力してインターを押してください。

SkyrimController/AudioClipの配列

そうすると2つそこに音のファイルを入れられるようになります。
次は効果音を調達しましょう。

音人 戦闘系音

こちらのサイトは個人の利用なら連絡なしで利用して良いそうなのでありがたく使わせていただきましょう。
好きな音を選んで良いのですが私はこちらにしました。

手足・殴る、蹴る12
回転03

前者は攻撃用で後者が旋風の疾走用です。
さて、SkyrimControllerに回転03だけをドラッグ&ドロップしてください。
手足・殴る、蹴る12は別に使います。

3.LegLeft、LegRight

次は足音を出すようにするのですがそれには無料アセットの「Free Footsteps System」を使うので以下のバナーからダウンロードしてください。

これはTerrain上で地面のテクスチャによって足音を替えてくれるという優れものです。

・footstep_triggerとfootsteps_databaseを設置。
・unitychanにAudioSourceとCharacterFootstepsを設置。
・設置したCharacterFootstepsのAudio Sourceの欄にHierarchyのunitychanをドラッグ&ドロップ。

このような流れになります。

Project > Assets > FREE Footsteps System > Resources

ここに入っているfootstep_triggerとfootsteps_databaseを使います。
まずfootstep_triggerですがこれはユニティちゃんの両方の足にひとつずつつける必要があります。

SkyrimController/ユニティちゃんの足の子にfootstep_trigger

このようにunitychanの中にあるCharacter1_LeftToeBaseとCharacter1_RightToeBaseに1つずつドラッグ&ドロップします。

SkyrimController/ユニティちゃんの足にfootstep_trigger

次に足から地面につくように位置を調整してください。

SkyrimController/Transformのマウス操作

このようにTransformのXやY、Zに矢印を置くとマウスでのドラッグで微調整できます。
しかし位置はXYZすべて0でも良いかもしれません。
調整は後からでもできます。

そしてfootstep_triggerをSkyrimControllerにドラッグ&ドロップします。
左右を設定していますが逆に入れても問題はありません。

次にHierarchyにfootsteps_databaseを置いてください。

その次に、

Assets > FREE Footsteps System > scripts

にあるCharacterFootstepsをunitychanにドラッグ&ドロップ

そしてまた次にunitychanのInspectorから

AddComponent > Audio Source

それから最後に Character FootstepsのAudio Sourceの欄にunitychanをドラッグ&ドロップして終わりです。

unitychan > Inspector > Character Footsteps > Audio Source

SkyrimController/ユニティちゃんのCharacter Footsteps

お疲れ様でした。

しかし、Terrainではテクスチャが張られていないと音が出ないようなのでそれもつけてみましょう。

Terrain > Edit Textures > Add Texture

SkyrimController/Terrainにテクスチャ

4.AttackObj

最後はとりあえず空のオブジェクトを作りAttackObjの欄に入れておくだけで良いです。

Hierarchy > Create > Create Empty

名前は同じ「AttackObj」にします。
HierarchyのGameObjectを右クリック、Renameで変えられます。

SkyrimController/Inspector/満杯

さて最低限の準備は完了したので動かしてみてください。
ちゃんと音は出ているでしょうか?
攻撃の音は敵に攻撃が当たった時に出るのでまだ聞けません。

W 前進
S 後進
D 右移動
A 左移動
スペース ジャンプ
Z 旋風の疾走
マウス左クリック 攻撃

■攻撃された敵が吹っ飛ぶようにする

SkyrimController/AttackObj/CapsuleCollider/IsTigger

まずはAttackObjにCapsuleColliderをAddComponentからセットし、IsTriggerにチェックを入れます。

SkyrimController/AttackObjをユニティちゃんの足に

次はまた以前のfootstep_triggerと同じように足につけるのですが、今回は右足だけです。
大きさは変えなくても問題ありません。
後から好きに変えてください。
位置はCharacter1_RightToeBaseの子にしたらTransformのXYZがすべて0で大丈夫です。

次はスクリプト「AttackRange」を作ります。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AttackRange : MonoBehaviour {
//敵を飛ばす方向を決める位置
Vector3 direction;
//効果音入れる、使う
public AudioClip audioClip1;
AudioSource audioSource;
void Start()
{
//ComponentのAudioSourceを取得しておく
audioSource = gameObject.GetComponent<AudioSource>();
}
//Colliderの範囲に入ったものに作用する
void OnTriggerEnter(Collider other)
{
//Enemyタグが入ったものに作用する
if (other.tag == "Enemy")
{
//相手の位置から自分(攻撃範囲)の位置を引いて飛ばす方向を決める
direction = other.transform.position - transform.position;
//相手のRigidbodyを取得する
Rigidbody othRb = other.GetComponent<Rigidbody>();
//相手のRigidbodyに力を加える
othRb.AddForce(direction * 30, ForceMode.Impulse);
//効果音を出す
audioSource.clip = audioClip1;
audioSource.Play();
}
}
}
view raw 07b.cs hosted with ❤ by GitHub

できたらAttackObjにドラッグ&ドロップ

SkyrimController/AttackObj/効果音入れる

そして前にダウンロードしておいた音声ファイルの手足・殴る、蹴る12を空欄に入れ、そしてAddComponentでAudioSourceを入れます。
次にAudioSourceのPlayOnAwakeのチェックを外してください。
入れたままにすると必要ないところでも鳴ってしまいます。

AddComponentで入れるものまとめ。
・CapsuleCollider、IsTriggerにチェック
・Rigidbody
・AudioSource、PlayOnAwakeのチェックを外す

次は蹴り飛ばす敵を用意します。
敵と言ってもただのCubeですが。

Hierarchy > Create > 3D Object > Cube

まずTagを前に作っておいたEnemyにします。
そしてAddComponentでRigidbodyを加えて出来上がり!
上手く音が出て敵は吹っ飛んでくれたでしょうか?

SkyrimController/ユニティちゃんがオブジェクトを蹴り飛ばす

これで今回は終わりです。
お疲れさまでした。

■関連記事

【UnityC#講座】ユニティちゃんでもっとAnimator Controllerを上手く使いたい

【UnityC#講座】ユニティちゃんでもっとスカイリム風に操作したい 前編【カメラ】

【UnityC#講座】ユニティちゃんでもっとスカイリム風に操作したい 後編【Animator Controller】

【UnityC#講座】AnimatorControllerを使いまわす【AnimatorOverrideController】

【UnityC#講座】AnimatorControllerの使い方

【UnityC#講座】ユニティちゃんをマウスカーソルの方向に移動させる

【UnityC#講座】上下キーで前進後退、左右キーで方向替える移動法【ユニティちゃん】

スポンサーリンク

目次に戻る