UE4 animation novice grave entry notes

Posted by noguru on Wed, 01 Dec 2021 13:36:40 +0100

UAnimInstance

Like UUserWidget and UMG, we can also use UAnimInstance with animation blueprint

UCLASS()
class SHOOTERGAME_API UShooterTPPAnimInstance : public UAnimInstance
{
	GENERATED_BODY()
protected:
	virtual void NativeUninitializeAnimation() override;
	
	virtual void NativeInitializeAnimation() override;
	
	virtual void NativeBeginPlay() override;

	virtual void NativeUpdateAnimation(float DeltaSeconds) override;
	
	virtual void NativePostEvaluateAnimation() override;
};

Here is a brief introduction to the life cycle of UAnimInstance during initialization

In the normal game flow

  • NativeUninitializeAnimation
  • NativeInitializeAnimation
  • NativeBeginPlay
  • After entering the game loop, the following two functions are called repeatedly
  • NativeUpdateAnimation
  • NativePostEvaluateAnimation

On the contrary, if only the compilation is successful or the animation is loaded, only the functions before BeginPlay will be executed

  • NativeUninitializeAnimation
  • NativeInitializeAnimation

If it is in the animation blueprint interface, it will enter the Tick loop. Note that BeginPlay will not be called at this time, and BeginPlay will only be called when the game process starts

  • NativeUpdateAnimation
  • NativePostEvaluateAnimation

So it seems that we can initialize some attributes in NativeInitializeAnimation(), and then update each frame in nativeupdatanimation()

Common nodes and attributes of animation blueprint

State Transition panel - Transition

  • Priority Order: the higher the value, the higher the priority. When multiple switching conditions are met at the same time, the Transition with high priority will be selected

  • Bidirectional: when checked, the Transition becomes bidirectional (sharing one condition?)

  • Blend Logic: when the SourcePose is a blend space, the SourcePose is likely to change when the Transition executes blend, resulting in confusion of the blend results

    • Standard Blend: Evaluate both SourcePose and TargetPose
    • Inertialization: inertial interpolation, Evaluate only TargetPose
  • Automatic Rule Based on Sequence Player in State: if checked, it means that the animation will be switched when the animation is played

State Transition panel - Blend Settings

  • Duration: mixing time for switching between states
  • Mode: blend the curves used. For details, press Ctrl+Alt to view the curve function image
  • Custom Blend Curve: Custom Blend Curve
  • Blend Profile: blending configuration. In the configuration, you can specify the weight of bones during blending. The greater the weight, the faster the change during blending

State Transition condition common nodes

  • CurrentTime
  • CurrentStateTime
  • GetRelevantAnimTimeRemaining
  • GetRelevantAnimTime
  • StateWeight

Coordinate system in UE4

UE4 is a left-handed coordinate system. Forward is X, up is Z, right is Y

  • Rotating around the X axis is called Roll. (crooked head) the value of the right crooked head becomes larger and the value of the left crooked head becomes smaller
  • Rotating around the Y axis is called Pitch, and pitching (nodding) in which the head up value becomes larger and the head down value becomes smaller
  • Rotating around the Z axis is called Yaw, and the Yaw angle (turning head) becomes larger when turning to the right and smaller when turning to the left

In UE4 Editor, X represents Roll, Y represents Pitch and Z represents Yaw in Rotation, corresponding to the above

In the FRotator constructor of C + +, you must pay attention to the construction order. Unlike the editor panel, the constructor order can be regarded as Y-Z-X

/**
* Constructor.
*
* @param InPitch Pitch in degrees.
* @param InYaw Yaw in degrees.
* @param InRoll Roll in degrees.
*/
FORCEINLINE FRotator(float InPitch, float InYaw, float InRoll);

Footstep IK

It can be seen from the figure that by subtracting the distance of the ray hitting the obstacle from the 1 / 4 height of the person's collision body, the value that the foot needs to be raised can be obtained. Applying this value to the IK node can achieve the effect of lifting the foot

However, in general, because the collision body of the character capsule is relatively large, the character will be in the air of the steps, making one foot hanging in the air. At this time, we can compare the height of the left and right feet to be lifted, select an absolute maximum value as the BodyOffSet, and then let the character's overall bones fall by a BodyOffSet. The situation is the same as above

Finally, if the character is on an inclined plane, it is necessary to calculate the slope of the inclined plane, and then quote it to the rotation of the foot. As shown in the figure, decompose the normal vector of the inclined plane, and then obtain its distance in the X and Z directions. At this time, conduct an arctan calculation to obtain the included angle (x / z = tan) θ)

Here, the arctangent is used to calculate the angle, but for the positive direction of the X axis, the positive and negative rotation angles need to be calculated. Here, assuming that the character looks at the positive direction of the X axis, it means that the foot needs to look down, so it is a negative angle

However, in 3D games, it is not enough to calculate Pitch only for the inclined plane. Roll also needs to be calculated. Similarly, there is the following figure. At this time, the X-axis direction faces the screen inward, and the forward direction of the character also faces the screen inward. In order to fit the ground, the character's feet need to tilt their heads to the left. The angle of tilting their heads to the left should be negative, but because the value in the - y direction is obtained after the decomposition of normal in the figure, so When negative is positive, the rotation angle is positive

So we can write such C + + code

float UShooterTPPAnimInstance::FootIKTrace(FName SocketName, float TraceDistance, FRotator& OutIKRotator)
{
	const FVector SocketLocation = OwnerCharacter->GetMesh()->GetSocketLocation(SocketName);
	FHitResult IKResult;
	const float HalfHeight = OwnerCharacter->GetCapsuleComponent()->GetScaledCapsuleHalfHeight();
	const float StartZ = OwnerCharacter->GetActorLocation().Z - HalfHeight / 2;
	const float EndZ = OwnerCharacter->GetActorLocation().Z - HalfHeight - TraceDistance;
	const FVector StartLocation(SocketLocation.X, SocketLocation.Y, StartZ);
	const FVector EndLocation(SocketLocation.X, SocketLocation.Y, EndZ);
	FCollisionObjectQueryParams ObjectQueryParams;
	ObjectQueryParams.AddObjectTypesToQuery(ECC_WorldStatic);

	FCollisionQueryParams QueryParams;
	QueryParams.bTraceComplex = true;
	if (!GetWorld()->LineTraceSingleByObjectType(IKResult, StartLocation, EndLocation, ObjectQueryParams, QueryParams))
	{
		OutIKRotator = FRotator::ZeroRotator;
		return 0;
	}

	// Radian rotation angle
	const float Pitch = FMath::RadiansToDegrees(-FMath::Atan2(IKResult.Normal.X, IKResult.Normal.Z));
	const float Row = FMath::RadiansToDegrees(FMath::Atan2(IKResult.Normal.Y, IKResult.Normal.Z));
	OutIKRotator = FRotator(Pitch, 0, Row);
	
	return HalfHeight / 2 - IKResult.Distance;
}

Because the bones of the left and right feet are oriented, you need to reverse the position of the right foot in the final result

// Distance to be lifted up
const float RightFootMoveUpDistance = FootIKTrace(RightFootBoneName, FootTraceDistance, LeftFootIKRotator);
const float LeftFootMoveUpDistance = FootIKTrace(LeftFootBoneName, FootTraceDistance, RightFootIKRotator);
BodyOffSet = FVector(0, 0, FMath::Min(RightFootMoveUpDistance, LeftFootMoveUpDistance));


RightFootIKLocation = FVector((RightFootMoveUpDistance - BodyOffSet.Z) * -1, 0, 0);
LeftFootIKLocation = FVector(LeftFootMoveUpDistance - BodyOffSet.Z, 0, 0);

Finally, the data is applied to the IK node

Footstep IK: the effect takes its own bone space as the reference system, and the Joint takes the parent node as the reference system

Footstep Rotation: in the above, Rotation is calculated in the world coordinate system, so Rotation Space selects World Space and applies it to the footstep in the form of superposition

Stop convergence optimization

The excellent one is not very standardized. It will be next time

Topics: UE4