Unity2018.1.5f1
Windows10
□
以前ユニティちゃんを操作できるようにしました。
【UnityC#講座】3D人型モデルの動かし方をユニティちゃんで学ぶ【Animator】
今回はその時とは別の操作方法にします。
名作オープンワールドRPG「スカイリム」のようにマウスで方向を変えてそれを基準に前後左右、ジャンプ、そして攻撃と高速移動を設置します。
さあ、まずはプロジェクト「SkyrimController」を作ってください。
■ユニティちゃんをセットする
以前と重複になりますがまずはユニティちゃんをアセットストアからダウンロードします。
この作品はユニティちゃんライセンス条項の元に提供されています
ProjectからunitychanをHierarchyかSceneにドラッグ&ドロップしてください。
UnityChan > Models > unitychan
次にユニティちゃんが乗る地面ですが、以前はPlanですが今回はTerrainを使います。
Hierarchy > 3D Object > Terrain
ユニティちゃんがTerrainにちゃんと乗るようにしておいてください。
あとタグの設定もしておきましょう。
Inspector > Tag > Add Tag > Tags & Layer > Tags > +
+を押して出てきた欄にGroundを追加します。
ついでに後で使うEnemyも作っておきましょう。
最後にTerrainにGroundのTagを設定して出来上がりです。
次にユニティちゃんにCapsule ColliderとRigidbodyを追加します。
Hierarchyのunitychanにクリックし、そのInspectorからAdd Componentをクリック、Capsule ColliderとRigidbodyを検索してください。
Capsule Colliderはこのようにしましたが厳密にこの通りにする必要はありません。
RigidbodyはConstraintsのFreeze Rotationのチェックボックスをすべてチェックしてください。
これで不要な回転をしなくなります。
■Animatorの設定をする
これも以前したことで説明は重複になるのでざっと説明します。
詳しい説明が見たい人はこの記事を見てください。
【UnityC#講座】3D人型モデルの動かし方をユニティちゃんで学ぶ【Animator】
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
3.Idleを中心にそれぞれのステートマシンを矢印、Transitionでつなぐ。
各ステートマシンを右クリック、Make Transitionをクリックしてつなぎたいステートマシンをクリックします。
もし間違えてつないでしまった場合、TransitionのInspectorのTransitionsの「-」をクリックすると消すことができます。
4.Parametersを設定する。
Animatorウィンドウの左上にParametersがあるのでクリック、次にBoolをクリックし名前を入れます。
名前は分かりやすくステートマシンと同じで良いでしょう。
Idle以外の7つのParametersを全てBoolで設定してください。
5.TransitionにParametersを設定していく。
矢印をクリックし、InspectorのConditionsの+マークをクリックしてください。
そこで先ほど設定したParametersを設定していきます。
Idleつながっている先のステートマシンと同じ名前のParametersを設定します。
そしてTrueとFalseは以下のようにしてください。
Idle → 各ステートマシン True
各ステートマシン → Idle False
あとInspectorのHas Exit Timeのチェックボックスを全て外します。
さて、できた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(); | |
} | |
} | |
} |
スポンサーリンク
W 前進
S 後進
D 右移動
A 左移動
スペース ジャンプ
Z 旋風の疾走
マウス左クリック 攻撃
できたらそれをHierarchyのunitychanにドラッグ&ドロップしてください。
ここで一旦動かしてみたいところでしょうが、まだ準備ができていません。
次はInspectorからSkyrimControllerの設定をします。
■カメラと効果音をセットする
これはHierarchyのunitychanのInspectorのSkyrimControllerです。
Camera、AudioClip、LegLeft、LegRight、AttackObjを上から順に設定していきます。
1.Camera
まずはHierarchyの最初からあるMain Cameraをunitychanにドラッグ&ドロップしてください。
画像のようになればOKです。
次にまたMain Cameraを今度はSkyrimControllerにドラッグ&ドロップします。
まずunitychanをクリックし、InspectorのCameraの欄に向けてドラッグ&ドロップします。
2.AudioClip
こちらはまずInspectorのSkyrimControllerのAudioClipの文字の頭についている三角をクリックします。
するとSizeという欄に数字を入れられるので「2」と入力してインターを押してください。
そうすると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ですがこれはユニティちゃんの両方の足にひとつずつつける必要があります。
このようにunitychanの中にあるCharacter1_LeftToeBaseとCharacter1_RightToeBaseに1つずつドラッグ&ドロップします。
次に足から地面につくように位置を調整してください。
このように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
お疲れ様でした。
しかし、Terrainではテクスチャが張られていないと音が出ないようなのでそれもつけてみましょう。
Terrain > Edit Textures > Add Texture
4.AttackObj
最後はとりあえず空のオブジェクトを作りAttackObjの欄に入れておくだけで良いです。
Hierarchy > Create > Create Empty
名前は同じ「AttackObj」にします。
HierarchyのGameObjectを右クリック、Renameで変えられます。
さて最低限の準備は完了したので動かしてみてください。
ちゃんと音は出ているでしょうか?
攻撃の音は敵に攻撃が当たった時に出るのでまだ聞けません。
W 前進
S 後進
D 右移動
A 左移動
スペース ジャンプ
Z 旋風の疾走
マウス左クリック 攻撃
■攻撃された敵が吹っ飛ぶようにする
まずはAttackObjにCapsuleColliderをAddComponentからセットし、IsTriggerにチェックを入れます。
次はまた以前の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(); | |
} | |
} | |
} |
できたらAttackObjにドラッグ&ドロップ。
そして前にダウンロードしておいた音声ファイルの手足・殴る、蹴る12を空欄に入れ、そしてAddComponentでAudioSourceを入れます。
次にAudioSourceのPlayOnAwakeのチェックを外してください。
入れたままにすると必要ないところでも鳴ってしまいます。
AddComponentで入れるものまとめ。
・CapsuleCollider、IsTriggerにチェック
・Rigidbody
・AudioSource、PlayOnAwakeのチェックを外す
次は蹴り飛ばす敵を用意します。
敵と言ってもただのCubeですが。
Hierarchy > Create > 3D Object > Cube
まずTagを前に作っておいたEnemyにします。
そしてAddComponentでRigidbodyを加えて出来上がり!
上手く音が出て敵は吹っ飛んでくれたでしょうか?
これで今回は終わりです。
お疲れさまでした。
■関連記事
【UnityC#講座】ユニティちゃんでもっとAnimator Controllerを上手く使いたい
【UnityC#講座】ユニティちゃんでもっとスカイリム風に操作したい 前編【カメラ】
【UnityC#講座】ユニティちゃんでもっとスカイリム風に操作したい 後編【Animator Controller】
【UnityC#講座】AnimatorControllerを使いまわす【AnimatorOverrideController】
【UnityC#講座】AnimatorControllerの使い方
【UnityC#講座】ユニティちゃんをマウスカーソルの方向に移動させる
【UnityC#講座】上下キーで前進後退、左右キーで方向替える移動法【ユニティちゃん】
スポンサーリンク