12.Update系の操作

1203.Action系コンポーネント

 このサンプルはFullSample203というディレクトリに含まれます。
 BaseCrossDx11.slnというソリューションを開くとDx11版が起動します。
 BaseCrossDx12.slnというソリューションを開くとDx12版が起動します。

 実行結果は以下のような画面が出ます。

 

図1203a

 

 オブジェクトの位置や回転、スケーリングを動的に変更する手段として、何秒間でどこまで移動といった指定ができると便利です。
 Action系コンポーネントはこのような動きを指定できます。

Actionコンポーネント

 このサンプルの中央部には、3つの球体が回転、そしてジャンプしながら区画に沿って移動します。
 このような動きを実装するには、Character.h/cppにある、ActionObjectクラスのような記述をします。
 以下は ActionObject::OnCreate()関数です。
//初期化
void ActionObject::OnCreate() {
    auto Ptr = GetComponent<Transform>();
    Ptr->SetPosition(m_StartPos);
    Ptr->SetScale(0.25f, 0.25f, 0.25f); //直径25センチの球体
    Ptr->SetRotation(0.0f, 0.0f, 0.0f);
    //CollisionSphere衝突判定を付ける
    auto PtrColl = AddComponent<CollisionSphere>();
    //Fixedを設定する
    PtrColl->SetFixed(true);

    //アクションの登録
    auto PtrAction = AddComponent<Action>();
    PtrAction->AddRotateBy(1.0f, Vec3(0, XM_PI, 0));
    PtrAction->AddRotateInterval(1.0f);
    PtrAction->AddMoveBy(1.0f, Vec3(2.0f, 0, 0));
    PtrAction->AddMoveBy(0.5f, Vec3(0, 1.0f, -1.0f), Lerp::Linear, Lerp::EaseOut, Lerp::Linear);
    PtrAction->AddMoveBy(0.5f, Vec3(0, -1.0f, -1.0f), Lerp::Linear, Lerp::Easein, Lerp::Linear);
    PtrAction->AddMoveBy(2.0f, Vec3(-4.0f, 0, 0));
    PtrAction->AddMoveBy(1.0f, Vec3(0, 0, 2.0f));
    PtrAction->AddMoveBy(1.0f, Vec3(2.0f, 0, 0));

    //ループする
    PtrAction->SetLooped(true);
    //アクション開始
    PtrAction->Run();

    //影の作成
    auto ShadowPtr = AddComponent<Shadowmap>();
    //影の形状
    ShadowPtr->SetMeshResource(L"DEFAULT_SPHERE");

    //描画コンポーネント
    auto PtrDraw = AddComponent<PNTStaticDraw>();
    //メッシュの登録
    PtrDraw->SetMeshResource(L"DEFAULT_SPHERE");
    //テクスチャの登録
    PtrDraw->SetTextureResource(L"WALL_TX");

}
 赤くなっているところがActionコンポーネントの実装です。
 Actionコンポーネントスケーリング、回転、移動の3つのラインがありそれぞれ独立して動き、組み合わさった状態になります。
 例えば1秒間でXM_PIだけY軸回転2秒間で2.0移動と指定した場合、スタートから0.5秒後XM_PI/2ぶん回転して、0.5だけ移動の状態になります。
 スケーリング、回転、移動の3つのラインに指定できるアクションはScaleBy、RotateBy、MoveBy○○Byであらわされる動作とScaleTo、RotateTo、MoveTo○○Toであらわされる動きです。
 ○○By現在の状態からの変化を表します。例えば、現在Vec3(1.0f,1.0f,1.0f)にいるオブジェクトをAddMoveBy(1.0f, Vec3(2.0f, 0, 0));した場合、1秒間でVec3(2.0f, 0, 0)だけ相対的に移動の意味になり移動後の位置はVec3(3.0f,1.0f,1.0f)になります。
 ○○Toは、AddMoveTo(1.0f, Vec3(2.0f, 0, 0));した場合、現在位置がどこにあっても、1秒後にはVec3(2.0f, 0, 0)に移動します。1秒間でVec3(2.0f, 0, 0)まで移動となり絶対位置の表現となります。
 Scale、Rotateも同様でScaleBy、RotateByの場合は相対的な変化でありScaleTo、RotateToは絶対的な変化になります。
 サンプルのように
    //ループする
    PtrAction->SetLooped(true);
 にすると、繰り返し変化を続けます。
    //ループしない
    PtrAction->SetLooped(false);
 にすると、登録された一連の動作が終了した時点で変化を終了します(デフォルトはループしない、です)。
 その場合Scale、Rotate、Moveの3つのラインがすべて終了したら、IsArrived()関数により、到着したかどうかを検証できます。
 また、それぞれのラインには○○Intervalという動作があります。これは何もしないという動作で、指定した時間は何もしません。
    PtrAction->AddRotateInterval(1.0f);
 で、1秒間回転を止めることができます。

その他のActionコンポーネント

 Action系コンポーネントには、MoveByRotateByを単独で実装できるコンポーネントがあります。
ScaleToコンポーネント    目的の拡大率に拡大縮小
ScaleByコンポーネント    目的の相対スケールにに拡大縮小
RotateToコンポーネント   目的の角度に回転
RotateByコンポーネント   目的の相対角度に回転
MoveToコンポーネント     目的の位置に移動
MoveByコンポーネント     目的の相対位置に移動
 また、このオブジェクトはCollisionSphere衝突判定を実装しています。
    //CollisionSphere衝突判定を付ける
    auto PtrColl = AddComponent<CollisionSphere>();
    //Fixedを設定する
    PtrColl->SetFixed(true);
 このようにSetFixed(true)にしていますが、こうしないと、他のオブジェクトがぶつかったときに、あらかじめ計画を立てたアクションが違ってしまいます。
 もちろん、何かが当たったらアクションを止めるのように記述することが可能です。
 その場合はSetFixed(true)は設定せずにOnCollisionEnter()などで処理を記述するとよいでしょう。アクションは途中で止めるStop()関数があります。