本日はUnityアニメーションの講座の続きです。
作成したプロジェクトに手を加えて、新しいアニメーションの追加にトライします。
bluebirdofoz.hatenablog.com
前回作成したプロジェクトを開きます。
最初に、追加するアニメーションの新しい State を作成します。
まずは以下の手順で「UnityChanLocomotions」を開いてください。
1.unitychan オブジェクトを選択する。
2.Inpector タブにある Animator コンポーネント内の「UnityChanLocomotions」をダブルクリックする。
3.画面中央に「UnityChanLocomotions」のフロー図が表示される。
フロー図上で右クリックをして、Create State -> Empty を選択します。
「New State」という新しい State が作成されます。
今回はユニティちゃんの勝利ポーズのアニメーションを作成します。
以下の通り、State の名前とモーションを設定します。
1.Inspector 上部の名前「Winner」を変更する。
2.Motion : None(Motion) の右端にある ◎ ボタンをクリックする。
3.表示されたダイアログから「WIN00」を選択する。
Motion に WIN00 が設定されればOKです。前回学んだモーションの確認方法で WIN00 のモーションを確認できます。
次に遷移条件の設定のため、「Winner」State へのトリガーとなる新しい Parameters 設定を追加します。
以下の手順で「WinBool」Parameter を作成してください。
1.Parameters タブの右上にある + ボタンをクリックする。
2.表示されたメニューから Bool を選択する。
3.作成された Parameter に「WinBool」という名前を設定する。
さて、追加した「WinBool」Parameter を元に Transition を作成し、「Idle」State から「Winner」State へ遷移を設定します。
「Idle」State 上で右クリックをして、Make Transition を選択します。
矢印が表示されるので、そのまま「Winner」State をクリックします。
すると「Idle」State から「Winner」State へ矢印線が結ばれます。
Transition の設定を行います。作成した矢印線をクリックして Inspector タブを開いてください。
まずは以下の手順で Conditions の設定を行い、遷移条件を設定しましょう。
1.Conditions の右下にある + ボタンをクリックすると、条件式が追加される。
2.追加された条件を「WinBool : true」の条件で設定する。
次に遷移のアニメーションの繋がりを設定します。
そのままの状態で「再生」ボタンを押してアニメーションを確認してみてください。
勝利ポーズにすぐに遷移せず、立ちポーズの状態が長く続くアニメーションになっていると思います。
トリガーが発生すれば、すぐにポーズを遷移したいので、アニメーションの繋がりを調整します。
Settings ウィンドウの Winner ブロックを前方に移動させてください。
合わせて、Idle ブロックから Winner ブロックへの遷移タイミングを示す青枠についても前方に移動させます。
この状態で再び「再生」ボタンを押してアニメーションを確認してみてください。
先ほどと比べ、すぐに勝利ポーズへの遷移が始まることが確認できます。
更にもう一つ、Has Exit Time のチェックを外してください。
Has Exit Time が無効の場合、「Idle」State の立ちモーションのアクションを即座にキャンセルして次のモーションに遷移します。
このチェックを外していないと例え、すぐに勝利ポーズへ遷移が始まるアニメーションを設定していても、その前の立ちモーションの完了を待ってしまうため、即座にモーションが遷移しません。
「Idle」State から「Winner」State への遷移が設定できました。しかし、このままだと一度「Winner」State に入ってしまうと「Idle」State に戻ってきません。
「Winner」State から「Idle」State への遷移も設定しておきましょう。
Transition を「Winner」State から「Idle」State に延ばします。
「Winner」State から「Idle」State へ Transition の設定項目ですが、こちらは変更は不要です。
Conditions の設定がない場合、無条件で遷移が発生します。
このため、「Idle」State から「Winner」State への遷移が発生すると、その後、必ず「Winner」State から「Idle」State に戻る形となります。
そしてこのとき、「Winner」State から「Idle」State への遷移では Has Exit Time が無効されていないため、「Winner」State のモーションが一通り再生された後、「Idle」State の立ちポーズに戻るという流れになる訳です。
フローの設定はこれで完了です。
後はスクリプトにて、トリガーの発生を実装しましょう。
以下の手順を実施し、スクリプトファイルを開いてください。
1.unitychan オブジェクトを選択する。
2.Inpector タブにある UnityChanControlScriptWithRgidBody(Script) コンポーネント内にある
Script「UnityChanControlScriptWithRgidBody」をダブルクリックする。
UnityChanControlScriptWithRgidBody.cs が個別のテキストエディタで開かれます。
Winアニメーション用に修正した UnityChanControlScriptWithRgidBody.cs を以下に添付します。内容を上書きしてください。
・UnityChanControlScriptWithRgidBody.cs
using UnityEngine;
using System.Collections;
namespace UnityChan
{
[RequireComponent(typeof(Animator))]
[RequireComponent(typeof(CapsuleCollider))]
[RequireComponent(typeof(Rigidbody))]
public class UnityChanControlScriptWithRgidBody : MonoBehaviour
{
public float animSpeed = 1.5f;
public float lookSmoother = 3.0f;
public bool useCurves = true;
public float useCurvesHeight = 0.5f;
public float forwardSpeed = 7.0f;
public float backwardSpeed = 2.0f;
public float rotateSpeed = 2.0f;
public float jumpPower = 3.0f;
private CapsuleCollider col;
private Rigidbody rb;
private Vector3 velocity;
private float orgColHight;
private Vector3 orgVectColCenter;
private Animator anim;
private AnimatorStateInfo currentBaseState;
private GameObject cameraObject;
static int idleState = Animator.StringToHash ("Base Layer.Idle");
static int locoState = Animator.StringToHash ("Base Layer.Locomotion");
static int jumpState = Animator.StringToHash ("Base Layer.Jump");
static int restState = Animator.StringToHash ("Base Layer.Rest");
static int winState = Animator.StringToHash("Base Layer.Winner");
void Start ()
{
anim = GetComponent<Animator> ();
col = GetComponent<CapsuleCollider> ();
rb = GetComponent<Rigidbody> ();
cameraObject = GameObject.FindWithTag ("MainCamera");
orgColHight = col.height;
orgVectColCenter = col.center;
}
void FixedUpdate ()
{
float h = Input.GetAxis ("Horizontal");
float v = Input.GetAxis ("Vertical");
anim.SetFloat ("Speed", v);
anim.SetFloat ("Direction", h);
anim.speed = animSpeed;
currentBaseState = anim.GetCurrentAnimatorStateInfo (0);
rb.useGravity = true;
velocity = new Vector3 (0, 0, v);
velocity = transform.TransformDirection (velocity);
if (v > 0.1) {
velocity *= forwardSpeed;
} else if (v < -0.1) {
velocity *= backwardSpeed;
}
if (Input.GetButtonDown ("Jump")) {
if (currentBaseState.nameHash == locoState) {
if (!anim.IsInTransition (0)) {
rb.AddForce (Vector3.up * jumpPower, ForceMode.VelocityChange);
anim.SetBool ("Jump", true);
}
}
}
transform.localPosition += velocity * Time.fixedDeltaTime;
transform.Rotate (0, h * rotateSpeed, 0);
if (currentBaseState.nameHash == locoState) {
if (useCurves) {
resetCollider ();
}
}
else if (currentBaseState.nameHash == jumpState) {
cameraObject.SendMessage ("setCameraPositionJumpView");
if (!anim.IsInTransition (0)) {
if (useCurves) {
float jumpHeight = anim.GetFloat ("JumpHeight");
float gravityControl = anim.GetFloat ("GravityControl");
if (gravityControl > 0)
rb.useGravity = false;
Ray ray = new Ray (transform.position + Vector3.up, -Vector3.up);
RaycastHit hitInfo = new RaycastHit ();
if (Physics.Raycast (ray, out hitInfo)) {
if (hitInfo.distance > useCurvesHeight) {
col.height = orgColHight - jumpHeight;
float adjCenterY = orgVectColCenter.y + jumpHeight;
col.center = new Vector3 (0, adjCenterY, 0);
} else {
resetCollider ();
}
}
}
anim.SetBool ("Jump", false);
}
}
else if (currentBaseState.nameHash == idleState) {
if (useCurves) {
resetCollider ();
}
if (Input.GetButtonDown ("Jump")) {
anim.SetBool ("Rest", true);
}
if (Input.GetKey(KeyCode.Return))
{
anim.SetBool("WinBool", true);
}
}
else if (currentBaseState.nameHash == restState) {
if (!anim.IsInTransition (0)) {
anim.SetBool ("Rest", false);
}
}
else if (currentBaseState.nameHash == winState) {
if (!anim.IsInTransition(0))
{
anim.SetBool("WinBool", false);
}
}
}
void OnGUI ()
{
GUI.Box (new Rect (Screen.width - 260, 10, 250, 150), "Interaction");
GUI.Label (new Rect (Screen.width - 245, 30, 250, 30), "Up/Down Arrow : Go Forwald/Go Back");
GUI.Label (new Rect (Screen.width - 245, 50, 250, 30), "Left/Right Arrow : Turn Left/Turn Right");
GUI.Label (new Rect (Screen.width - 245, 70, 250, 30), "Hit Space key while Running : Jump");
GUI.Label (new Rect (Screen.width - 245, 90, 250, 30), "Hit Spase key while Stopping : Rest");
GUI.Label (new Rect (Screen.width - 245, 110, 250, 30), "Left Control : Front Camera");
GUI.Label (new Rect (Screen.width - 245, 130, 250, 30), "Alt : LookAt Camera");
}
void resetCollider ()
{
col.height = orgColHight;
col.center = orgVectColCenter;
}
}
}
シーンの「再生」ボタンを押してシーンを開始します。
エンターキーを押してみてください。ユニティちゃんが勝利ポーズを取るアニメーションが始まれば成功です。
以上でアニメーションの追加が出来ました。Unityアニメーション講座はここで一旦区切りとします。
ここまでお付き合い頂きありがとうございました。