移動、回転、スケールする上記のオブジェクトでは、3 つすべてを同時に行っています。 ただし、同時に複数の方法で移動する小道具用のアニメーションを作成する際に考慮すべき、いくつかの重要な課題があります。
アニメーション コントローラーが一度に再生できるアニメーションは 1 つだけであるため、移動、回転、スケールを個別のアニメーションで行うことはできません。 また、小道具をアニメーションごとに複数回回転させることもできるよう、それらのアニメーションでは複数のキーフレームが必要です。 すべてのキーフレームを事前に作成しておく必要があるため、小道具の経路の各ポイントで位置、回転、スケールを計算する必要もあります。 小道具で均等な量の回転が作成されない場合はどうなるでしょうか。 半回転はどのように処理するのでしょうか。
この後のセクションでは多数の数学演算を伴いますが、セクションが終わるまでに、小道具を複数のポイントに移動、回転、スケールでき、複雑で動的で楽しい (これが最も重要) プラットフォームの課題を作成して、理想の Fall Guys コースを構築できるようになります。
移動、回転、スケールするアニメーションを作成する
以下の手順に従って、1 つにまとめ始めます。
Verse Explorer を使用して、
movable_propを継承するanimating_propという新しい Verse クラスを作成します。 このクラスに<concrete>指定子を付加して、そのプロパティが UEFN に公開されるようにします。Verse# A prop that translates, rotates, and scales to a destination using animation. animating_prop<public> := class<concrete>(movable_prop):using { /Fortnite.com/Devices/CreativeAnimation }文とusing { /UnrealEngine.com/Temporary/SpatialMath }文をファイルの先頭に追加して、これらのモジュールがインポートされるようにします。 これらは、小道具をアニメートするために必要になります。 このセクションで使用されているツールチップも以下に示しています。Verseusing { /Fortnite.com/Devices } using { /Fortnite.com/Devices/CreativeAnimation } using { /Verse.org/Simulation } using { /UnrealEngine.com/Temporary/SpatialMath } RotationRateTip<localizes>:message := "The time it takes to make one AdditionalRotation in seconds." UseEasePerKeyframeTip<localizes>:message := "Whether this prop should use the MoveEaseType for each keyframe. False will use the Linear ease type on each frame." # A prop that translates, rotates, and scales to a destination using animation. animating_prop<public> := class<concrete>(movable_prop):animating_propクラス定義の先頭で、以下のフィールドを追加します。AdditionalRotationという編集可能なrotation。 これは、キーフレームごとにRootPropに適用される回転です。Verse# The additional rotation to apply to the RootProp per keyframe. @editable {ToolTip := AdditionalRotationTip} AdditionalRotation:rotation = rotation{}RotationRateという編集可能なfloat値。 これは、AdditionalRotationを 1 回行うのにかかる時間 (秒) です。Verse# The time it takes to make one AdditionalRotation in seconds. @editable {ToolTip := RotationRateTip} var RotationRate:float = 1.0UseEasePerKeyFrameという編集可能なlogic。 これは、各キーフレームで補間にMoveEaseTypeが使用されるかどうかを指示します。 この例では、この値をfalseに設定すると、各フレームでデフォルトの線形補間タイプが使用されます。Verse# Whether this prop should use the MoveEaseType per each frame of animation. # Setting this to false will use the linear MoveEaseType on each frame. @editable UseEasePerKeyframe:logic = trueMoveTargetsという、creative_propの編集可能な配列。 これらは、ルート小道具が移動先にすることができるクリエイティブの小道具です。Verse# The Creative prop target for the RootProp to move toward. @editable {ToolTip := MoveTargetsTip} var MoveTargets:[]creative_prop = array{}TargetTransformというtransform変数。 これは、ルート小道具が現在移動先にしているトランスフォームです。Verse# The transform the prop is currently targeting. var TargetTransform:transform = transform{}
クラス定義は次のようになります。
Verseusing { /Fortnite.com/Devices } using { /Fortnite.com/Devices/CreativeAnimation } using { /Verse.org/Simulation } using { /UnrealEngine.com/Temporary/SpatialMath } RotationRateTip<localizes>:message := "The time it takes to make one AdditionalRotation in seconds." UseEasePerKeyframeTip<localizes>:message := "Whether this prop should use the MoveEaseType for each keyframe. False will use the Linear ease type on each frame." # A prop that translates, rotates, and scales to a destination using animation. animating_prop<public> := class<concrete>(movable_prop):animating_propクラスのMove()関数をオーバーライドします。 そして、for式内で、MoveTargets配列の各MoveTargetをイテレートします。 各MoveTargetが有効であるかどうかをチェックし、有効であれば、TargetTransformをMoveTargetのトランスフォームに設定します。Verse# Move and rotate the RootProp toward the MoveTarget, or MoveTransform if one is set. Move<override>()<suspends>:void= # Move to each target in the MoveTargets array. for: MoveTarget:MoveTargets do: # Set the TargetTransformto the MoveTarget if the # MoveTarget is set. Otherwise set it to the MoveTransform.「
movement_behaviors」ファイルに戻り、BuildMovingAnimationKeyframes()という新しいメソッドを追加します。 この関数は、ターゲット トランスフォームに移動および回転する小道具をアニメートする、キーフレームの配列を構築して返します。 この関数は、animating_propからいくつかのパラメータを受け取ります。MoveDuration、RotationRate、AdditionalRotation、OriginalTransform(小道具の開始時のトランスフォーム)、TargetTransform、MoveEaseType、およびUseEasePerKeyframeという新しいlogic値です。 この logic 値によって、各キーフレームでMoveEaseTypeを使用するかどうかが決まります。 関数シグネチャは次のようになります。Verse# Builds an array of keyframes that animate movement and rotation from the OriginalTransform to the TargetTransform. BuildMovingAnimationKeyframes(MoveDuration:float, RotationRate:float, AdditionalRotation:rotation, OriginalTransform:transform, TargetTransform:transform,MoveEaseType:move_to_ease_type, UseEasePerKeyframe:logic):[]keyframe_delta=BuildMovingAnimationKeyframes()内で、以下の変数を初期化します。Keyframesというkeyframe_deltaの変数配列。 これは、終了時に返す配列です。Verse# The array of keyframes to return. var KeyFrames:[]keyframe_delta = array{}TotalTimeというfloat変数。 これは、これまでにアニメートに費やした合計時間です。Verse# The total amount of time spent animating. var TotalTime:float = 0.0StartTransformとEndTransformという 2 つのtransform変数。 これらはそれぞれ、各キーフレームの開始時と終了時の、小道具の開始トランスフォームと終了トランスフォームです。 どちらもOriginalTransformに初期化します。Verse# The starting transform for building keyframes. This is the # transform of the RootProp at the start of each keyframe. var StartTransform:transform = OriginalTransform # The ending transform for building keyframes. This is the # transform of the RootProp at the end of each keyframe. var EndTransform:transform = OriginalTransformRotationToApplyというrotation変数。AdditionalRotationに初期化されています。 これは、各キーフレームに対して小道具に適用される実際の回転です。 これは、通常はAdditionalRotationですが、部分回転を作成する必要がある場合は、この値を変更します。Verse# The actual rotation to apply to the RootProp. Usually this is the # AdditionalRotation, but will change in cases with fractional rotations. var RotationToApply:rotation = AdditionalRotationAnimationTimeというfloat変数。 これは、各キーフレームの所要時間 (秒) です。 RootProp では 1 秒あたりRotationRate個の回転を作成する必要があるため、この値を1.0 / RotationRateに初期化します。Verse# The time it takes for each keyframe of animation to complete. # This is initialized to 1.0/Rotation rate since the RootProp needs to make a # RotationRate number of rotations per second. var AnimationTime:float = 1.0 / RotationRateTotalRotationsというfloat値。 これは、アニメーション全体で作成される回転の総数であり、MoveDuration * RotationRateに初期化されています。 これがintではなくfloatである理由は、アニメーションの終了時などで 1 回転を作成する必要がない場合に対処するためです。Verse# The total number of rotations to make. TotalRotations:float = MoveDuration * RotationRateTimePerRotationというfloat値。 これは、1 つの回転が完了するのにかかる時間 (秒) です。 この関数は次のようになっています。Verse# Builds an array of keyframes that animate movement and rotation from the OriginalTransform to the TargetTransform. BuildMovingAnimationKeyframes(MoveDuration:float, RotationRate:float, AdditionalRotation:rotation, OriginalTransform:transform, TargetTransform:transform,MoveEaseType:move_to_ease_type, UseEasePerKeyframe:logic):[]keyframe_delta= # The array of keyframes to return. var KeyFrames:[]keyframe_delta = array{} # The total amount of time spent animating. var TotalTime:float = 0.0 # The starting transform for building keyframes. This is the
追跡する値が多数あるため、一例として、RotationRate が 2.5 であり、MoveDuration が 5.0 である場合の計算を以下に示します。
Rotation Rate = 2.5 rotations/second
Move Duration = 5.0 seconds
Animation Time =
1.0 seconds/Rotation Rate =
1.0/2.5 = 0.4 seconds
Total Rotations =
Move Duration /Rotation Rate =
RotationRate が 2.5 であり、MoveDuration が 5.0 であれば、合計 12.5 個の回転を作成し、各回転に 0.4 秒かかります。 したがって、アニメーションの終了時に、1 つの半回転を余分に作成する必要があることになります。 また、AnimationTime と TimePerRotation の時間が同じであることもわかります。 1 回転未満の回転を作成する必要がある場合を除いて、ほとんどの場合にそうなります。 それらが最初は同じ値であっても、どちらの変数も追跡して、後で数学演算を処理する必要があります。
ループ内でキーフレームを作成する
では、作成しましょう。 以下の手順に従って、キーフレームを作成するループをセットアップします。
loop式をBuildMovingAnimationKeyframes()に追加します。 ループのイテレーションごとに、新しいキーフレームを作成し、それをキーフレームの配列に追加します。 ループの先頭で、TotalTimeをTimePerRotationに更新します。Verse# Build each keyframe of animation and add it to the Keyframes array. # The loop breaks when the TotalTime goes past the MoveDuration. loop: # Add the TimePerRotation to the TotalTime. set TotalTime += TimePerRotationこのキーフレームの終了時の小道具のトランスフォームを表す
EndTransformを作成します。EndTransformを、以下のパラメータを使用した新しいトランスフォームに設定します。Translationを、OriginalTransformとTargetTransformの間でLerp()を呼び出した結果に設定します。Lerp()関数は、2 つの値と LerpRatio (0.0~1.0の範囲の値) を受け取ります。 LerpRatio に基づいて 2 値の間に新しい値を生成します。 LerpRatio が 1.0 に近いほど、新しいトランスフォームはTargetTransformに近くなり、逆の場合は遠ざかります。Verse# Build the ending transform for the RootProp to move to. set EndTransform = transform: # Use Lerp() to find how far between the StartingTransform and the TargetTransform the RootProp should translate. # Do the same for scale, and rotate the starting transform by the RotationToApply. # The Lerp Parameter is based on the total number of rotations since the RootProp should guarantee that it makes # at least that many rotations over the whole animation. Translation := Lerp(OriginalTransform.Translation, TargetTransform.Translation, (TotalTime * RotationRate) / (TotalRotations))Rotationを、元のトランスフォームの回転およびRotationToApplyによって回転された元のトランスフォームを渡した、MakeShortestRotationBetween()の結果に設定します。VerseTranslation := Lerp(OriginalTransform.Translation, TargetTransform.Translation, (TotalTime * RotationRate) / (TotalRotations)) Rotation := MakeShortestRotationBetween(OriginalTransform.Rotation, OriginalTransform.Rotation.RotateBy(RotationToApply))~~~Scaleを、OriginalTransform.ScaleとTargetTransform.Scaleの間でLerp()を呼び出した結果に設定します。 これは小道具のスケールを合わせるスケールであり、必要なスケールの倍率ではないことに注意してください。 完全なEndTransformは次のようになります。Verse# Build the ending transform for the RootProp to move to. set EndTransform = transform: # Use Lerp() to find how far between the StartingTransform and the TargetTransform the RootProp should translate. # Do the same for scale, and find the shortest rotation between the original transform and a rotation to apply to it. Translation := Lerp(OriginalTransform.Translation, TargetTransform.Translation, LerpParameter) Rotation := MakeShortestRotationBetween(OriginalTransform.Rotation, OriginalTransform.Rotation.RotateBy(RotationToApply)) Scale := Lerp(OriginalTransform.Scale, TargetTransform.Scale, LerpParameter)
終了トランスフォーム セットが作成できたので、キーフレームを作成しましょう。 これは
MoveToEase()関数に対して行った処理とほぼ同じです。keyframe_delta変数を新規作成して「KeyFrame」という名前にします。DeltaLocationを、開始トランスフォームの平行移動と終了トランスフォームの平行移動の差分に設定します。DeltaRotationを、終了トランスフォームの回転に設定します。 スケールでの変化を計算する必要があるため、DeltaScaleを、終了トランスフォームのスケールを開始トランスフォームのスケールで除算した結果に設定します。TimeはAnimationTimeであり、InterpolationTypeはif式の結果です。UseEasePerKeyframeが true であれば、MoveEaseTypeを使用します。 その他の場合は線形型を使用します。 キーフレーム式は次のようになります。Verse# Build the animation keyframe to animate the RootProp. Keyframe := keyframe_delta: DeltaLocation := EndTransform.Translation - StartTransform.Translation, DeltaRotation := EndTransform.Rotation, DeltaScale := EndTransform.Scale/StartTransform.Scale, Time := AnimationTime, # Use the MoveEaseType for interpolation if UseEasePerKeyframe is true, # otherwise use the Linear movement type. Interpolation := if:キーフレームを作成したので、それを
Keyframes配列に追加することができます。 さらに、StartTransformをEndTransformに設定して、次のキーフレーム用にそれを更新します。 最後に、TotalTimeがMoveDurationより大きくなっていれば、ここでループを抜けます。Verse# Add the new keyframe to the KeyFrames array, and set the # StartTransform to the EndTransform. set Keyframes += array{Keyframe} set StartTransform = EndTransform # Break out of the loop if the TotalTime passes the MoveDuration. if: TotalTime >= MoveDuration then: break考慮すべき重要なエッジケースとして、1 回転未満の回転を作成する場合があります。
TimePerRotationをTotalTimeに追加しているため、ループの開始時にTotalTimeがMoveDurationよりも大きくなっている可能性があります。 この状況では、差分に相当する、短いアニメーション時間で、残り時間を調整して 1 回転未満の回転にする必要があります。 この状況に対応するために次の手順を実行します。ループの先頭に戻り、
TotalTimeを更新した後で、if式を開始します。 その中で、変数LeftoverTimeを初期化し、TotalTimeからMoveDurationを除算した結果に一致するように設定して、それが0.0より大きいかどうかをチェックします。 比較結果が true であれば、この式はLeftoverTimeを代入するだけです。Verseloop: # Add the TimePerRotation to the TotalTime. set TotalTime += TimePerRotation if: # If the TotalTime is greater than the MoveDuration, the final keyframe needs # to be shortened. This means making a fraction of a rotation. LeftoverTime := TotalTime - MoveDuration > 0.0どの程度の部分回転にする必要があるのかを知るには、新しい変数
RotationFractionを初期化し、TimePerRotationとLeftoverTimeの差分をTimePerRotationで除算した値に一致するように設定します。Verseif: # If the TotalTime is greater than the MoveDuration, the final keyframe needs # to be shortened. This means making a fraction of a rotation. LeftoverTime := TotalTime - MoveDuration > 0.0 # The fraction of a rotation to make. RotationFraction := (TimePerRotation - LeftoverTime)/TimePerRotation変更した回転を
RotationFractionから作成するには、Slerp[]を使用します。 これは、Lerp()の別バージョンであり、球面線形補間を処理し、同様のパラメータを取ります。 2 つの異なる回転から最短の回転を見つけ、線形補間パラメータに基づく回転を返します。Slerp[]を呼び出し、IdentityRotation()と、RotationToApplyによって回転したIdentityRotation()の間を、線形補間パラメータとしてRotationFractionを使用して補間します。 ここでIdentityRotation()を使用しているのは、どの程度の部分回転を適用する必要があるかということだけに関心があり、EndTransformでの回転が最終的にどこになるかには関心がないためです。Verseset TotalTime += TimePerRotation if: # If the TotalTime is greater than the MoveDuration, the final keyframe needs # to be shortened. This means making a fraction of a rotation. LeftoverTime := TotalTime - MoveDuration > 0.0 # The fraction of a rotation to make. RotationFraction := (TimePerRotation - LeftoverTime)/TimePerRotation # Make a modified fractional rotation by using Slerp(). The Slerp() function does spherical interpolationそれらの値を設定し、
RotationToApplyをModifiedRotationに設定し、AnimationTimeにRotationFractionを乗算して、アニメーションがどの程度短縮されるかを把握し、最後にTotalTimeをMoveDurationに設定します。これはEndTransformを計算するときに、それより大きくならないようにするためです。VerseModifiedRotation := Slerp[IdentityRotation(), IdentityRotation().RotateBy(RotationToApply), RotationFraction] then: # Set the RotationToApply to the modified rotation, and multiply the animation time by # the RotationFraction to get the modified animation time. set RotationToApply = ModifiedRotation set AnimationTime = AnimationTime * RotationFraction # Since the TotalTime should not go past the MoveDuration, # set TotalTime to MoveDuration. set TotalTime = MoveDuration
この関数の最後で、ループの後で、
Keyframes配列を返します。 完全なBuildMovingAnimationKeyframes()関数は次のようになります。Verse# Builds an array of keyframes that animate movement and rotation from the OriginalTransform to the TargetTransform. BuildMovingAnimationKeyframes(MoveDuration:float, RotationRate:float, AdditionalRotation:rotation, OriginalTransform:transform, TargetTransform:transform,MoveEaseType:move_to_ease_type, UseEasePerKeyframe:logic):[]keyframe_delta= # The array of keyframes to return. var Keyframes:[]keyframe_delta = array{} # The total amount of time spent animating. var TotalTime:float = 0.0 # The starting transform for building keyframes. This is theキーフレームを作成するロジックを定義したので、これからそれらをアニメートします。 個別の関数を使用して、アニメーションを作成し、呼び出します。 新しい関数
BuildAndPlayAnimation()をanimating_propクラスに追加します。 この関数に<suspends>モディファイヤを付加して、他の非同期関数を呼び出すことができるようにします。Verse# Builds an animation from an array of keyframes, then calls MoveToEase() # to animate the prop. BuildAndPlayAnimation()<suspends>:void=BuildAndPlayAnimation()内で、Keyframesという新しいkeyframe_delta配列を初期化します。 そして、Keyframesを、BuildMovingAnimationKeyframes()を呼び出した結果に設定します。RootProp.GetTransform()を開始トランスフォームとして使用します。これは、Move()呼び出しごとに小道具の位置が変わるためです。animation_mode変数をanimation_mode.OneShotに初期化し、Keyframes配列とAnimationModeを渡して、MoveToEase()を呼び出します。完全な
BuildAndPlayAnimation()関数は次のようになります。Verse# Builds an animation from an array of keyframes, then calls MoveToEase() # to animate the prop. BuildAndPlayAnimation()<suspends>:void= var Keyframes:[]keyframe_delta = array{} # Build the animation, using the RootProp as the target transform. set Keyframes = BuildMovingAnimationKeyframes(MoveDuration, RotationRate, AdditionalRotation, RootProp.GetTransform(), TargetTransform, MoveEaseType, UseEasePerKeyframe) # Set the animation mode to OneShot. var AnimationMode:animation_mode := animation_mode.OneShotMove()内に戻り、TargetTransformを移動ターゲット トランスフォームに設定した後で、BuildAndPlayAnimation()を呼び出します。Verse# Move to each target in the MoveTargets array. for: MoveTarget:MoveTargets do: # Set the TargetTransform to the MoveTarget if the # MoveTarget is set. Otherwise set it to the MoveTransform. if: MoveTarget.IsValid[] then: set TargetTransform = MoveTarget.GetTransform()
留意が必要な場合がもう 1 つあります。 移動ターゲットを何も設定しない場合に何が起きるでしょう。 この状況では、小道具はその場で回転を続け、新しい目的地に移動しません。 これに対応するには、Move() 関数の先頭に if 式を追加します。 その if 式内で、MoveTargets.Length = 0 であるかどうかをチェックし、ゼロであれば、TargetTransform をルート小道具のトランスフォームに設定します。 その後に、BuildAndPlayAnimation() を呼び出します。 こうすることで、移動ターゲットを設定しなかった場合でも、小道具は引き続きアニメートされます。 完全な Move() アニメーションは次のようになります。
# Move and rotate the RootProp toward the MoveTarget, or MoveTransform if one is set.
Move<override>()<suspends>:void=
# If there are no targets to move to, this prop will rotate in place.
if:
MoveTargets.Length = 0
then:
set TargetTransform = RootProp.GetTransform()
# Build and play the animation.
BuildAndPlayAnimation()
ここで、animating_prop を prop_animator クラスで参照する必要があります。 prop_animator 内で、MoveAndRotateProps という animating_prop の編集可能な配列を追加します。 OnBegin() 内のもう一方の for 式内で、Setup() を呼び出すことによって、MoveAndRotateProps の各小道具を初期化します。 完全な prop_animator クラスは次のようになります。
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
TranslatingPropsTip<localizes>:message = "The props that translate (move) using animation."
RotatingPropsTip<localizes>:message = "The props that rotate using animation."
ScalingPropsTip<localizes>:message = "The props that scale using animation."
AnimatingPropsTip<localizes>:message = "The props that both move and rotate using animation."
# Coordinates moving props through animation by calling each movable_prop's Setup() method.
コードを保存してコンパイルします。
おめでとうございます。すべてのコードが完成です。 これですべてをリンクすることができます。
作成した animating_prop クラスでは、小道具を移動、回転、スケールすることができます。 ただし、ManageMovement() などのいくつかの関数を継承する必要があるため、引き続き moveable_prop クラスに依存しています。 animating_prop クラスでは動きの 3 つのタイプすべてを行うことができるため、animating_prop をリファクタリングして、このクラスが単独で動作できるように、moveable_prop のすべてのロジックを含めると便利です。 次に示しているリファクタリングの例では、animating_prop と moveable_prop を単一ファイルにマージしています。 prop_animator Verse の仕掛けクラスも含めています。 このコードを実行するには、movement_behaviors の機能が引き続き必要ですが、このリファクタリングでは、必要とするファイルの数が 5 から 2 に減っています。 このコードは、「完全なコード」セクションにも記載されています。
using { /Fortnite.com/Devices }
using { /Fortnite.com/Devices/CreativeAnimation }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/SpatialMath }
EasingCategory<localizes>:message := "These control the type of movement easing applied to the prop."
LogicCategory<localizes>:message := "These control different aspects of the prop's logic."
PropsCategory<localizes>:message := "These are the props that move associated with this device."
RotationCategory<localizes>:message := "These control how the prop rotates."
TimingCategory<localizes>:message := "These control the timing of parts of the prop's movmement."
小道具を仕掛けに結び付ける
エディタに戻り、回転する小道具セクションで作成したコースのセクションを削除して、最終目標の前に割れ目を作り出します。 FG01 SpinningBar Double S と FG01 Hover Platform M をもう一つ、レベルに追加します。 それらを SpinningMovingBar と TranslatingPlatform という名前にし、FG01 Button Bulb 小道具をいくつか追加します。これらは、各小道具の移動先ターゲットになります。 これらを PlatformTarget という名前にします。 割れ目の上にプラットフォームとバーを配置し、プラットフォームの移動先とするターゲットを配置します。 この例では、スピンするバーが左右に動き、プラットフォームは前後に動きます。
スピンするバーと移動するプラットフォームのセットアップ。 矢印はそれぞれの小道具が移動する方向を示しています。 スピンするバーとプラットフォームはどちらも前後に動き、回転するバーは動くときにスピンします。
アウトライナー内で prop animator を選択します。 スピンするバーの AnimatingProps に配列要素を追加します。 それぞれの値を次のように設定します。
| オプション | 値 | 説明 |
|---|---|---|
Additional Rotation (追加の回転) | 90.0 | この小道具は毎回 90 度回転します |
Rotation Rate (回転率) | 1.5 | この小道具は |
Use Ease Per Keyframe (キーフレームごとのイージングを使用) | false | 小道具が一定の速度で移動および回転するように、キーフレームごとに線形イージング タイプを使用します |
MoveTargets | 2 要素、プラットフォーム ターゲットに割り当てられている | バーの移動先とするターゲットです |
RootProp | SpinningMovingBar | アニメートしている小道具です。 |
移動するプラットフォームの TranslatingProps に配列要素をもう一つ追加します。 MoveTargets をプラットフォーム ターゲットに割り当て、RootProp を TranslatingPlatform に割り当てます。
[Launch Session (セッションを開始)] をクリックして、完成した障害物コースを試走しましょう。
応用編
完成です。 これで Verse を使用して Fall Guys の独自の障害物コースを作成するすべてが揃いました。
ここに示したコードを使用して、自分の体験でクリエイティブの小道具をアニメートし、Fall Guys プロジェクトを超えるものも生み出すことができます。
ここで学習したことを活かして以下を試してみてください。
さまざまな方向に回転する障害物、またはキーフレームにわたってランダムに回転する障害物を作成します。
プレイヤーがその上に立つか一定の距離に近づいたときにのみ、アクティブ化される障害物を作成します。
一定時間が経過すると消えるプラットフォーム、またはプレイヤーが長く留まっていると危険な場所に移動させるプラットフォームを作成する方法を考え出します。
完全なコード
このセクションで作成した完全なコード、および animating_prop のリファクタリング例を以下に示します。
movable_prop.verse
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/SpatialMath }
MoveDurationTip<localizes>:message = "The amount of time the prop takes to move to its destination."
MoveEaseTypeTip<localizes>:message = "The animation easing applied to the movement."
MoveEndDelayTip<localizes>:message = "The delay after the movement finishes."
MoveOnceAndStopTip<localizes>:message = "Whether the RootProp should stop in place after it finishes moving."
MoveStartDelayTip<localizes>:message = "The delay before the movement starts."
MoveTargetsTip<localizes>:message = "The array of CreativeProp to move toward. These targets can be children of the RootProp."
translating_prop.verse
using { /Fortnite.com/Devices }
using { /Fortnite.com/Devices/CreativeAnimation }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/SpatialMath }
MovePositionTip<localizes>:message = "The optional position to move to World Space. Use this if you do not want to set a MoveTarget."
# A prop that moves (translates) toward either a Creative prop target
# or a position in world space.
translating_prop<public> := class<concrete>(movable_prop):
rotating_prop.verse
using { /Fortnite.com/Devices }
using { /Fortnite.com/Devices/CreativeAnimation }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/SpatialMath }
AdditionalRotationTip<localizes>:message = "The rotation to apply to the RootProp."
ShouldRotateForeverTip<localizes>:message = "Whether the RootProp should rotate forever."
MatchRotationTargetTip<localizes>:message = "The optional prop whose rotation the RootProp should rotate to. Use this if you do not want to set an Additional Rotation."
# A prop that rotates by an additional rotation or rotates to match
scaling_prop.verse
using { /Fortnite.com/Devices }
using { /Fortnite.com/Devices/CreativeAnimation }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/SpatialMath }
MatchScaleTargetTip<localizes>:message = "The optional position to move to World Space. Use this if you do not want to set a MoveTarget."
# A prop that scales toward either a given scale or a Creative prop's scale.
scaling_prop<public> := class<concrete>(movable_prop):
# The array of vector3 targets for the RootProp to scale to.
animating_prop.verse
using { /Fortnite.com/Devices }
using { /Fortnite.com/Devices/CreativeAnimation }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/SpatialMath }
RotationRateTip<localizes>:message := "The time it takes to make one AdditionalRotation in seconds."
UseEasePerKeyframeTip<localizes>:message := "Whether this prop should use the MoveEaseType for each keyframe. False will use the Linear ease type on each frame."
# A prop that translates, rotates, and scales to a destination using animation.
animating_prop<public> := class<concrete>(movable_prop):
movement_behaviors.verse
# This file stores functions common to animating Creative props using keyframes.
# It also defines the move_to_ease_type enum to help in building animations.
using { /Fortnite.com/Devices }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /Fortnite.com/Characters}
using { /Fortnite.com/Devices/CreativeAnimation }
# Represents the different movement easing types.
move_to_ease_type<public> := enum {Linear, Ease, EaseIn, EaseOut, EaseInOut}
prop_animator.verse
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
TranslatingPropsTip<localizes>:message = "The props that translate (move) using animation."
RotatingPropsTip<localizes>:message = "The props that rotate using animation."
ScalingPropsTip<localizes>:message = "The props that scale using animation."
MoveAndRotatePropsTip<localizes>:message = "The props that both move and rotate using animation."
# Coordinates moving props through animation by calling each moveable_prop's Setup() method.
animating_props.verse (animating_prop のリファクタリング例)
using { /Fortnite.com/Devices }
using { /Fortnite.com/Devices/CreativeAnimation }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/SpatialMath }
EasingCategory<localizes>:message := "These control the type of movement easing applied to the prop."
LogicCategory<localizes>:message := "These control different aspects of the prop's logic."
PropsCategory<localizes>:message := "These are the props that move associated with this device."
RotationCategory<localizes>:message := "These control how the prop rotates."
TimingCategory<localizes>:message := "These control the timing of parts of the prop's movmement."