Playerの作成
スケルトンメッシュとアニメーション
スケルトンメッシュとアニメーションを設定してキャラクタを動かします。
こんな感じに仕上げていきます。
キャラクタはストアから"Paragon:Twinblast"ダウンロードしました。(無料です)
アニメーションBPの作成とメッシュの割り当て
アニメーションBPの作成です。
新規作成 -> アニメーション -> アニメーションBPを選びます。
ターゲットスケルトンはメッシュ(モデル)に対応しているスケルトンを選択します。
Twinblast
に対応しているスケルトンはTwinBlast_Skeleton
です。
BPA_chr00として作成しました。
中身は後ほど作成します。
ブループリントを修正してメッシュとアニメーションBPを割り当てます。
- BP_CppPlyBaseを選択
- Cubeを削除する
- Mesh(継承)を選ぶ
- 詳細のメッシュからプルダウンでメッシュ(TwinBlast_???)を選ぶ。
- トランスフォームを編集してカプセルコリジョンと位置合わせをする
- アニメーションのAnm Classからプルダウンで作成した
BPA_chr00_C
を選択します。
アニメション管理用のコンポーネントの作成
アニメーションBPを作成する前に アニメーション再生要求をしたり
イベント受け取るためのコンポーネント(AnmStateComponent.h
)を作成します。
CppPlayerController.h
にインクルードします。
CppPlayerController.h
#include "CoreMinimal.h"
#include "GameFramework/PlayerController.h"
#include "../../../uty/IvPadInput.h" //Key入力の取得
#include "../../../uty/AnmStateComponent.h" //アニメーション状態コンポーネント
#include "CppPlayerController.generated.h"
AnmStateComponent.h 全文
/**
* @file AnmStateComponent.h
* @brief アニメーション状態
* @author inuvatico
* @date 2020/11/08
* @version 1.0
* @copyright 2018 inuvatico
* Released under the MIT license.
* see https://opensource.org/licenses/MIT
* @par (new/Add/Change : 2020/10/17)
*
*/
#pragma once
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "Animation/AnimNotifies/AnimNotify.h"
#include "AnmStateComponent.generated.h"
//---------------------------------------------------------------------
// アニメーションインデックス
//---------------------------------------------------------------------
UENUM(BlueprintType)
enum class UAnmIndex : uint8 {
ANMID_NONE UMETA(DisplayName = "None"),
ANMID_IDLE_RUN UMETA(DisplayName = "IdleRun"),
ANMID_ATTACK1 UMETA(DisplayName = "Attack1"),
ANMID_ATTACK2 UMETA(DisplayName = "Attack2"),
ANMID_DAMAGE UMETA(DisplayName = "Damage"),
ANMID_DEAT UMETA(DisplayName = "Death"),
ANMID_TESTANM1 UMETA(DisplayName = "Test1"),
ANMID_TESTANM2 UMETA(DisplayName = "Test2"),
ANMID_TESTANM3 UMETA(DisplayName = "Test3"),
//Num UMETA(Hidden)
};
//---------------------------------------------------------------------
/// アニメーションイベント
//---------------------------------------------------------------------
UENUM(BlueprintType)
enum class UAnmEvent : uint8 {
ST_START UMETA(DisplayName = "Start"),
ST_END UMETA(DisplayName = "End"),
ST_SHOOT1 UMETA(DisplayName = "Shoot1"),
ST_SHOOT2 UMETA(DisplayName = "Shoot2"),
};
//---------------------------------------------------------------------
/// アニメーションの状態
//---------------------------------------------------------------------
USTRUCT(BlueprintType)
struct FBPAnmState
{
GENERATED_USTRUCT_BODY();
UPROPERTY(BlueprintReadOnly, Category = "BPA")
UAnmIndex AnmIndex = UAnmIndex::ANMID_NONE; //!< 0~1
UPROPERTY(BlueprintReadOnly, Category = "BPA")
float Speed = 0;
FBPAnmState() {
AnmIndex = UAnmIndex::ANMID_NONE;
Speed = 0;
}
};
//---------------------------------------------------------------------
/// アニメーション管理用コンポーネント
//---------------------------------------------------------------------
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class UAnmStateComponent : public UActorComponent
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadOnly, Category = "Variable|Blueprint")
FBPAnmState BPAnmState; //!< アニメーションの状態
public:
//-------------------------------------------------------------------------------
// 指定のイベントをクリア
//-------------------------------------------------------------------------------
void ClearEventNo(int No) {
AnmEventBit &= ~(1 << No);
}
//-------------------------------------------------------------------------------
// アニメーションイベントを受信
//-------------------------------------------------------------------------------
void ReceiveEvent(UAnmEvent AnmEvent) {
if (AnmEvent == UAnmEvent::ST_START) {
if (Started == 0) {
Started = 1;
Ended = 0;
AnmEventBit = 0;
}
}
if (AnmEvent == UAnmEvent::ST_END) {
Started = 0;
Ended = 1;
}
AnmEventBit |= (1 << (uint32)AnmEvent); //受信イベントを保存
if (GEngine) {
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Orange, FString::Printf(TEXT("AnmEvent=%d"), (int)AnmEvent));
}
}
//-------------------------------------------------------------------------------
/// アニメーションの変更要求
//-------------------------------------------------------------------------------
void SetAnmIndex(UAnmIndex AnmIndex) {
AnmEventBit = 0;
BPAnmState.AnmIndex = AnmIndex;
if (GEngine) {
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Orange, FString::Printf(TEXT("ANMIDX=%d"), (int)BPAnmState.AnmIndex));
}
}
uint32 AnmEventBit = 0; //!< 通知されたイベント
private:
int Started;
int Ended;
};
//---------------------------------------------------------------------
/// アニメーション管理用コンポーネント
//---------------------------------------------------------------------
UCLASS()
class UAnmStateNotify : public UAnimNotify {
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere)
UAnmEvent AnmEvent;
void Notify(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation) override {
if (AActor* Actor = MeshComp->GetOwner()) {
auto AnmStateComponent = Actor->FindComponentByClass<UAnmStateComponent>();
if (AnmStateComponent) {
AnmStateComponent->ReceiveEvent(AnmEvent);
}
}
}
};
1DアニメーションidelRun(待機と移動)アニメーションの作成
ブレントスペース1Dを使って待機から走りへと移行するアニメーションを作成します。
コンテンツブラウザ内で右クリックでメニューを開き
アニメーション → ブレンドスペース
の順番で選んでいきます。
〇水平軸の変更
・ MinimumAxisValuek~MAXmumAxisValuekは `0 ~ 1' の値をとるように変更します。
・ Number of Grid Divisions は10 です。
〇アニメーションはアセットブラウザからドロップします。 左から
・ Idle_Relaxed
・ Walk_Fwd
・ Jog_Fwd
の順で登録してあります。
アニメーションに開始と終了のイベントを設定する
アニメーションに開始と終了のイベントを設定します。
AnmStateNotifyからstartとEndを設定します。
AnmStateNotifyはAnmStateComponent.hで定義されています。
さらにAnmStateNotifyを使用してShoot1とShoot2の通知を登録します。
アニメーションBPの作成
ここではアニメーションBPが アクターの状態を取得しアニメーションの再生を行っています。
●イベントグラフ:
PawnのAnmStateComponentからBPAnmStateを取得しAnimGraphに伝えます。
AnmStateComponentはGetComponentByClassで取得します。
●AnimGraph:
受け取ったBPAnmStateに合わせてアニメーションを実行します。
■ブレンドポーズについて
アニメーションを切り替えたときに最初から再生するには、'Reset Child on Activation'にチェックを入れます。
■再生(アニメーション)のloopについて
アニメーション毎にloop設定があるので必要に応じてon/offします。
こんなたたずまいになりました。
つぎは、Key入力にたいしてアニメーションや移動なとアクションを割り当てていきます。