主なコンテンツ

〜主なコンテンツ〜

1. Unityで製作したゲームと製作Tips
  1. 三月精チャレンジ(東方Project二次創作)
    1. 作り方
  2. 英語学習2D(オリジナルスマホアプリ)
2. UE4
3. ゲームアプリ見学
4. Bitbucket & SourceTreeでの一連の流れ
  1. 前半
  2. 後半
5. Tips
  1. UnityのTips
  5. SQL文のTips
  6. Final IK
  7. GearVR+Unity

2023年3月4日土曜日

41. Animation Blueprint

 おかえり。


これでキャラクターの動きができましたが、キャラクターはアニメーション化されていないため、アニメーション インスタンスが必要になります。


これは、アニメーション ブループリントのベースとなる C++ クラスです。


ここで、C++ クラスが必要な理由は、C++ からこれにアクセスしてそのプロパティを設定できるようにするためです。


ここで、このコース全体を通して、アニメーション ブループリントであるアニメーション インスタンスを使用します。


しかし今のところは、プロジェクトを走り回ってテストできるように、アイドル ウォーク、ラン、ジャンプなどの未装備のアニメーションをキャラクターに設定したいと思います。


それでは飛び込みましょう。


わかった。


これが私たちのプロジェクトで、私たちのキャラクターは非常に硬いので、アニメ インスタンスをセットアップします。


それでは、C++ クラスに入りましょう。このキャラクター フォルダーには、Blaster キャラクターがあります。


ここでアニメのインスタンスを作りたいので、右クリックで新しい C++ クラスを選択し、すべてのクラスを選択してインスタンスを検索します。


そして、ここにあります。


[次へ] をクリックすると、ここにパスが設定されていることがわかります。これをキャラクター フォルダーに配置します。


では、これを「ブラスター アニメーション インスタンス」と呼びましょう。


文字クラスを作成したときと同じ警告メッセージが表示されます。 繰り返しますが、それはキャラクター フォルダーに配置したためです。


いいえをクリックします。


ここ Visual Studio には、BlasterAnimInstance.h と BlasterAnimInstance.cpp があります。


  エラーの原因は次のとおりです。Unreal Engine は自動的にキャラクター フォルダをそこに配置します。 これを削除すると、コンパイルできるようになります。

これで、AnimInstance は非常に単純になり、駆動するいくつかの重要な変数を設定するだけで、非常に基本的な未実装のアニメーションになります。


そこで、パブリック セクションを追加し、いくつかの継承された関数をオーバーライドします。 したがって、これらは「仮想オーバーライド」になります。


1 つ目は NativeInitializeAnimation です。 これはBegin Playによく似ています。 これは、ゲームの最初だけでなく、Unreal Engine をロードしてコンパイルするときなど、さまざまなときに呼び出されます。


ここで、NativeUpdateAnimation という別の仮想関数もオーバーライドしたいと思います。これは Delta Time という float を取り、tick 関数と同じようにすべてのフレームで呼び出されます。


これもオーバーライドなので、先に進んでこれら 2 つの関数を実装できます。 そして、何よりも先に最初に行うことは、これらの関数の SUPER バージョンを呼び出すことです。


ですから、忘れないようにしましょう。


これで、super::NativeInitializeAnimation と super::NativeUpdateAnimation が得られました。 それにデルタ時間を渡します。 これで、アニメーション インスタンスには、アニメーション ブループリントに公開できる変数がいくつかあるはずです。


これらは非公開にすることができるので、非公開セクションを作成します。 最初に追加したい変数は、Blaster キャラクターを格納する変数です。 これは、このアニメーション インスタンスを使用するキャラクターになります。


そこで、ABlasterCharacter を前方宣言します。 このポインターは単純に BlasterCharacter と呼ばれます。


アニメーション ブループリントからこれにアクセスする必要があるため、これを UProperty で公開し、このブループリントを読み取り専用にします。


必要に応じて、これにカテゴリを指定できます。 CHARACTER というカテゴリにします。 また、このブループリントを読み取り専用にしているため、これはプライベート変数であるため、メタ指定子が必要です。


このメタ指定子を [allowPrivateAccess = true] に使用しない限り、プライベート変数で読み取り専用のブループリントを使用することはできません。


ここで、ここに保存したい他のいくつかの変数に対して同じことを行います。


1 つは速度のためなので、ここでは同じ UProperty を使用します。 MOVEMENT にできるのはカテゴリのみです。


速度に加えて、空中にいるかどうかも知りたいです。 そこで、bIsInAir という bool を作成します。 そして、これに同じ UProperty カテゴリ MOVEMENT を与えます。


そして、私は別のブールが必要です。 これを [bIsAccelerating] と呼ぶことにします。 その通り。 加速しているかどうかがわかるので、それを使用して、走っているかどうかなどのアニメーションを操作できます。


これら 4 つの変数があり、それらを設定する必要があります。


ここで、ネイティブ初期化アニメーションの早い段階でブラスター キャラクターについて説明します。 BlasterCharacter を TryGetPawnOwner の結果と等しく設定するだけです。


しかし、TryGetPawnOwner を呼び出すと、この関数は Pawn を返します。 これをブラスターキャラクターにキャストする必要があります。


というわけでキャストをやっていきます。 これを ABlasterCharacter にキャストします。 そしてもちろん、BlasterCharacter を「含める」必要があるので、ここの一番上に「含める」ことにします。 blasterCharacter.h になります。


名前の前にそのキャラクター フォルダーを配置せずに、ここでこれを「含める」ことができる理由は、アニメーション インスタンスがキャラクター フォルダー内にあるからです。


これで、ブラスターのキャラクターができました。

現在、NativeUpdateAnimation はすべてのフレームで呼び出されます。 また、NativeInitializeAnimation で設定する前に BlasterCharacter にアクセスしようとしていないことを確認する必要があります。 簡単に確認できます。 「if BlasterCharacter」。 BlasterCharacter が null ポインターであるかどうかを確認したいのですが、そうであればすぐに取得して、NativeUpdateAnimation を呼び出す最初のフレームにアクセスして設定できるようにします。 BlasterCharacter が等しいと言えます。 ここでは、ポーンの所有者を取得して BlasterCharacter にキャストしようとする同じ行を使用します。 これで、Blaster キャラクターへのアクセスが処理されます。


次に、以下の行で BlasterCharacter にアクセスしたいと思います。「If BlasterCharacter」などの IF チェックですべてをラップするのではなく、単に「If BlasterCharacter が null であるか」を確認して戻ります。 その場合、BlasterCharacter が null の場合はこの行に到達しないため、この方法で BlasterCharacter に安全にアクセスできます。


次に設定したい変数は速度です。これにより、BlasterCharacter の速度を取得できます。 ここでは FVector の速度を指定し、単純に BlasterCharacter を使用して getVelocity を呼び出します。 そして、私の速度については、横方向の速度だけが本当に必要です。 速度の z コンポーネントは気にしないので、速度の Z をゼロにします。 したがって、velocity.z = 0.f とします。


次に、このベクトルのサイズを簡単に取得して、速度に等しく設定できます。 したがって、速度は「velocity.size」に等しいと言えます。 そして、私にはスピードがあります。


ここで、bIsInAir を設定したいと思います。 そのため、bIsInAir では、キャラクターの動きのコンポーネントを取得する必要があります。 つまり、もちろん、そのための適切なインクルードを追加する必要があります。 そして、その characterMovementComponent はゲーム フレームワークにあります。 [game/framework/characterMovementComponent.h] をインクルードします。 その型が使えるようになったので、BlasterCharacter から characterMovementComponent を取得します。 つまり、BlasterCharacter->getCharacterMovement になります。 characterMovementComponent から isFalling を呼び出すだけです。 ブール値を返します。 落下している場合は true になります。この場合、空中にいることがわかり、適切なアニメーションを再生できます。

最後に、bIsAccelerating を使用します。 速度ではなく、なぜこれを使用しているのか疑問に思われるかもしれません。 また、インスタンスの観点から加速について話すとき、速度の変化率について話しているのではありません。 物理学を知っていれば、それが加速度の技術的定義であることを知っています。


私が話しているのは、キーを押して移動する入力を追加するかどうかです。 ここでそれを設定します。 bIsAccelerating で、これもキャラクターの動きのコンポーネントから取得します。 BlasterCharacter->getCharacterMovement と言って、現在の加速度を取得します。 getCurrentAcceleration を使用して、このベクトルのサイズを取得します。 ゼロより大きい場合は、それを使用して加速を定義します。


ここで三項演算子を使用して、この数量が 0 より大きい場合は「?」を使用します。 そこで「f」を使います。 次に、ブール値を「true」に設定します。 そして、これが私の「:」であり、「false」はそれ以外の場合です。


というわけで簡単にレビュー。 三項演算子に慣れていない場合は、ここで最初の式がその式、値の真偽を評価します。 したがって、現在の加速度のサイズが 0 より大きい場合、この三項演算子式によって返されるのは、この 2 番目の量です。 最初の式が false と評価された場合、三項式はこの数量をここに返します。 つまり、「この量なら「これ」を返し、そうでなければ「あれ」を返す」と言っているのと同じです。


そのため、コード行を単純化するために、必要に応じて三項演算子を使用します。 そうでなければ、ここに FALSE STATEMENT があるだけです。


これで、"speed" と "isInAir" と "isAccelerating" ブール値を変数に設定しました。 私たちのブラスターキャラクターと同様に。 これで、アニメーション ブループリント内からこれらにアクセスできるようになりました。 それでは、このクラスに基づいてアニメーション ブループリントを作成しましょう。


このコードをコンパイルし、blueprints フォルダーに移動してキャラクターに入ります。 ここにアニメーション ブループリントを追加したいと思いますが、ここで Animation という新しいフォルダーを作成し、作成したアニメーション ブループリントとその他すべてをここに保持します。 これは、アニメーション モンタージュのようなアニメーション関連です。


右クリックして、新しいアニメーション ブループリントを作成します。 親クラスには AnimInstance を選択します。 次に、クラスの親を blasterAnimInstance に変更します。 [最高の成功設定] をこのように設定しました。


次に、スケルトンを sk_epic_character_skeleton に設定し、[OK] をクリックします。 これを BlasterAnimBP と呼びたいと思います。


そして、それを開いてみましょう。 さて、これが私の blasterAnimBP です。


最初に行うことは、クラスの設定に移動することです。これは、ここの上部のバーに表示されます。 クラス設定では、親クラスを BlasterAnimInstance に設定します。


BlasterAnimInstance からアニメーション ブループリントを派生させたので、C++ で宣言した変数 (加速、速度、Blaster キャラクターなど) にアクセスできるはずです。そのため、これらのブループリントを読み取り専用にして、このブループリント内からアクセスできるようにしました。


さて、このゲームの大部分で、キャラクターは武器を装備します。 しかし、その機能を実装するまでは、未装備用のアニメーション ステート マシンを使用する予定です。


それではステートマシンを作ってみましょう。


新しいステート マシンを追加して、出力ポーズに接続します。 そして、これを未装備と呼びます。

これは、キャラクターが武器を持っていないときにポーズに使用するステート マシンです。 そこで、ステート マシンに移動して、いくつかのステートを追加します。


さて、まず、アイドル ウォーク アラウンド状態が必要になります。 したがって、このアイドル ウォーク ランを簡単に呼び出すことができます。 そして、このための簡単なブレンド スペースを作成します。


また、キャラクターもジャンプできる必要があります。 そこで、ジャンプ用の状態をいくつか作成します。 最初のアニメーションを作成するためにジャンプ スタートを実行し、空中にいるときのアニメーション状態を作成します。 これを落下と呼ぶことにします。


そして落下から、ジャンプストップアニメへ。 それでは、ジャンプ停止状態を追加しましょう。 そして、ジャンプストップから、そのままアイドルウォーク、ランに戻ることができます。 繰り返しますが、これは簡単です。


「アイドルウォークランからジャンプスタートへ」、ダブルクリックしてそのトランジションに入りましょう。


これには isInAir を使用します。 isInAir が true の場合、ジャンプ スタート アニメーションに移行し、ジャンプ スタートから落下することができます。 これを自動移行にするだけです。 [シーケンス、プレーヤー、状態に基づく自動ルール] の横にあるチェックボックスをオンにできます。 つまり、このアニメーションが終了するとすぐに、次の状態 (落下アニメーション) に自動的に遷移します。


フォールバックからジャンプストップまで、再び isInAir を使用できます。 そこで、isInAir を使用します。 そしてもちろん、このブール値を false にする必要があります。 そこで、[NOT boolean] を使用します。 isInAir が false の場合は遷移し、アイドル ウォーク ランに戻ります。


このアニメーションが特定のポイントまで再生されたら、そのために残り時間ノードを使用します。これを行うには、そこにアニメーションが必要です。 ですから、これについてはすぐに説明します。


Jump Start では、Jump を検索し、Learning Kid Games Pack に付属のアニメーションをいくつか使用します。 そしてそれらは EPIC CHARACTER で始まります。 したがって、エピック キャラクター ジャンプ アップ スタートは、キャラクターが武器を持っていない場合のジャンプ スタート アニメーションです。 それをダブルクリックすると、このように見えることがわかります。 これをジャンプスタートと落下状態に使います。


EPIC CHARACTER ジャンプ アップ ループがあり、それがこのアニメーションです。 彼はちょうど落下ポーズです。 ジャンプストップには、EPIC CHARACTERのジャンプアップエンドがあります。 そして、これがそのアニメーションの外観です。 それを再生して、キャラクターが地面に (落下) 戻っていることを確認できます。


これで [jump stop] の中にアニメーションができました。 [残り時間の比率] を使用するこの遷移規則を完成させることができます。


[残り時間比率] は、比率が必要なアニメーションを知る必要があるノードです。 だからこそ、あのアニメーションが必要だったのです。


これはジャンプアップとアニメーションのためのもので、残り時間が特定の値以下かどうかを確認したいだけで、0.1 などを使用できます。 したがって、アニメーションが 90% 再生され、そのアニメーションの残り時間の比率が 0.1 になると、IdleWalkRun に戻ります。

IdleWalkRun では、ブレンド スペースを使用して、アイドリングから実行中へのブレンドを行います。 それでは、そのブレンドスペースを作りましょう。


アニメーション フォルダに戻り、右クリックしてアニメーションを選択し、単純な [ブレンド スペース 1D] を使用します。 SK_epic_character_skeleton を選択します。 そして、これを未装備の IdleWalkRun と呼ぶことにします。


そして、これは簡単です。 EpicCharacter_Idle アニメーションを作成します。 ここにあります。 そして、彼はただそこに立って周りを見回しています。


(今) EpicCharacter_Walk があります。 これを 2 番目の場所で設定し、最後に EpicCharacter_Run を使用できます。 今度は横軸が速度になります。 [maximum] については、およそ 350 に達したら running_animation に入りたいと思います。


キャラクターのデフォルトの最大歩行速度はそれよりも高速です。 約 600 です。ゼロから最大歩行速度まで加速するので、スムーズな移行が得られるはずです。


これでブレンド スペースができたので、それを閉じます。 ここで UnequipledIdleWalkRun を取得し、それを PLUG して、速度変数 (C++ で宣言し、NativeUpdateAnimation で設定しています) を使用するだけです。


ですから、それをコンパイルして保存します。 これで、今のところのアニメーション グラフが完成しました。 キャラクター用の単純なステート マシンがあります。 武器なしで装備されていません。


それでは、キャラクター フォルダの BP_BlasterCharacter に戻り、メッシュを選択して新しいブループリントを割り当てます。


では、アニメーションモードを [use animation blueprint] にしましょう。


[アニメーション クラス] には BlasterAnimBP を使用します。アニメーション インスタンスではなく BP を選択してください。これは、BP がステート マシンを持つものであるためです。 コンパイルして再生すると、キャラクターがアイドル状態になっていることがわかります。


これで、まだコントローラーと一緒に回転しており、動きに向けられていません。これは、私たちが望むものです。 そこで、いくつかのことを行います。


まず、BlasterCharacter.CPP に戻り、C++ でいくつかの変数を設定します。


1 つ目は、コントローラーの rotationYaw を使用することです。 これを false に設定します。 少なくともまだ、コントローラーの回転に合わせてキャラクターを回転させたくないからです。 武器を装備し、エイム オフセットを使用していて、状況がさらに複雑になったら、それを使用したいと思うでしょう。 しかし今のところ、コントローラーの回転とは無関係にキャラクターを静止させ、代わりに独自の移動方向に向けます。


そのために、getCharacterMovement を使用してキャラクターの動きのコンポーネントを取得し、ブール値の bOrientRotationToMovement にアクセスします。 これを true に設定します。


ここで、キャラクターの移動コンポーネントを使用しています。 また、ヘッダーを含めたインスタンスでも使用していることを思い出してください。 これをコピーして、インクルードし、BlasterCharacter の上部に貼り付けることができます。 そして今、そこに含まれているエラーはありません。


これをコンパイルしますが、設定した C++ 変数とコンストラクターをブループリントがオーバーライドするため、ブループリントでこれらの変数を設定する必要もあります。


BlasterCharacter に戻ります。 BP_BlasterCharacter(self) を選択し、[use controller rotation Yaw] を検索します。 チェックを外します。 CharacterMovement を選択し、[回転を動きに合わせる] を検索し、チェックされていることを確認します。


コンパイルできるように見えるので、今再生すると、キャラクターは移動方向に向き、コントローラーを動かし、スプリングアームとカメラを拡張すると、キャラクターはそれに沿って回転しません.


これで、キャラクターが走り回ることができました。これは素晴らしい出発点です。 動きがあり、アニメーションがあり、ジャンプできます。 だから、これはよさそうだ。


ここで、ジャンプの最後でキャラクターの一種のグリッチが発生することに気付きました。 そこで、AnimBP の JumpStop 状態に戻り、ジャンプ エンドを選択し、ループ アニメーションのチェックを外してコンパイルします。 さて、戻ってジャンプすると、もうその不具合はありません。 そして今、私たちはジャンプしています。


すべてが良さそうです。


この講義では、アニメーション ブループリントをセットアップし、このアニメーション ブループリントの親として使用するアニメーション インスタンス C++ クラスを用意しました。


このようにして、C++ から変数を設定し、ブループリント内の変数にアクセスしてアニメーションを駆動できます。 キャラクターが走り回っており、今後のビデオでより複雑な機能を追加する予定です。 しかし、今のところ、基本的な動きがあります。


よくやった。


また後で。


Welcome back.


Now we have character movement, but our character is not animated, so we're going to need an anim instance.


This is the C++ class that our animation blueprint will be based on.


Now, the reason we want a C++ class is that so we can access this from C++ and set its properties.


Now we'll be working with our anim instance, an animation blueprint all throughout this course.


But for now, we'd like to just set up some unequipped animations, such as Idle Walk, Run and jumping for our character so that we can run around and test our project.


So let's jump in.


Okay.


So here's our project and our character is quite stiff, so we're going to set up an anime instance.


So let's go into our C++ classes and here in our character folder we have Blaster character.


I'd like to make the anime instance here, so I'm going to right click select new C++ class and choose all classes and search for an instance.


And here it is.


I'm going to click next and I see that we have the path set here and we'll be placing this in the character folder.


So let's call this "blaster anim instance".


Now we're going to get this same warning message we got when we created the character class. And again, that's because we placed it in the character folder.


So we're going to click No.


And here in Visual Studio I have my BlasterAnimInstance.h and the BlasterAnimInstance.cpp.


 and here's the cause of that error.Unreal Engine automatically places the character folder there. I'm going to remove that and I should now be able to compile.


Now our AnimInstance is going to be quite simple for now we're just going to set up a few key variables to drive are very basic unequipped animations.


So I'm going to add a public section and override a couple of inherited functions. So these are going to be "virtual overrides".


And the first one is NativeInitializeAnimation. Now this is much like Begin Play. It's going to be called at the very beginning of the game as well as at other various times, such as when we load up Unreal Engine and compile and so on.


Now I'd also like to override another virtual function called NativeUpdateAnimation, and this one takes a float called Delta Time, and this is called every frame, much like the tick function.


Now this is also an override, so we can go ahead and implement these two functions. And the first thing we're going to do before anything else is call the SUPER version of these functions.


So let's make sure we don't forget to do that.


So we got super::NativeInitializeAnimation and super::NativeUpdateAnimation. and we're passing Delta time into that one. Now, our anim instance should have a few variables that we can expose to our animation blueprint.


Now, these can be private, so I'm going to make a private section. And the first variable I'd like to add is a variable to store the Blaster character. This is going to be the character using this anim instance.


So I'm going to forward declare ABlasterCharacter. and this pointer is simply going to be called BlasterCharacter.


And since we need to access this from the animation blueprint, we're going to expose this with a UProperty, and I'm going to make this blueprint read only. 


Now, we can give this a category if we like. I'm going to give it the category CHARACTER. And because I'm making this blueprint read only, I need a meta specifier because this is a private variable.


Now we can't use blueprint read only on private variables unless we use this meta specifier to [allowPrivateAccess = true].


Now I'm going to do the same thing for several other variables that I would like to store here.


One is going to be for the speed, so I'm going to use the same UProperty here. Only the category can be MOVEMENT.


And in addition to speed, I'd also like to know whether or not we're in the air. So I'm going to make a bool called bIsInAir. And I'll give this the same UProperty category MOVEMENT.


And I need another bool. and I'm going to call this one [bIsAccelerating]. That way. We know if we're accelerating and we can use that to drive our animations, such as whether or not we're running and so on.


So we have these four variables and we need to set those.


Now I'm going to said Blaster character early on here in Native Initialize animation. All I'm going to do is set BlasterCharacter equal to the result from TryGetPawnOwner.


But if I just call TryGetPawnOwner, This function returns Pawn. and I need to cast this to a blaster character.


So I'm going to perform the cast. And I'm going to cast this to ABlasterCharacter. And of course I need to "INCLUDE" BlasterCharacter, so I'm going to "INCLUDE" that at the top here. It's going to be blasterCharacter.h.


And the reason we can "INCLUDE" this here without placing that character folder before the name is because the anim instance is right here in the character folder.


So we have our blaster character.


Now NativeUpdateAnimation is called every frame. and we need to make sure that we're not trying to access BlasterCharacter before we've set it in NativeInitializeAnimation. so we can simply check. "if BlasterCharacter". and I'd like to check to see if BlasterCharacter is null pointer and if that's the case, then I'll quickly get it so that the first frame we call a NativeUpdateAnimation, we can access that and set it, So we're going to say BlasterCharacter equals. And we're going to use this same line here where we try to get pawn owner and cast to BlasterCharacter. So that takes care of accessing Blaster character.


Now I'd like to access BlasterCharacter in the lines below, and rather than wrapping everything in an IF check, such as "If BlasterCharacter", I'm just going to check to see "if BlasterCharacter is null" and return. If that's the case, That way we can simply access BlasterCharacter safely down here as we won't reach this line if BlasterCharacter is null.


So the next variable that I'd like to set is the speed so I can get my BlasterCharacter's velocity. So I'm going to say FVector velocity and I'm going to simply use BlasterCharacter and call getVelocity. And for my speed, I really only want the lateral speed. I don't care about the z component of my velocity, so I'm going to zero out the Z of my velocity. So I'm going to say velocity.z = 0.f. 


and then I can simply get the size of this vector and set it equal to speed. So I'm going to say speed equals "velocity.size". And I have my speed.


Now I'd like to set bIsInAir. So for bIsInAir, I need to get my character's movement component. That means, of course, I'm going to need to add the proper include for that. And that characterMovementComponent is in game framework. So I'm going to include [game/framework/characterMovementComponent.h]. Now I can use that type, so I'm going to get the characterMovementComponent from BlasterCharacter. So it's going to be BlasterCharacter->getCharacterMovement. And from the characterMovementComponent we can simply call isFalling. which returns a boolean. Now if we're falling, then we'll get true, in which case we'll know that we're in the air and we can play the appropriate animations.

Now finally I'm going to use bIsAccelerating. Now you may be wondering why we're using this rather than the speed. And when we talk about accelerating from the an instance point of view, we're not talking about the rate of change of velocity. If you know physics, you know that that's the technical definition of acceleration.


What I'm talking about is whether or not we're adding input where pressing the keys to move. Now we're going to set that right here. So bIsAccelerating and we're going to get this from the character movement component as well. So we're going to say BlasterCharacter->getCharacterMovement and we're going to get the current acceleration. Using getCurrentAcceleration and I'm going to get the size of this vector. And if it's greater than zero, then I'm going to use that as my definition for is accelerating.


So I'm going to use the ternary operator here and I'm going to say if this quantity here is greater than zero, there's my "?". I'm going to use that "f" there. Then I'm going to set my boolean to "true". And then here's my ":" and "false" will be else the case. 


So just a quick review. If you're not familiar with the ternary operator, it takes the first expression here evaluates that expressions, truth of value. So if the current accelerations size is greater than zero, then what is returned by this ternary operator expression is this second quantity here. And if the first expression evaluates to false, then the ternary expression returns this quantity here. So it's the same as saying, "if this quantity, return "this", else, return "that". 


So we're going to be using the ternary operator when appropriate to simplify our lines of code. Otherwise, we would just have a FALSE STATEMENT here.


Now we've set our "speed" and "isInAir" and "isAccelerating" boolean in variables. as well as our blasterCharacter. So we can now access these from within an animation blueprint. So let's go ahead and make an animation blueprint based on this class.


I'm going to compile this code and I'm going to go into my blueprints folder and into character. And here in character, I'd like to add my animation blueprint, but I'm going to make a new folder here in character called Animation, and I'll keep my animation blueprint here as well as anything else I create. That's animation related, like anim montages.


So I'm going to right click and create a new animation blueprint. And for the parent class, I'm going to choose AnimInstance. Then I'm going to reparent the class to blasterAnimInstance. I've had [the best success setting] things up this way. 


Now I'm going to set the skeleton to sk_epic_character_skeleton and click Okay. Now I'd like to call this BlasterAnimBP.


And let's open that up. Now, here's my blasterAnimBP.


The first thing I'm going to do is go to my class settings, which you should see at the top bar here. And in class settings, I'm going to set the parent class to BlasterAnimInstance.


So now that we've derived our animation blueprint from the BlasterAnimInstance, we should have access to those variables we declared in C++, such as is accelerating and Speed and Blaster character and so on.

So we made those blueprint read only so we can access them from within this blueprint.


Now, for the majority of this game, our character is going to be equipped with a weapon.  But until we implement that functionality, we're going to have an animation state machine for unequipped.


So let's make a state machine.


We'll add a new state machine and plug it in to output pose. And I'm going to call this unequipped.

And this will be the state machine that we're using for our pose whenever our character does not have a weapon. So I'm going to go into the state machine and add a few states.


Now, firstly, we're going to need an idle walk around state. So I can simply call this idle walk run. And we'll be making a simple blend space for this. 


And our characters should also be able to jump. So we're going to create some states for jumping. I'm going to do a jump start to have the beginning animation, and we'll have an animation state for when we're in the air. I'm going to call this falling.


And from falling, we'll go to the jump stop animation. So let's add a jump stop state. And from jump stop, we can go straight back to idle walk, run. Now again, this is going to be simple. 


"From idle walk run to jump start", Let's double click to enter that transition.


And I'm going to use isInAir for this.  if isInAir is true we can go into the jump start animation and from jump start to falling. I'm going to just make this an automatic transition. I can check the checkbox right here next to [automatic rule based on sequence, player and state]. And all that means is as soon as this animation finishes, then we'll automatically transition to the next state, which will be our falling animation. 


And from falling back to jump stop we can use isInAir again. So I'm going to use isInAir. And of course we want this boolean to be false. So I'm going to use a [NOT boolean]. And will transition if isInAir is false and for jump start back to idol walk run. 


We'll transition, When this animation has played up to a certain point, we're going to use a time remaining node for that, which we need an animation in there to do that. So we'll get to this one very shortly.


Now for Jump Start, I'm going to search for Jump and we're going to use some of the animations that came with the Learning Kid Games Pack. And those start with EPIC CHARACTER. So epic character jump up start is a jump start animation when the character has no weapon. If we double click that, we can see that this is what it looks like. So I'm going to use that for jump start and for the falling state.


We have EPIC CHARACTER jump up loop and that's this animation here. He's just in the falling pose. And for Jump Stop, we have EPIC CHARACTER jump up end. And here's what that animation looks like. We can play it to see that it's just the character (falling) back to the ground.


So now that our [jump stop] has an animation inside it. we can complete this transition rule where we're going to use a [time remaining ratio].


And [time remaining ratio] is a node that needs to know what animation we want the ratio for. That's why we needed that animation there.


And this is for the jump up and animation and we simply want to see if the time remaining is less than or equal to a certain value and we can use something like 0.1. So when the animation has played 90% of the way through and the ratio of time left on that animation is 0.1 will transition back to IdleWalkRun.

Now for IdleWalkRun, we're going to use a blend space to blend from idling to running. So let's make that blend space. 


So back here in our animation folder, I'm going to right click select animation and we'll use a simple [blend space 1D] for this. and choose SK_epic_character_skeleton. And I'm going to call this unequippedIdleWalkRun.


And this will be simple. We're going to have the EpicCharacter_Idle animation. Here it is. And he's just standing there looking around.


(Now) we have an EpicCharacter_Walk. We can set that here at the second spot here, and we can use EpicCharacter_Run for all the way at the end. Now the horizontal axis is going to be speed. and for [maximum], I'd like to be in the running_animation Once we've reached roughly, say, 350.


The character's default max walk speed is higher than that. It's about 600. So we should get a smooth transition as we're accelerating from zero to the max walk speed.


Now we have a blend space, so I can close that. and we can get UnequippedIdleWalkRun here and PLUG that in and simply use our speed variable (that we declared in C++ and we're setting in NativeUpdateAnimation).


So I'm going to compile that and save. And now our anim graph for now is complete. We have a simple state machine for our character. unequipped without a weapon.


So let's go back to our character folder into BP_BlasterCharacter and I'm going to select my mesh and assign my new blueprint.


So let's choose for animation mode, [use animation blueprint].


And for the [anim class], we're going to use BlasterAnimBP, make sure to choose the BP and not the anim instance as the BP is what has the state machine. so we can compile and if we hit play we see that our character is idling.


Now it's still rotating along with our controller and it's not orienting towards movement, which is something that we're going to want. So we're going to do a couple of things.


First, we're going to go back to our BlasterCharacter.CPP, and we're going to set some variables in C++.


The first is be use controller rotationYaw. we're going to set that to false. as we don't want our character rotating along with our controller rotation, at least not yet. Once we're equipped with a weapon and we're using an aim offset and things get more complicated, we're going to want to use that. But for now, we're just going to have our character standing still independent of the controller rotation, and instead we're going to have it orient towards its own movement direction.


And for that, we're going to get our character movement component with getCharacterMovement and access the Boolean bOrientRotationToMovement. We're going to set that to true.


Now we're using our character movement component here. And if you'll recall, we're also using it in the an instance where we included the header for it. So we can copy that, include and paste that right here at the top of BlasterCharacter. And now we don't have the included error there.


Now we're going to compile this, but we also need to make sure to set these variables in blueprints because the blueprint will override the C++ variables that we set and the constructor.


So we'll go back to BlasterCharacter. and select BP_BlasterCharacter(self) and search for [use controller rotation Yaw]. and we're going to uncheck that. and we'll select CharacterMovement and search for [orient rotation to movement] and make sure that's checked.


It looks like it is so we can compile and if I hit play now, the character orients toward the direction of movement and if we move our controller and by extension our spring arm and camera, the character doesn't rotate along with it.


So now we have our character running around and this is a great starting point. We have a movement, we have animations, we can jump. So this is looking good. 


Now I notice that the character sort of glitches at the end of the jump. So I'm going to go back into my AnimBP into my JumpStop state and select a jump end and uncheck loop animation and compile. Now, if I go back and jump, we don't have that glitch anymore. And now we're jumping and.


Everything looks good.


So in this lecture we set up our animation blueprint and we have an anim instance C++ class that we're using as the parent for this animation blueprint.


And that way we can set variables from C++ and access those in the blueprint to drive our animations. So we now have a character running around and we're going to be adding more complicated functionality in the videos to come. But for now, we have basic movement.


Great job.


I'll see you soon.


0 件のコメント:

コメントを投稿