AnyPortrait > マニュアル > スクリプトで初期化
Unityの基本的な関数である「Instantiate」を利用して、Prefabのオブジェクトをシーンに配置したり、シーンのオブジェクトを複製することができます。
「Instantiate」はUnityでゲームを作成するときに最も多く使用される関数のいずれかである。
AnyPortraitで製作したキャラクターをInstantiate関数で複製するとき、たまに「初期化」のエラーを経る場合があります。
このページは、簡単なコード例を通し、初期化について説明します。
(初期化関数に関しては、「関連ページ」を参照してください。)
シーンに配置されたAnyPortraitキャラクターを複製してみましょう。
「Space Bar」を入力すると、キャラクターが複製されてわずかに右に配置され、「Move」のアニメーションが再生されるようにしましょう。
これでスクリプトで作成すると、次のようになります。
public class InitializeSample : MonoBehaviour
{
// 対象となるapPortrait
public apPortrait portrait;
void Start () { }
void Update ()
{
if ( Input.GetKeyDown(KeyCode.Space) )
{
// GameObjectをInstantiateを利用してコピーする
GameObject newGameObject = Instantiate<GameObject>(portrait.gameObject);
// 位置移動
newGameObject.transform.position = new Vector3(8, 0, 0);
// 複製されたGameObjectでapPortraitコンポーネント得る
apPortrait newPortrait = newGameObject.GetComponent<apPortrait>();
// Moveアニメーション
newPortrait.Play("Move");
}
}
}
このスクリプトをUnityシーンに配置して、ゲームを実行してみましょう。
ゲームを実行して、Space Barを押すとキャラクターが複製になりますが、エラーが発生します。
そして「Move」のアニメーションも再生されません。
このエラーは、Unityシーンに初めて配置されたキャラクターが 「初期化プロセス」を経ていない状態では、すぐに「Play」関数が呼び出されたためです。
AnyPortraitのシステムは、自動的にキャラクターが最初にロードされると、更新フレームに直接初期化を実行します。
しかしながら、「Instantiate」関数でロードされた直後にapPortraitの任意の関数を呼び出す場合は、まだ初期化がされていない状態なので、エラーが発生し、その関数は正常に動作しません。
この問題を解決する方法は、次のの二つがあります。
(1) スクリプトを利用して、初期化を直接実行します。
(2) ロードされたフレームでは、apPortraitの関数を呼び出すことなく、次のフレームまで待機します。
このページでは、(1)の方法について説明します。
コードを次のように変更してみましょう。
public class InitializeSample : MonoBehaviour
{
public apPortrait portrait;
void Start () { }
void Update ()
{
if ( Input.GetKeyDown(KeyCode.Space) )
{
GameObject newGameObject = Instantiate<GameObject>(portrait.gameObject);
newGameObject.transform.position = new Vector3(8, 0, 0);
apPortrait newPortrait = newGameObject.GetComponent<apPortrait>();
// すぐに初期化をするためにInitialize関数を呼び出して、Moveアニメーションを再生
newPortrait.Initialize();
newPortrait.Play("Move");
}
}
}
Play関数を実行する前に、apPortraitの「Initialize」関数を呼び出すように作成しました。
「Initialize」関数は、apPortraitを初期化して、更新をすることができるように準備させる役割をします。
現在のゲームを実行してみましょう。
スライムキャラクターが複製され、エラーなしで「Move」のアニメーションが再生されます。
初期化関数は、「Initialize」のほか、「AsyncInitialize」関数もあります。
この関数の特徴は、次のとおりです。
1. Initialize()
: 基本的な初期化関数です。
関数が呼び出される時点で、すべての初期化処理が行われます。
関数が呼び出されると、初期化が完了しますので、すぐにapPortraitを制御することができる利点があります。
キャラクターがアニメーションやモディファイヤをたくさん持っている場合、初期化コードは、非常に重く、一時的にFPS(Frames Per Second)が低下することがあります。
2. AsyncInitialize(OnAsyncLinkCompleted onAsyncLinkCompleted)
: 非同期の初期化関数です。
ゲーム中に初期化がされたときFPSが大きく落ちることが問題になる場合、この関数は、良い選択になるでしょう。
関数が呼び出されても、初期化は、若干のアップデートが行われた後に完了します。
この関数が呼び出された直後には、apPortraitをすぐに制御することができません。
初期化が完了したときの引数として入力されたイベントを呼び出します。
3. AsyncInitialize(int timePerYield, OnAsyncLinkCompleted onAsyncLinkCompleted)
: v1.1.7で追加された関数です。
ms単位の「timePerYield」因子が追加され、非同期処理単位の制限時間を指定することができます。
既存のAsyncInitialize関数に比べ処理時間はさらに増加されるが、ゲームのFPSを認識し、可能な限りのパフォーマンスに影響を与えないように改善しました。
同時に多くのキャラクターをロードするときにお勧めです。
非同期初期化関数を利用して、コードを作成してみましょう。
public class InitializeSample : MonoBehaviour
{
public apPortrait portrait;
void Start () { }
void Update ()
{
if ( Input.GetKeyDown(KeyCode.Space) )
{
GameObject newGameObject = Instantiate<GameObject>(portrait.gameObject);
newGameObject.transform.position = new Vector3(8, 0, 0);
apPortrait newPortrait = newGameObject.GetComponent<apPortrait>();
// 非同期初期化関数の呼び出し
newPortrait.AsyncInitialize(OnAsyncPortraitIntialized);
// またはそう作成してもされます。
// newPortrait.AsyncInitialize(100, OnAsyncPortraitIntialized);
}
}
// 初期化が完了すると、呼び出されるイベント
void OnAsyncPortraitIntialized(apPortrait portrait)
{
portrait.Play("Move");
}
}
非同期初期化処理は、すぐに完了していないので、初期化関数の呼び出しの直後にapPortraitを制御することができません。
イベントを利用することをお勧めします。