Control Rig中的Python脚本

使用Python脚本,扩展并自定义Control Rig的功能。

Choose your operating system:

Windows

macOS

Linux

Control Rig中的Python脚本功能能让你将工作流程自动化,并创建可用于绑定流程的工具。你还可以使用 Control Rig Python日志(Control Rig Python Log) 对命令进行逆向工程,复制脚本以便共享到其他项目。

本文介绍了Control Rig的Python脚本功能、Control Rig Python Log功能,以及一些脚本示例。

先决条件

脚本编写概述

Python主要用于在Control Rig中与Rig图表(Rig Graph)进行交互,Rig图表包含多个模块:

模块名称

说明

ControlRig

包含Rig运行时。

ControlRigDeveloper

包含更改Rig的所有功能。

ControlRigEditor

包含前端和用户界面逻辑。

Control Rig图表使用 模型(Model) - 视图(View) - 控制器(Controller) 设计模式实现。模型层就是图表本身,其中使用了以下术语:

Control Rig Python术语

说明

RigUnit

为Rig定义函数的C++结构体(示例:FRigUnit_GetBoneTransform)。

引脚(Pin)

函数的单个输入或输出。

链接(Link)

两个引脚之间的连接。

节点(Node)

RigUnit的视觉效果表示。

图表(Graph)

定向图表,包含Rig中所有节点和链接。

PinPath

描述图表中引脚地址的字符串(示例:NodeA.Translation.X)。

控制器(Controller)

用于在图表中做出更改的对象。

RigElementKey

从骨骼(Bone)、控制点(Control)、空(Null)或曲线(Curve)中选择。

骨骼(Bone)

骨架中用于变形的Rig元素。

控制点(Control)

用于交互的Rig元素。

空(Null)

用于中间变换的Rig元素。

曲线(Curve)

用于存储浮点通道的Rig元素。

形状(Shape)

视口中控制点的视觉效果表示。

层级(Hierarchy)

用于存储Rig中所有骨骼、控制点、空和曲线的容器。

HierarchyController

与控制器类似,HierarchyController用于更改层级。

编译器(Compiler)

将Control Rig图表转换为高性能运行时的对象。

VM

用于执行Rig的虚拟机运行时。

常量(Constant)

运行时不会更改的值。

参数(Parameter)

可以用作Rig输入或输出的值

变量(Variable)

可以在运行时更改并在Rig执行后保留的值。

ControlRigBlueprint

包含图表(Graph)、控制器(Controller)、编译器(Compiler)和VM的资产。

工厂(Factory)

负责创建和导入新对象的对象。在整个虚幻编辑器中用于创建资产。

Python通过 Python编辑器脚本插件(Python Editor Script Plugin) 启用,它本身在虚幻引擎中默认启用。当启用 Control Rig插件(Control Rig Plugin) 时,该插件也会自动启用,因为它是依赖项。

访问Control Rig

编写脚本的第一步是访问你将与之交互的主要对象,此处为 ControlRigBlueprint 对象。你有几种访问方法,但是你的第一个命令通常是加载ControlRigDeveloper模块,以便更改Control Rig。

  unreal.load_module('ControlRigDeveloper')

要访问现有Rig,请使用以下示例命令加载资产:

  rig = unreal.load_object(name = '/Game/ControlRig/Samples/Mannequin_ControlRig', outer = None)

你还可以使用以下内容加载当前打开的Control Rig资产:

  rigs = unreal.ControlRigBlueprint.get_currently_open_rig_blueprints()

使用以下内容新建Control Rig资产:

  factory = unreal.ControlRigBlueprintFactory()
  rig = factory.create_new_control_rig_asset(desired_package_path = '/Game/TestRig')

最后,你可以使用以下示例代码基于骨架或骨骼网格体创建Control Rig资产:

  # load a skeletal mesh
  mesh = unreal.load_object(name = '/Game/Mannequin/Character/Mesh/SK_Mannequin.SK_Mannequin', outer = None)
  # create a control rig for the mesh
  factory = unreal.ControlRigBlueprintFactory
  rig = factory.create_control_rig_from_skeletal_mesh_or_skeleton(selected_object = mesh)

Python日志

Python日志(Python Log) 提供了你在Control Rig编辑器中执行的所有操作的文本日志。其中包括视口、层级和图表中的操作。你可以使用它引用要在Python脚本中使用的命令。

要访问日志,请从Control Rig主菜单中,点击 窗口(Window)>消息日志(Message Log),然后从消息日志(Message Log)侧边栏中选择 Control Rig Python日志(Control Rig Python Log)

control rig python log

你现在可以在Rig图表中执行操作并查看日志中记录的操作。

Python日志记录操作

如果你要保存命令以便在其他地方共享或使用,你可以从日志中选择任意行,并按 Ctrl + C 复制,然后粘贴到文本编辑器中。你还可以按住 Shift 选择多行。

Python日志复制粘贴

将命令粘贴到 输出日志(Output Log) 中并执行即可测试命令,确保将日志类型设置为Python。在此示例中,创建了新控制点。

Python输出日志命令

Python上下文

Python上下文用于设置在运行Python命令时应该影响哪个Control Rig资产的上下文。默认情况下,查看Control Rig时不设置上下文。在 类设置(Class Settings) 细节(面板中,点击 运行Python上下文(Run Python Context),你可以设置当前Control Rig的上下文。

运行Python上下文

这将执行一系列将当前Control Rig资产绑定到Python上下文的命令。这允许在此Control Rig资产中粘贴和执行从Python日志复制的命令。

运行Python上下文命令

  blueprint.get_controller_by_name('').set_node_selection([])
  import unreal
  blueprint = unreal.load_object(name = '/Game/ShowAndTell202009/Pretzel/Mannequin_FBIK_CtrlRig', outer = None)
  library = blueprint.get_local_function_library()
  library_controller = blueprint.get_controller(library)
  hierarchy = blueprint.hierarchy
  hierarchy_controller = hierarchy.get_controller()

复制Python脚本

你还可以将Control Rig的节点、Rig元素和属性全部复制到剪贴板。然后,你可以将其粘贴到外部脚本编辑器中,或粘贴回输出日志,以便在另一个Control Rig上执行。复制Python脚本对于共享、调试和比较不同Rig之间的逻辑很有用。与复制单个命令类似,复制整个Rig对于从Control Rig对Python命令进行逆向工程也很有用。

要复制Control Rig,请点击 类设置(Class Settings) 细节面板中的 复制Python脚本(Copy Python Script)

复制Python脚本

Python脚本示例

添加节点

由于节点是 RigUnit 结构体的视觉效果表示,因此你需要访问该单元才能将节点添加到图表中。

  unreal.load_module('ControlRigDeveloper')

  # get an array of all available units
  units = unreal.ControlRigBlueprint.get_available_rig_units()

  # print details about the units
  for unit in units:
      print(unit.get_path_name())
      print(unreal.EditorAssetLibrary.get_metadata_tag(unit, 'Keywords'))

然后,你需要访问控制器。控制器是用于对图表做出更改的中心对象。

  controller = rig.get_controller()

要将节点添加到图表中,你可以使用 add_struct_nodeadd_comment_nodeadd_parameter_nodeadd_variable_node 函数。下面的示例重点关注结构体节点,这是最常见的类型。结构体节点是RigUnit的视觉效果表示,因此图表中的大多数节点都是结构体节点。

  # get the unit - you might also get this by path or similar
  unit = unreal.RigUnit_MathFloatAdd.static_struct()

  # add the node to the graph provided the unit struct, the method (is always Execute) and 2D position in the graph
  node = controller.add_unit_node(script_struct = unit, method_name = "Execute", position = unreal.Vector2D(0, 0))

编辑层级

除了编辑图表,你还可以使用Python代码编辑层级。Control Rig层级中的每个Rig元素都使用 RigElementKey 标识,其中包含元素的名称和类型。当你创建层级中的元素或与之交互时,你将需要使用此键。

Control Rig元素是结构体,这意味着复制它们时使用的是其总值。因此,如果你更改了元素,你可能必须在层级中重新设置。

层级 可用于查询元素、获取或设置全局/局部变换,以及将元素重置回初始值。

HierarchyController 可以用于添加、删除和编辑元素。如有必要,你还可以使用它来重命名和重新确定父元素。

要检查当前层级,可以使用以下Python代码:

  # access the hierarchy object
  hierarchy = rig.hierarchy

  # get all element keys and print them
  elements = hierarchy.get_all_keys()
  for element in elements:
      print(element)

要创建Rig元素,例如骨骼,你可以使用以下代码:

  # access the hierarchy controller object
  hierarchy_ctrlr = rig.get_hierarchy_controller()

  # add a new bone
  new_bone_key = hierarchy_ctrlr.add_bone(name = "MyBone", parent = unreal.RigElementKey(), transform = unreal.Transform())

  # add a new child bone to a parent that is 10 units away on Z
  child_transform = unreal.Transform(location = [0, 0, 10])

  new_child_bone_key = hierarchy_ctrlr.add_bone(name = "ChildBone", parent = new_bone_key, transform = child_transform)

变量和资产操作

要使用getter和setter节点创建Control Rig变量,你可以使用以下代码:

  rig.add_member_variable("MyVariable", "Transform", is_public = True, is_read_only = False, default_value ="")

  # Create variable getter node
  controller.add_variable_node_from_object_path(MyVariable, 'FTransform', '/Script/CoreUObject.Transform', is_getter = True, default_value = '', position = unreal.Vector2D(), node_name = 'MyVariable_Getter')

  # Create variable setter node
  controller.add_variable_node_from_object_path(MyVariable, 'FTransform', '/Script/CoreUObject.Transform', is_getter = False, default_value = '', position = unreal.Vector2D(), node_name = 'MyVariable_Setter')

预览网格体也可以使用以下代码更改:

  # load a skeletal mesh
  mesh = unreal.load_object(name = '/Game/Mannequin/Character/Mesh/SK_Mannequin.SK_Mannequin', outer = None)

  # create a new (empty) asset
  factory = unreal.ControlRigBlueprintFactory()
  rig = factory.create_new_control_rig_asset(desired_package_path = '/Game/TestRig')

  # set the preview mesh
  rig.set_preview_mesh(preview_mesh = mesh)

你可以使用以下代码编译Control Rig,具体取决于你的上下文:

  # force a recompile of the VM
  rig.recompile_vm()

  # compile the VM if there are pending changes
  rig.recompile_vm_if_required()

  # request a compilation if auto compile is enabled and the editor is open
  rig.request_auto_vm_recompilation()

  # request the control rig to run an init pass (initialize all units)
  rig.request_control_rig_init()

  # request the control rig to run a full blueprint compile
  unreal.BlueprintEditorLibrary.compile_blueprint(rig)

编辑器启动

Python脚本可以在编辑器启动时加载,这对于加载自定义工具和内置Python函数很有用。你可以从以下文件夹路径的项目目录中找到此脚本和示例脚本函数:

Engine\Plugins\Animation\ControlRig\Content\Python

此文件夹中是init_unreal.py脚本,其中包含以下代码:

  import RigHierarchy.add_controls_for_selected
  import RigHierarchy.add_null_above_selected
  import RigHierarchy.align_items

  RigHierarchy.add_controls_for_selected.run()
  RigHierarchy.add_null_above_selected.run()
  RigHierarchy.align_items.run()

init_unreal.py python custom command

此代码将加载启用了额外功能的示例脚本。

例如,add_controls_for_selected 将启用使用附加规则在选定骨骼上创建控制点的功能。这些规则由自定义Python脚本确定,脚本位于Engine\Plugins\Animation\ControlRig\Content\Python\RigHierarchy\add_controls_for_selected.py中。

为所选内容添加控制点