You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
This represents UE4/Main @ 16261013 and Dev-PerfTest @ 16259937 [CL 16306996 by aurel cordonnier in ue5-main branch]
478 lines
20 KiB
C++
478 lines
20 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "BoneControllers/AnimNode_SkeletalControlBase.h"
|
|
#include "Components/SkeletalMeshComponent.h"
|
|
#include "Physics/ImmediatePhysics/ImmediatePhysicsDeclares.h"
|
|
#include "PhysicsProxy/PerSolverFieldSystem.h"
|
|
#include "AnimNode_RigidBody.generated.h"
|
|
|
|
struct FBodyInstance;
|
|
struct FConstraintInstance;
|
|
class FEvent;
|
|
|
|
extern ANIMGRAPHRUNTIME_API TAutoConsoleVariable<int32> CVarEnableRigidBodyNode;
|
|
extern ANIMGRAPHRUNTIME_API TAutoConsoleVariable<int32> CVarEnableRigidBodyNodeSimulation;
|
|
extern ANIMGRAPHRUNTIME_API TAutoConsoleVariable<int32> CVarRigidBodyLODThreshold;
|
|
|
|
/** Determines in what space the simulation should run */
|
|
UENUM()
|
|
enum class ESimulationSpace : uint8
|
|
{
|
|
/** Simulate in component space. Moving the entire skeletal mesh will have no affect on velocities */
|
|
ComponentSpace,
|
|
/** Simulate in world space. Moving the skeletal mesh will generate velocity changes */
|
|
WorldSpace,
|
|
/** Simulate in another bone space. Moving the entire skeletal mesh and individually modifying the base bone will have no affect on velocities */
|
|
BaseBoneSpace,
|
|
};
|
|
|
|
|
|
/**
|
|
* Settings for the system which passes motion of the simulation's space into the simulation. This allows the simulation to pass a
|
|
* fraction of the world space motion onto the bodies which allows Bone-Space and Component-Space simulations to react to world-space
|
|
* movement in a controllable way.
|
|
*/
|
|
USTRUCT(BlueprintType)
|
|
struct ANIMGRAPHRUNTIME_API FSimSpaceSettings
|
|
{
|
|
GENERATED_USTRUCT_BODY()
|
|
|
|
FSimSpaceSettings();
|
|
|
|
// Global multipler on the effects of simulation space movement. Must be in range [0, 1]. If MasterAlpha = 0.0, the system is disabled and the simulation will
|
|
// be fully local (i.e., world-space actor movement and rotation does not affect the simulation). When MasterAlpha = 1.0 the simulation effectively acts as a
|
|
// world-space sim, but with the ability to apply limits using the other parameters.
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Settings, meta = (ClampMin = "0.0", ClampMax = "1.0"))
|
|
float MasterAlpha;
|
|
|
|
// Multiplier on the Z-component of velocity and acceleration that is passed to the simulation. Usually from 0.0 to 1.0 to
|
|
// reduce the effects of jumping and crouching on the simulation, but it can be higher than 1.0 if you need to exaggerate this motion for some reason.
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Settings, meta = (ClampMin = "0.0"))
|
|
float VelocityScaleZ;
|
|
|
|
// A clamp on the effective world-space velocity that is passed to the simulation. Units are cm/s. The default value effectively means "unlimited". It is not usually required to
|
|
// change this but you would reduce this to limit the effects of drag on the bodies in the simulation (if you have bodies that have LinearDrag set to non-zero in the physics asset).
|
|
// Expected values in this case would be somewhat less than the usual velocities of your object which is commonly a few hundred for a character.
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Settings, meta = (ClampMin = "0.0"))
|
|
float MaxLinearVelocity;
|
|
|
|
// A clamp on the effective world-space angular velocity that is passed to the simulation. Units are radian/s, so a value of about 6.0 is one rotation per second.
|
|
// The default value effectively means "unlimited". You would reduce this (and MaxAngularAcceleration) to limit how much bodies "fly out" when the actor spins on the spot.
|
|
// This is especially useful if you have characters than can rotate very quickly and you would probably want values around or less than 10 in this case.
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Settings, meta = (ClampMin = "0.0"))
|
|
float MaxAngularVelocity;
|
|
|
|
// A clamp on the effective world-space acceleration that is passed to the simulation. Units are cm/s/s. The default value effectively means "unlimited".
|
|
// This property is used to stop the bodies of the simulation flying out when suddenly changing linear speed. It is useful when you have characters than can
|
|
// changes from stationary to running very quickly such as in an FPS. A common value for a character might be in the few hundreds.
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Settings, meta = (ClampMin = "0.0"))
|
|
float MaxLinearAcceleration;
|
|
|
|
// A clamp on the effective world-space angular accleration that is passed to the simulation. Units are radian/s/s. The default value effectively means "unlimited".
|
|
// This has a similar effect to MaxAngularVelocity, except that it is related to the flying out of bodies when the rotation speed suddenly changes. Typical limist for
|
|
// a character might be around 100.
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Settings, meta = (ClampMin = "0.0"))
|
|
float MaxAngularAcceleration;
|
|
|
|
UPROPERTY(meta = (DeprecatedProperty, DeprecationMessage = "ExternalLinearDrag is deprecated. Please use ExternalLinearDragV instead."))
|
|
float ExternalLinearDrag_DEPRECATED;
|
|
|
|
// Additional linear drag applied to every body in addition to linear drag specified on them in the physics asset.
|
|
// When combined with ExternalLinearVelocity, this can be used to add a temporary wind-blown effect without having to tune linear drag on
|
|
// all the bodies in the physics asset. The result is that each body has a force equal to -ExternalLinearDragV * ExternalLinearVelocity applied to it, in
|
|
// additional to all other forces. The vector is in simulation local space.
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Settings)
|
|
FVector ExternalLinearDragV;
|
|
|
|
// Additional velocity that is added to the component velocity so the simulation acts as if the actor is moving at speed, even when stationary.
|
|
// Vector is in world space. Units are cm/s. Could be used for a wind effects etc. Typical values are similar to the velocity of the object or effect,
|
|
// and usually around or less than 1000 for characters/wind.
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Settings)
|
|
FVector ExternalLinearVelocity;
|
|
|
|
// Additional angular velocity that is added to the component angular velocity. This can be used to make the simulation act as if the actor is rotating
|
|
// even when it is not. E.g., to apply physics to a character on a podium as the camera rotates around it, to emulate the podium itself rotating.
|
|
// Vector is in world space. Units are rad/s.
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Settings)
|
|
FVector ExternalAngularVelocity;
|
|
|
|
void PostSerialize(const FArchive& Ar);
|
|
};
|
|
|
|
#if WITH_EDITORONLY_DATA
|
|
template<>
|
|
struct TStructOpsTypeTraits<FSimSpaceSettings> : public TStructOpsTypeTraitsBase2<FSimSpaceSettings>
|
|
{
|
|
enum
|
|
{
|
|
WithPostSerialize = true
|
|
};
|
|
};
|
|
#endif
|
|
|
|
|
|
/**
|
|
* Controller that simulates physics based on the physics asset of the skeletal mesh component
|
|
*/
|
|
USTRUCT()
|
|
struct ANIMGRAPHRUNTIME_API FAnimNode_RigidBody : public FAnimNode_SkeletalControlBase
|
|
{
|
|
GENERATED_USTRUCT_BODY()
|
|
|
|
FAnimNode_RigidBody();
|
|
~FAnimNode_RigidBody();
|
|
|
|
// FAnimNode_Base interface
|
|
virtual void GatherDebugData(FNodeDebugData& DebugData) override;
|
|
// End of FAnimNode_Base interface
|
|
|
|
// FAnimNode_SkeletalControlBase interface
|
|
virtual void UpdateComponentPose_AnyThread(const FAnimationUpdateContext& Context) override;
|
|
virtual void EvaluateComponentPose_AnyThread(FComponentSpacePoseContext& Output) override;
|
|
virtual void EvaluateSkeletalControl_AnyThread(FComponentSpacePoseContext& Output, TArray<FBoneTransform>& OutBoneTransforms) override;
|
|
virtual void OnInitializeAnimInstance(const FAnimInstanceProxy* InProxy, const UAnimInstance* InAnimInstance) override;
|
|
virtual bool NeedsOnInitializeAnimInstance() const override { return true; }
|
|
virtual void PreUpdate(const UAnimInstance* InAnimInstance) override;
|
|
virtual void UpdateInternal(const FAnimationUpdateContext& Context) override;
|
|
virtual bool HasPreUpdate() const override { return true; }
|
|
virtual bool IsValidToEvaluate(const USkeleton* Skeleton, const FBoneContainer& RequiredBones) override;
|
|
virtual bool NeedsDynamicReset() const override;
|
|
virtual void ResetDynamics(ETeleportType InTeleportType) override;
|
|
virtual int32 GetLODThreshold() const override;
|
|
// End of FAnimNode_SkeletalControlBase interface
|
|
|
|
virtual void AddImpulseAtLocation(FVector Impulse, FVector Location, FName BoneName = NAME_None);
|
|
|
|
// TEMP: Exposed for use in PhAt as a quick way to get drag handles working with Chaos
|
|
virtual ImmediatePhysics::FSimulation* GetSimulation() { return PhysicsSimulation; }
|
|
|
|
public:
|
|
/** Physics asset to use. If empty use the skeletal mesh's default physics asset */
|
|
UPROPERTY(EditAnywhere, Category = Settings)
|
|
TObjectPtr<UPhysicsAsset> OverridePhysicsAsset;
|
|
|
|
private:
|
|
FTransform PreviousCompWorldSpaceTM;
|
|
FTransform CurrentTransform;
|
|
FTransform PreviousTransform;
|
|
|
|
UPhysicsAsset* UsePhysicsAsset;
|
|
public:
|
|
/** Override gravity*/
|
|
UPROPERTY(EditAnywhere, Category = Settings, meta = (PinHiddenByDefault, editcondition = "bOverrideWorldGravity"))
|
|
FVector OverrideWorldGravity;
|
|
|
|
/** Applies a uniform external force in world space. This allows for easily faking inertia of movement while still simulating in component space for example */
|
|
UPROPERTY(EditAnywhere, Category = Settings, meta = (PinShownByDefault))
|
|
FVector ExternalForce;
|
|
|
|
/** When using non-world-space sim, this controls how much of the components world-space acceleration is passed on to the local-space simulation. */
|
|
UPROPERTY(EditAnywhere, Category = Settings, meta = (PinHiddenByDefault))
|
|
FVector ComponentLinearAccScale;
|
|
|
|
/** When using non-world-space sim, this applies a 'drag' to the bodies in the local space simulation, based on the components world-space velocity. */
|
|
UPROPERTY(EditAnywhere, Category = Settings, meta = (PinHiddenByDefault))
|
|
FVector ComponentLinearVelScale;
|
|
|
|
/** When using non-world-space sim, this is an overall clamp on acceleration derived from ComponentLinearAccScale and ComponentLinearVelScale, to ensure it is not too large. */
|
|
UPROPERTY(EditAnywhere, Category = Settings)
|
|
FVector ComponentAppliedLinearAccClamp;
|
|
|
|
/**
|
|
* Settings for the system which passes motion of the simulation's space
|
|
* into the simulation. This allows the simulation to pass a
|
|
* fraction of the world space motion onto the bodies which allows Bone-Space
|
|
* and Component-Space simulations to react to world-space movement in a
|
|
* controllable way.
|
|
* This system is a superset of the functionality provided by ComponentLinearAccScale,
|
|
* ComponentLinearVelScale, and ComponentAppliedLinearAccClamp. In general
|
|
* you should not have both systems enabled.
|
|
*/
|
|
UPROPERTY(EditAnywhere, Category = Settings, meta = (PinHiddenByDefault))
|
|
FSimSpaceSettings SimSpaceSettings;
|
|
|
|
|
|
/**
|
|
* Scale of cached bounds (vs. actual bounds).
|
|
* Increasing this may improve performance, but overlaps may not work as well.
|
|
* (A value of 1.0 effectively disables cached bounds).
|
|
*/
|
|
UPROPERTY(EditAnywhere, Category = Settings, meta = (ClampMin="1.0", ClampMax="2.0"))
|
|
float CachedBoundsScale;
|
|
|
|
/** Matters if SimulationSpace is BaseBone */
|
|
UPROPERTY(EditAnywhere, Category = Settings)
|
|
FBoneReference BaseBoneRef;
|
|
|
|
/** The channel we use to find static geometry to collide with */
|
|
UPROPERTY(EditAnywhere, Category = Settings, meta = (editcondition = "bEnableWorldGeometry"))
|
|
TEnumAsByte<ECollisionChannel> OverlapChannel;
|
|
|
|
/** What space to simulate the bodies in. This affects how velocities are generated */
|
|
UPROPERTY(EditAnywhere, Category = Settings)
|
|
ESimulationSpace SimulationSpace;
|
|
|
|
/** Whether to allow collisions between two bodies joined by a constraint */
|
|
UPROPERTY(EditAnywhere, Category = Settings)
|
|
bool bForceDisableCollisionBetweenConstraintBodies;
|
|
|
|
|
|
private:
|
|
ETeleportType ResetSimulatedTeleportType;
|
|
|
|
public:
|
|
UPROPERTY(EditAnywhere, Category = Settings, meta = (InlineEditConditionToggle))
|
|
uint8 bEnableWorldGeometry : 1;
|
|
|
|
UPROPERTY(EditAnywhere, Category = Settings, meta = (InlineEditConditionToggle))
|
|
uint8 bOverrideWorldGravity : 1;
|
|
|
|
/**
|
|
When simulation starts, transfer previous bone velocities (from animation)
|
|
to make transition into simulation seamless.
|
|
*/
|
|
UPROPERTY(EditAnywhere, Category = Settings, meta=(PinHiddenByDefault))
|
|
uint8 bTransferBoneVelocities : 1;
|
|
|
|
/**
|
|
When simulation starts, freeze incoming pose.
|
|
This is useful for ragdolls, when we want the simulation to take over.
|
|
It prevents non simulated bones from animating.
|
|
*/
|
|
UPROPERTY(EditAnywhere, Category = Settings)
|
|
uint8 bFreezeIncomingPoseOnStart : 1;
|
|
|
|
/**
|
|
Correct for linear tearing on bodies with all axes Locked.
|
|
This only works if all axes linear translation are locked
|
|
*/
|
|
UPROPERTY(EditAnywhere, Category = Settings)
|
|
uint8 bClampLinearTranslationLimitToRefPose : 1;
|
|
|
|
/**
|
|
For world-space simulations, if the magnitude of the component's 3D scale is less than WorldSpaceMinimumScale, do not update the node.
|
|
*/
|
|
UPROPERTY(EditAnywhere, Category = Settings)
|
|
float WorldSpaceMinimumScale;
|
|
|
|
/**
|
|
If the node is not evaluated for this amount of time (seconds), either because a lower LOD was in use for a while or the component was
|
|
not visible, reset the simulation to the default pose on the next evaluation. Set to 0 to disable time-based reset.
|
|
*/
|
|
UPROPERTY(EditAnywhere, Category = Settings)
|
|
float EvaluationResetTime;
|
|
|
|
private:
|
|
uint8 bEnabled : 1;
|
|
uint8 bSimulationStarted : 1;
|
|
uint8 bCheckForBodyTransformInit : 1;
|
|
|
|
public:
|
|
void PostSerialize(const FArchive& Ar);
|
|
|
|
private:
|
|
|
|
#if WITH_EDITORONLY_DATA
|
|
UPROPERTY()
|
|
bool bComponentSpaceSimulation_DEPRECATED; //use SimulationSpace
|
|
#endif
|
|
|
|
// FAnimNode_SkeletalControlBase interface
|
|
virtual void InitializeBoneReferences(const FBoneContainer& RequiredBones) override;
|
|
// End of FAnimNode_SkeletalControlBase interface
|
|
|
|
void InitPhysics(const UAnimInstance* InAnimInstance);
|
|
void UpdateWorldGeometry(const UWorld& World, const USkeletalMeshComponent& SKC);
|
|
void UpdateWorldForces(const FTransform& ComponentToWorld, const FTransform& RootBoneTM, const float DeltaSeconds);
|
|
|
|
void InitializeNewBodyTransformsDuringSimulation(FComponentSpacePoseContext& Output, const FTransform& ComponentTransform, const FTransform& BaseBoneTM);
|
|
|
|
void InitSimulationSpace(
|
|
const FTransform& ComponentToWorld,
|
|
const FTransform& BoneToComponent);
|
|
|
|
// Calculate simulation space transform, velocity etc to pass into the solver
|
|
void CalculateSimulationSpace(
|
|
ESimulationSpace Space,
|
|
const FTransform& ComponentToWorld,
|
|
const FTransform& BoneToComponent,
|
|
const float Dt,
|
|
const FSimSpaceSettings& Settings,
|
|
FTransform& SpaceTransform,
|
|
FVector& SpaceLinearVel,
|
|
FVector& SpaceAngularVel,
|
|
FVector& SpaceLinearAcc,
|
|
FVector& SpaceAngularAcc);
|
|
|
|
// Gather nearby world objects and add them to the sim
|
|
void CollectWorldObjects();
|
|
|
|
// Flag invalid world objects to be removed from the sim
|
|
void ExpireWorldObjects();
|
|
|
|
// Remove simulation objects that are flagged as expired
|
|
void PurgeExpiredWorldObjects();
|
|
|
|
// Update sim-space transforms of world objects
|
|
void UpdateWorldObjects(const FTransform& SpaceTransform);
|
|
|
|
// Advances the simulation by a given timestep
|
|
void RunPhysicsSimulation(float DeltaSeconds, const FVector& SimSpaceGravity);
|
|
|
|
// Waits for the deferred simulation task to complete if it's not already finished
|
|
void FlushDeferredSimulationTask();
|
|
|
|
// Destroy the simulation and free related structures
|
|
void DestroyPhysicsSimulation();
|
|
|
|
private:
|
|
|
|
float WorldTimeSeconds;
|
|
float LastEvalTimeSeconds;
|
|
|
|
float AccumulatedDeltaTime;
|
|
float AnimPhysicsMinDeltaTime;
|
|
bool bSimulateAnimPhysicsAfterReset;
|
|
/** This should only be used for removing the delegate during termination. Do NOT use this for any per frame work */
|
|
TWeakObjectPtr<USkeletalMeshComponent> SkelMeshCompWeakPtr;
|
|
|
|
ImmediatePhysics::FSimulation* PhysicsSimulation;
|
|
FSolverIterations SolverIterations;
|
|
|
|
friend class FRigidBodyNodeSimulationTask;
|
|
struct FSimulationTaskState
|
|
{
|
|
FSimulationTaskState()
|
|
: SimulationCompletionEvent(nullptr)
|
|
, bSimulationPending(false)
|
|
{
|
|
}
|
|
|
|
// We must explicitly declare the assignment operator due to the atomic, but we must never assign to or from a state with a live simulation
|
|
FORCEINLINE FSimulationTaskState& operator=(const FSimulationTaskState& Other)
|
|
{
|
|
check((SimulationCompletionEvent == nullptr) && (Other.SimulationCompletionEvent == nullptr));
|
|
return(*this);
|
|
}
|
|
|
|
FEvent* SimulationCompletionEvent;
|
|
std::atomic<bool> bSimulationPending;
|
|
};
|
|
FSimulationTaskState SimulationTaskState;
|
|
|
|
struct FOutputBoneData
|
|
{
|
|
FOutputBoneData()
|
|
: CompactPoseBoneIndex(INDEX_NONE)
|
|
{}
|
|
|
|
TArray<FCompactPoseBoneIndex> BoneIndicesToParentBody;
|
|
FCompactPoseBoneIndex CompactPoseBoneIndex;
|
|
int32 BodyIndex;
|
|
int32 ParentBodyIndex;
|
|
};
|
|
|
|
struct FBodyAnimData
|
|
{
|
|
FBodyAnimData()
|
|
: TransferedBoneAngularVelocity(ForceInit)
|
|
, TransferedBoneLinearVelocity(ForceInitToZero)
|
|
, LinearXMotion(ELinearConstraintMotion::LCM_Locked)
|
|
, LinearYMotion(ELinearConstraintMotion::LCM_Locked)
|
|
, LinearZMotion(ELinearConstraintMotion::LCM_Locked)
|
|
, LinearLimit(0.0f)
|
|
, RefPoseLength (0.f)
|
|
, bIsSimulated(false)
|
|
, bBodyTransformInitialized(false)
|
|
{}
|
|
|
|
FQuat TransferedBoneAngularVelocity;
|
|
FVector TransferedBoneLinearVelocity;
|
|
|
|
ELinearConstraintMotion LinearXMotion;
|
|
ELinearConstraintMotion LinearYMotion;
|
|
ELinearConstraintMotion LinearZMotion;
|
|
float LinearLimit;
|
|
// we don't use linear limit but use default length to limit the bodies
|
|
// linear limits are defined per constraint - it can be any two joints that can limit
|
|
// this is just default length of the local space from parent, and we use that info to limit
|
|
// the translation
|
|
float RefPoseLength;
|
|
|
|
bool bIsSimulated : 1;
|
|
bool bBodyTransformInitialized : 1;
|
|
};
|
|
|
|
struct FWorldObject
|
|
{
|
|
FWorldObject() : ActorHandle(nullptr), LastSeenTick(0), bExpired(false) {}
|
|
FWorldObject(ImmediatePhysics::FActorHandle* InActorHandle, int32 InLastSeenTick) : ActorHandle(InActorHandle), LastSeenTick(InLastSeenTick), bExpired(false) {}
|
|
|
|
ImmediatePhysics::FActorHandle* ActorHandle;
|
|
int32 LastSeenTick;
|
|
bool bExpired;
|
|
};
|
|
|
|
TArray<FOutputBoneData> OutputBoneData;
|
|
TArray<ImmediatePhysics::FActorHandle*> Bodies;
|
|
TArray<int32> SkeletonBoneIndexToBodyIndex;
|
|
TArray<FBodyAnimData> BodyAnimData;
|
|
|
|
TArray<FPhysicsConstraintHandle*> Constraints;
|
|
TArray<USkeletalMeshComponent::FPendingRadialForces> PendingRadialForces;
|
|
|
|
FPerSolverFieldSystem PerSolverField;
|
|
|
|
TMap<const UPrimitiveComponent*, FWorldObject> ComponentsInSim;
|
|
int32 ComponentsInSimTick;
|
|
|
|
FVector WorldSpaceGravity;
|
|
|
|
float TotalMass;
|
|
|
|
// Bounds used to gather world objects copied into the simulation
|
|
FSphere CachedBounds;
|
|
|
|
FCollisionQueryParams QueryParams;
|
|
|
|
FPhysScene* PhysScene;
|
|
|
|
// Used by CollectWorldObjects and UpdateWorldGeometry in Task Thread
|
|
// Typically, World should never be accessed off the Game Thread.
|
|
// However, since we're just doing overlaps this should be OK.
|
|
const UWorld* UnsafeWorld;
|
|
|
|
// Used by CollectWorldObjects and UpdateWorldGeometry in Task Thread
|
|
// Only used for a pointer comparison.
|
|
const AActor* UnsafeOwner;
|
|
|
|
FBoneContainer CapturedBoneVelocityBoneContainer;
|
|
FCSPose<FCompactHeapPose> CapturedBoneVelocityPose;
|
|
FCSPose<FCompactHeapPose> CapturedFrozenPose;
|
|
FBlendedHeapCurve CapturedFrozenCurves;
|
|
|
|
FVector PreviousComponentLinearVelocity;
|
|
|
|
// Used by the world-space to simulation-space motion transfer system in Component- or Bone-Space sims
|
|
FTransform SimSpacePreviousComponentToWorld;
|
|
FTransform SimSpacePreviousBoneToComponent;
|
|
FVector SimSpacePreviousComponentLinearVelocity;
|
|
FVector SimSpacePreviousComponentAngularVelocity;
|
|
FVector SimSpacePreviousBoneLinearVelocity;
|
|
FVector SimSpacePreviousBoneAngularVelocity;
|
|
};
|
|
|
|
#if WITH_EDITORONLY_DATA
|
|
template<>
|
|
struct TStructOpsTypeTraits<FAnimNode_RigidBody> : public TStructOpsTypeTraitsBase2<FAnimNode_RigidBody>
|
|
{
|
|
enum
|
|
{
|
|
WithPostSerialize = true,
|
|
};
|
|
};
|
|
#endif
|
|
|