この記事はUnityとVuforiaを用いてARアプリを開発する初心者向け入門講座の第4回目です。
前回はスマホUI画面を作り実際にandroidやiphoneからARモデルのアニメーションを動かすことができるようになりました。
前回の記事:
今回の講座では前回実装しなかった前に歩く処理と後ろに下がる処理を実装します。
自然に歩かせるためにC#スクリプトをコーディングしてARアプリを完成させます。
ARモデルを動かすC#スクリプトをコーディングしよう
詳細な条件に応じてキャラクターを動かすにはC#スクリプトが必要です。
プロジェクトフォルダ「Scripts」内にC#スクリプトを作成します。右クリック → Create→ C# スクリプト
CharacterScriptという名前をつけます。自動的に「CharacterScript.cs」というC#スクリプトができあがります。
タイトルにはスペースを入れないように。もし名前のスペルを間違えたらスクリプトを削除して新規に作成するようにしましょう。
作成したスクリプトをダブルクリックするとVisual Studioやお好みのエディタで開くことができます。
Visual Studioをインストールしているにもかかわらず、スクリプトがVisual Studioで開かない場合は、環境設定の「Edit→ Preferences → External Tools → External Script Editor」で、Visual Studioが設定されているかを確認してください。
スクリプトを開くと以下のような内容になっています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class CharacterScript : MonoBehaviour { // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { } } |
C#スクリプトで歩行アニメーションを動かす
Start() と Update() メソッドを削除します。
次に、クラスの括弧の中に前に歩く&後ろに下がる動作に対応するメソッドを2つ記述します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class CharacterScript : MonoBehaviour { public Animator animator; public void Walk() { } public void Back() { } } |
*** スクリプトに変更を加えた後、スクリプトを保存することを忘れないでください。Ctrl +Sで保存です。
まずはじめにいくつかの変数を宣言します。
Transition、State、Parameterをすべて含むAnimatorを作成する必要があります。
このスクリプトをキャラクターオブジェクトにアタッチします。スクリプトを保存して、Unityに戻ります。
HierarchyからCharacterオブジェクトを選択するか、PrefabsフォルダからCharacterオブジェクトを選択します。
Scriptsフォルダを選択し、CharacterScriptをドラッグして、最後にCharacterのインスペクタにドロップします。
キャラクターオブジェクトに必要な「Animator」コンポーネントがあるので、同じインスペクタ(「キャラクター」のインスペクタ)から、スクリプトコンポーネントの「Animator」フィールドにドラッグします。
*シーンでこれらの変更を行った場合、キャラクタープレハブを上書きしてください。
これからアニメーションを動かすための2つのメソッドを作っていきましょう。
それらのメソッドが呼ばれたら、アニメーションのfloatパラメータを有効にしたいです。
Animatorでは3つのパラメータとアニメーションステートを作成しましたが、ボタンについては4つ作成しました。
a_Walk パラメータと Walk ステートを Walk と Back の両方の動作に使用して再利用するから数が一致していません。
私たちの状況ではシームレスですが、モデルによっては後方へのアニメーションを提供するものもあります。
そのため、メソッド本体を2回記述する必要はありません。唯一の違いは方向だけです。
IEnumeratorのコルーチンが必要なので、コルーチンを作成し、2つのメソッドでそれを呼び出すようにしていきます。コルーチンに関してはC#の文法入門講座でも解説しています。
StartやUpdateメソッドは消去して以下のようにスクリプトを書きなおします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class CharacterScript : MonoBehaviour { public Animator animator; public void Walk() { StartCoroutine(Walking()); } public void Back() { StartCoroutine(Walking()); } IEnumerator Walking() { yield return null; } } |
では、コルーチンに何をさせたいかを考えていきます。
ボタンを押すとキャラクターはWalkアニメーションを開始し動き出すようにしたいですね。
そして、移動とアニメーションの両方を停止させます。
今回コルーチンが必要な理由は、何かをトリガーにして、順序よく物事が起こるようにしたいからです。
アニメーションのパラメータにアクセスするには、UnityEngineライブラリの組み込みメソッドを使用します。
必要なのは、Floatパラメータの名前と値だけです。今回だと「c」ですね。
では、コルーチン内で歩行アニメーションを有効、無効にしてみましょう。
1 2 3 4 5 6 |
IEnumerator Walking() { animator.SetFloat("a_Walk", 1f); animator.SetFloat("a_Walk", 0f); yield return null; } |
パラメータ「a_Walk」が0より大きい場合、Walk状態に遷移するように設定していましたね。
よって、上記スクリプトで「a_Walk」を1にする処理と0にする処理の間に実際の移動を行わせたいです。
キャラクターを今いる位置から少し移動させてみましょう。そこで、オブジェクトのTransformの localPosition 変数が必要になります。もし「position」変数だけを使用した場合、ワールド座標の位置を意味することになります。
このスクリプトはキャラクターに付属しているので、変数の参照などの処理を別に書く必要はありません。
キャラクターはZ軸方向にのみ動くようにしたいので、Vector3コンポーネントで3番目の属性だけを変更します。Vector3 (0f, 0f, 1f)とします。
モデルは 180 度回転しているので、「前」の方向は反転していることに注意してください。
そこで Vector3 (0f, 0f, -1f) は実際には1m前方で、Vector3 (0f, 0f, 1f) は1m後方になります。
これを実際にコーディングしたものが以下の追加行です。
1 2 3 4 5 6 7 |
IEnumerator Walking() { animator.SetFloat("a_Walk", 1f); transform.localPosition = Vector3.Lerp(transform.localPosition, new Vector3(0f, 0f, -1f), 0.001f); animator.SetFloat("a_Walk", 0f); yield return null; } |
テストプレイの前に、WalkButtonとBackButtonのOnClick()に、CharacterScriptのWalk()とBack()メソッドを設定するのを忘れないようにしてください
この方法を試してみると、キャラクタはz軸方向に1mだけテレポートしていることがわかります。
そうではなくキャラクターがこの距離を連続的に歩くようにアニメーションさせたいですね。
そうした連続的な変化はVector3のLerp()メソッドで作ることができます。
スクリプトの移動に関する行を次のように変更します。
transform.localPosition = Vector3.Lerp(transform.localPosition, new Vector3(0f, 0f, -1f), 0.001f);
このメソッドの第一引数は開始位置、第二引数は最終位置、第三引数は補間値 – – 仮に速度とする – – となります。
実際のスクリプトは以下の通り。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class CharacterScript: MonoBehaviour { public Animator animator; public void Walk() { StartCoroutine(Walking()); } public void Back() { StartCoroutine(Walking()); } IEnumerator Walking() { animator.SetFloat("a_Walk", 1f); transform.localPosition = Vector3.Lerp(transform.localPosition, new Vector3(0f, 0f, -1f), 0.001f); animator.SetFloat("a_Walk", 0f); yield return null; |
今はまだ一瞬歩いて移動するだけなのでこの処理を繰り返したいです。
ゴールとステップを与えるだけで、この手順をある特定の時間の間繰り返してくれたら連続的に歩いてくれますね。
そこで、コルーチンの先頭で変数を導入します。
float time = 0fです。
この値を例えば1秒間かけて歩き続けるといった処理を作ることが可能になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class CharacterScript : MonoBehaviour { public Animator animator; public void Walk() { StartCoroutine(Walking()); } public void Back() { StartCoroutine(Walking()); } IEnumerator Walking() { float time = 0f; animator.SetFloat("a_Walk", 1f); while (time < 1f) { transform.localPosition = Vector3.Lerp(transform.localPosition, new Vector3(0f, 0f, -1f), 0.001f); time += Time.deltaTime; yield return null; } animator.SetFloat("a_Walk", 0f); } } |
ここでは、コルーチンで時間変数を設定し、Walk アニメーションを有効にし、キャラクターをしばらく動かし、すべてを表示し終わったら(yield return null;) アニメーションを無効にしています。
うまく動作しますが、1つのボタンに対してのみ動作します。また綺麗なコーディングとは言えません。
Unity C#スクリプトのリファクタリングに挑戦しよう!
綺麗なコーディングで一度書いたコードを書き直して汎用性や保守性を高めることを「リファクタリング」といいます。今回は最後に少しだけリファクタリングに挑戦してみましょう。
変化しない変数やエディターで変更できるようにしたい変数をすべて宣言してみましょう。
スクリプトの一番上、Animatorの宣言の下に、次のように書きます。
1 2 3 4 5 6 |
public float speed; public float duration; private string walkAnim = "a_Walk"; private Vector3 forwards = new Vector3(0f, 0f, -1f); private Vector3 backwards = new Vector3(0f, 0f, 1f); public float speed = 0.001f; public float duration = 1f; |
最初の2行のpublic変数「Speed」,「Duration」は歩行速度と一度ボタンを押した時に移動する時間を意味しています。エディタから設定することもできますし、このスクリプトのように最初から値を持たせて宣言することもできます。
続いて宣言している文字列変数「WalkAnim」はアニメーションのパラメータ名です。
「forward」と「backward」の変数は、それぞれ2つの異なるボタン/メソッドからコルーチンを呼び出す際に使用されます。
コルーチン内の数値やパラメータを新しい変数に置き換えます。
これらの新しい変数は、コルーチンの呼び出しやメソッドに渡されます。
コルーチンの宣言時に引数として与えて参照できるようにします。
1 2 3 4 5 6 7 8 9 10 11 12 |
IEnumerator Walking(Vector3 direction, float duration, float speed) { float time = 0f; animator.SetFloat(walkAnim, 1f); while (time < duration) { transform.localPosition = Vector3.Lerp(transform.localPosition, direction, speed); time += Time.deltaTime; yield return null; } animator.SetFloat(walkAnim, 0f); } |
次に、メソッド内のコルーチンの呼び出し側を変更して変数を渡すようにします。
1 2 3 4 5 6 7 8 9 |
public void Walk() { StartCoroutine(Walking(forwards, duration, speed)); } public void Back() { StartCoroutine(Walking(backwards, duration, speed)); } |
ここまでできたらスクリプトを保存してエディタに戻ります。
パブリック変数の値を別に設定したい場合は、キャラクタープレハブのインスペクタから宣言してください。
アプリをビルドする前にPlayモードで値を試して最もスムーズな値を使用することができます。
変数でパラメータを置き換えたり関数を設定したことでいろんな条件でテストプレイしたり改造しやすくなりましたね。
ARアプリの歩行処理を実現するスクリプト全文掲載
全スクリプトを以下に掲載します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class CharacterScript : MonoBehaviour { public float speed = 0.001f; public float duration = 1f; private string walkAnim = "a_Walk"; private Vector3 forwards = new Vector3(0f, 0f, -1f); private Vector3 backwards = new Vector3(0f, 0f, 1f); public Animator animator; public void Walk() { StartCoroutine(Walking(forwards, duration, speed)); } public void Back() { StartCoroutine(Walking(backwards, duration, speed)); } IEnumerator Walking(Vector3 direction, float duration, float speed) { float time = 0f; animator.SetFloat(walkAnim, 1f); while (time < duration) { transform.localPosition = Vector3.Lerp(transform.localPosition, direction, speed); time += Time.deltaTime; yield return null; } animator.SetFloat(walkAnim, 0f); } } |
ここまでのまとめと次回
今回はC#スクリプトを作成してARモデルを前に歩かせたり後ろに下がらせることができるようになりました。
コルーチンを利用してるので少しとっつきにくかったかもしれないですが、今後UnityやC#で本格的なゲーム開発を行う際によくお世話になる機能です。
今回はスクリプト全体が短いのでぜひここでコルーチンの基本をマスターしてしまいましょう。
次は完成したARアプリを実機で動かしてビルドして完成させます。すぐにできるのでこのまま読み進めていきましょう!初めてのARアプリをスマホで動かすと感動しますよ。
次回の記事:
コメント