【UE5】CPP中使用ControlRig蓝图节点示例

模板

需要.Build中添加编译要用到的模块

		PrivateDependencyModuleNames.AddRange(new string[]
		{
			"ControlRig", 
			"RigVM", 
			"AnimationCore"
		});

1774598536172

.h

#include "CoreMinimal.h"
#include "Units/Execution/RigUnit_DynamicHierarchy.h"
#include "ControlRig.h"
#include "Rigs/RigHierarchy.h"
#include "RigUnit_HybridAnim.generated.h"

#pragma region 初始化Array
	//初始化Array
	USTRUCT(meta = (DisplayName = "SetupArray"), Category = "ConstructionEvent")
struct HYBRIDANIM_API FRigUnit_SetupArray : public FRigUnit_DynamicHierarchyBaseMutable
	{
		GENERATED_BODY()

		RIGVM_METHOD()
		virtual void Execute() override;

		UPROPERTY(meta=(Output))
		TArray<FRigElementKey> FootArray;

	};
#pragma endregion

.cpp

// Fill out your copyright notice in the Description page of Project Settings.

#include "ControlRigFunctions/RigUnit_HybridAnim.h"


#pragma region 初始化Array
	//初始化Array
FRigUnit_SetupArray_Execute()
{

}
#pragma endregion

这种方式相当于建立一个controlrig的公开函数库,不需要controlrig蓝图继承

1785138816040

注意:

类型 Execute 引脚 典型用途
FRigUnit ❌ 无 纯数学计算(Add、Multiply、Lerp、SpringInterpolate 等),结果仅依赖输入,无内部状态
FRigUnitMutable ✅ 有 需要缓存状态的操作(执行顺序敏感、有中间变量需要跨帧保留)
FRigUnit_DynamicHierarchyBaseMutable ✅ 有 动态层级修改(添加/移除骨骼、修改层级结构),必须按序执行

ControlRig节点迁移到C++的基本流程

1774598530978

逻辑代码迁移到C++自定义ControlRig节点:

RigUnit_ProceduralCharacter.h

#pragma region 计算脚部的目标朝向
    //计算脚部的目标朝向
    USTRUCT(meta = (DisplayName = "GetFootTargetAngle"))
    struct PROCEDURALANIM_API FRigUnit_GetFootTargetAngle : public FRigUnit
    {
        GENERATED_BODY()

        RIGVM_METHOD()
        virtual void Execute() override;

        UPROPERTY(meta = (Input))
        FVector RigSpaceVelocity;
  
        UPROPERTY(meta = (Output))
        float FootTargetZAngle;

    };

    FVector EulerFromQuat(const FQuat& Rotation, EEulerRotationOrder RotationOrder = EEulerRotationOrder::ZYX, bool bUseUEHandyness = false);

    FQuat FromTwoVectors(const FVector& A, const FVector& B);

#pragma endregion

RigUnit_ProceduralCharacter.cpp

#pragma region 计算脚部的目标朝向
    FRigUnit_GetFootTargetAngle_Execute()
    {
        const float OriginalZAngle = AnimationCore::EulerFromQuat(
            FromTwoVectors(FVector(0,1,0),RigSpaceVelocity)
            ).Z;
        if (OriginalZAngle > 100)
        {
            FootTargetZAngle = OriginalZAngle - 180;
        }
        else if (OriginalZAngle < -100)
        {
            FootTargetZAngle = OriginalZAngle + 180;
        }
        else
        {
            FootTargetZAngle = OriginalZAngle;
        }
    }

    FQuat FromTwoVectors(const FVector& A, const FVector& B)
    {
        if (A.IsNearlyZero() || B.IsNearlyZero())
        {
            return FQuat::Identity;
        }
        return FRigVMMathLibrary::FindQuatBetweenVectors(A, B);
    }
#pragma endregion

1774598542118

对于一些蓝图和实际C++API名字不一致的节点

搜DisplayName="蓝图节点名"找对应的C++API

比如:Interpolate节点

1774598644513

1774598764221

如何在节点中获取Transform

	URigHierarchy* Hierarchy = ExecuteContext.Hierarchy;
	if(!Hierarchy)
	{
		return;
	}
	FRigElementKey HeadRig = FRigElementKey(TEXT("head"), ERigElementType::Bone);
	FTransform HeadTransform = Hierarchy->GetGlobalTransform(HeadRig);
posted @ 2026-03-27 16:05  EanoJiang  阅读(59)  评论(0)    收藏  举报