Python 컨트롤 릭 리깅을 위한 Python 스크립팅

Python 스크립팅을 사용하여 컨트롤 릭 리깅 프로세스를 확장하고 커스터마이징합니다.

Choose your operating system:

Windows

macOS

Linux

컨트롤 릭에서 Python 스크립팅을 사용하여 워크플로를 자동화하고 리깅 프로세스를 위한 툴을 생성합니다. 또한 컨트롤 릭 Python 로그(Control Rig Python Log) 를 사용하여 명령을 리버스 엔지니어링하고 스크립트를 복사하여 다른 프로젝트에 공유할 수 있습니다.

이 문서는 컨트롤 릭에서의 Python 스크립팅에 대한 개요, 컨트롤 릭 Python 로그와 몇 가지 스크립팅 예시를 제공합니다.

전제조건

스크립팅 개요

Python은 주로 컨트롤 릭에서 사용되어 릭 그래프와 인터랙션하며, 다음과 같은 여러 가지 모듈로 구성됩니다.

모듈 이름

설명

ControlRig

릭을 위한 런타임을 포함합니다.

ControlRigDeveloper

릭을 변경하는 모든 기능을 포함합니다.

ControlRigEditor

프론트 엔드 및 유저 인터페이스 로직을 포함합니다.

컨트롤 릭 그래프는 모델-뷰-컨트롤러(Model-View-Controller) 디자인 패턴을 사용하여 구현되었습니다. 모델은 다음 용어를 사용한 그래프 그 자체입니다.

컨트롤 릭 Python 용어

설명

RigUnit

릭의 함수를 정의하는 C++ 구조체입니다(예: FRigUnit_GetBoneTransform).

핀(Pin)

함수의 단일 입력 또는 출력입니다.

링크(Link)

두 핀 사이의 연결입니다.

노드(Node)

RigUnit의 시각적 표현입니다.

그래프(Graph)

릭 내에서 모든 노드와 링크를 포함하는 방향 그래프입니다.

PinPath

그래프 내 핀의 주소를 설명하는 스트링입니다(예: NodeA.Translation.X).

컨트롤러(Controller)

그래프 내에서 변경을 하는 데 사용되는 오브젝트입니다.

RigElementKey

본, 컨트롤, Null, 커브 중에서 선택합니다.

본(Bone)

디포메이션에 사용되는 스켈레톤의 릭 엘리먼트입니다.

컨트롤(Control)

인터랙션에 사용되는 릭 엘리먼트입니다.

Null

중간 트랜스폼에 사용되는 릭 엘리먼트입니다.

커브(Curve)

float 채널을 저장하는 데 사용되는 릭 엘리먼트입니다.

셰이프(Shape)

뷰포트 내 컨트롤의 시각적 표현입니다.

계층구조(Hierarchy)

릭 내의 모든 본, 컨트롤, Null, 커브를 저장하는 컨테이너입니다.

HierarchyController

HierarchyController는 컨트롤러와 유사하며 계층구조를 변경하는 데 사용됩니다.

컴파일러(Compiler)

컨트롤 릭 그래프를 고성능 런타임으로 변환하는 오브젝트입니다.

VM

릭 실행에 사용되는 가상 머신 런타임입니다.

상수(Constant)

런타임 시 변하지 않는 값입니다.

파라미터(Parameter)

릭의 입력 또는 출력으로 사용될 수 있는 값입니다.

변수(Variable)

런타임에서 변경될 수 있는 값으로 릭 실행 이후로 계속 유지됩니다.

ControlRigBlueprint

그래프, 컨트롤러, 컴파일러, VM을 포함하는 에셋입니다.

팩토리(Factory)

새 오브젝트 생성 및 임포트를 담당하는 오브젝트입니다. 언리얼 에디터 전체에 에셋을 생성하는 데 사용됩니다.

Python은 Python 에디터 스크립트 플러그인(Python Editor Script Plugin) 으로 활성화되며, 이 플러그인은 언리얼 엔진에서 기본적으로 활성화됩니다. 또한 이 플러그인은 컨트롤 릭 플러그인(Control Rig Plugin) 이 활성화되면 종속성으로 인해 자동으로 활성화됩니다.

컨트롤 릭에 액세스하기

스크립팅의 첫 단계는 인터랙션할 메인 오브젝트에 액세스하는 것입니다. 이 경우는 ControlRigBlueprint 오브젝트에 액세스합니다. 액세스하는 방법에는 몇 가지가 있지만 첫 명령은 보통 컨트롤 릭을 변경하기 위해 ControlRigDeveloper 모듈을 로드하는 것입니다.

  unreal.load_module('ControlRigDeveloper')

기존 릭에 액세스하려면 다음 예시 명령으로 에셋을 로드합니다.

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

다음을 사용하여 현재 열려 있는 컨트롤 릭 에셋을 로드할 수도 있습니다.

  rigs = unreal.ControlRigBlueprint.get_currently_open_rig_blueprints()

새 컨트롤 릭 에셋은 다음과 같이 생성합니다.

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

마지막으로 다음 예시 코드를 사용하여 스켈레톤 또는 스켈레탈 메시를 기준으로 컨트롤 릭 에셋을 생성할 수 있습니다.

  # 스켈레탈 메시 로드하기
  mesh = unreal.load_object(name = '/Game/Mannequin/Character/Mesh/SK_Mannequin.SK_Mannequin', outer = None)
  # 메시를 위한 컨트롤 릭 생성하기
  factory = unreal.ControlRigBlueprintFactory
  rig = factory.create_control_rig_from_skeletal_mesh_or_skeleton(selected_object = mesh)

Python 로그

Python 로그(Python Log) 는 컨트롤 릭 에디터 안에서 수행한 모든 액션의 텍스트 로그를 제공합니다. 여기에는 뷰포트, 계층구조, 그래프 내의 액션도 포함됩니다. 이 로그를 사용하여 Python 스크립트에서 사용할 명령을 참조하세요.

로그에 액세스하려면 메인 컨트롤 릭 메뉴에서 창(Window) > 메시지 로그(Message Log) 를 클릭한 다음 메시지 로그 사이드바에서 컨트롤 릭 Python 로그(Control Rig Python Log) 를 선택합니다.

컨트롤 릭 Python 로그

이제 릭 그래프에서 액션을 수행하고 로그에 기록할 수 있습니다.

python 로그 기록 액션

명령을 저장해서 공유하거나 다른 곳에서 사용하려면 로그에서 라인을 선택하고 Ctrl + C 를 눌러 복사한 후 다른 텍스트 에디터에 붙여넣으면 됩니다. Shift 키를 누른 채로 여러 라인을 선택할 수도 있습니다.

Python 로그 복사 후 붙여넣기

명령을 출력 로그(Output Log) 에 붙여넣고 실행하는 테스트를 수행하면 로그 유형이 Python으로 설정됐는지 확인할 수 있습니다 이 예시에서는 새 컨트롤이 생성되었습니다.

python 출력 로그 명령

Python 컨텍스트

Python 컨텍스트는 Python 명령 실행 시 어떤 컨트롤 릭 에셋이 영향을 받을지 컨텍스트화하는 데 사용됩니다. 기본적으로 컨트롤 릭을 볼 때는 컨텍스트가 설정되어 있지 않습니다. 클래스 세팅(Class Settings) 디테일 패널에서 Python 컨텍스트 실행(Run Python Context) 을 클릭하여 현재 컨트롤 릭의 컨텍스트를 설정할 수 있습니다.

Python 컨텍스트 실행

이렇게 하면 현재 컨트롤 릭 에셋을 Python 컨텍스트에 바인드하는 일련의 명령이 실행됩니다. 그러면 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 스크립트 복사하기

컨트롤 릭의 노드, 릭 엘리먼트, 프로퍼티 전체를 클립보드에 복사할 수 있습니다. 그런 다음 이를 외부 스크립트 에디터에 붙여넣거나 출력 로그에 붙여넣고 다른 컨트롤 릭에서 실행할 수 있습니다. Python 스크립트 복사는 여러 릭 간의 로직 공유, 디버깅, 비교에 유용합니다. 개별 명령을 복사하는 것과 마찬가지로 전체 릭을 복사하는 것 또한 컨트롤 릭에서 Python 명령을 리버스 엔지니어링하는 데 도움이 됩니다.

컨트롤 릭을 복사하려면 클래스 세팅 디테일 패널에서 Python 스크립트 복사 를 클릭합니다.

Python 스크립트 복사

Python 스크립트 예시

노드 추가하기

노드는 RigUnit 구조체의 시각적 표현이므로 그래프에 노드를 추가하려면 유닛에 액세스해야 합니다.

  unreal.load_module('ControlRigDeveloper')

  # 사용 가능한 모든 유닛의 배열 가져오기
  units = unreal.ControlRigBlueprint.get_available_rig_units()

  # 이 유닛에 대한 디테일 출력하기
  for unit in units:
      print(unit.get_path_name())
      print(unreal.EditorAssetLibrary.get_metadata_tag(unit, 'Keywords'))

다음으로 컨트롤러에 액세스해야 합니다. 컨트롤러는 그래프를 변경하는 데 사용되는 중심적인 오브젝트입니다.

  controller = rig.get_controller()

그래프에 노드를 추가하려면 add_struct_node, add_comment_node, add_parameter_node 또는 add_variable_node 함수를 사용할 수 있습니다. 아래 예시는 가장 일반적인 유형인 구조체 노드에 집중합니다. 구조체 노드는 RigUnit의 시각적 표현이므로 그래프의 노드 대부분은 구조체 노드입니다.

  # 유닛 구하기 - 경로 또는 유사 방식으로도 구할 수도 있음
  unit = unreal.RigUnit_MathFloatAdd.static_struct()

  # 그래프에 유닛 구조체, 메서드(항상 Excute임), 2D 위치가 제공되는 경우 그래프에 노드를 추가하기
  node = controller.add_unit_node(script_struct = unit, method_name = "Execute", position = unreal.Vector2D(0, 0))

계층구조 편집하기

그래프 편집뿐 아니라 계층구조도 Python 코드로 편집할 수 있습니다. 컨트롤 릭 계층구조의 각 릭 엘리먼트는 RigElementKey 를 사용하여 식별하며, 여기에는 엘리먼트의 이름과 유형이 포함됩니다. 계층구조 내의 엘리먼트를 생성하거나 엘리먼트와 인터랙션할 때 이 키를 사용해야 합니다.

컨트롤 릭 엘리먼트는 구조체입니다. 즉, 전체 값을 사용하여 복사됩니다. 그 결과 엘리먼트를 변경하면 계층구조에서 이를 다시 설정해야 할 수도 있습니다.

계층구조(Hierarchy) 는 엘리먼트를 쿼리하고, 글로벌/로컬 트랜스폼을 구하거나 설정하고, 엘리먼트를 초기 값으로 리셋하는 데 사용됩니다.

HierarchyController 는 엘리먼트를 추가, 제거, 편집하는 데 사용됩니다. 필요한 경우 이를 사용하여 엘리먼트의 이름을 변경하거나 부모를 다시 지정할 수도 있습니다.

현재 계층구조 검사를 수행하기 위해 다음 Python 코드를 사용할 수 있습니다.

  # 계층구조 오브젝트에 액세스하기
  hierarchy = rig.hierarchy

  # 모든 엘리먼트 키를 구하여 출력하기
  elements = hierarchy.get_all_keys()
  for element in elements:
      print(element)

릭 엘리먼트(예: 본)를 생성하기 위해 다음 코드를 사용할 수 있습니다.

  # 계층구조 컨트롤러 오브젝트에 액세스하기
  hierarchy_ctrlr = rig.get_hierarchy_controller()

  # 새 본 추가하기
  new_bone_key = hierarchy_ctrlr.add_bone(name = "MyBone", parent = unreal.RigElementKey(), transform = unreal.Transform())

  # Z에서 10유닛 떨어져 있는 부모에 새 자손 본 추가하기
  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)

변수 및 에셋 조작하기

게터 및 세터 노드가 있는 컨트롤 릭 변수를 생성하기 위해 다음 코드를 사용할 수 있습니다.

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

  # 변수 게터 노드 생성하기
  controller.add_variable_node_from_object_path(MyVariable, 'FTransform', '/Script/CoreUObject.Transform', is_getter = True, default_value = '', position = unreal.Vector2D(), node_name = 'MyVariable_Getter')

  # 변수 세터 노드 생성하기
  controller.add_variable_node_from_object_path(MyVariable, 'FTransform', '/Script/CoreUObject.Transform', is_getter = False, default_value = '', position = unreal.Vector2D(), node_name = 'MyVariable_Setter')

프리뷰 메시도 다음 코드를 사용하여 변경할 수 있습니다.

  # 스켈레탈 메시 로드하기
  mesh = unreal.load_object(name = '/Game/Mannequin/Character/Mesh/SK_Mannequin.SK_Mannequin', outer = None)

  # 새(빈) 에셋 생성하기
  factory = unreal.ControlRigBlueprintFactory()
  rig = factory.create_new_control_rig_asset(desired_package_path = '/Game/TestRig')

  # 프리뷰 메시 설정하기
  rig.set_preview_mesh(preview_mesh = mesh)

컨트롤 릭은 컨텍스트에 따라 다음 코드를 사용하여 컴파일할 수 있습니다.

  # VM 강제 리컴파일하기
  rig.recompile_vm()

  # 보류 중인 변경 사항이 있는 경우 VM 컴파일하기
  rig.recompile_vm_if_required()

  # 자동 컴파일이 활성화되어 있고 에디터가 열려 있으면 컴파일 요청하기
  rig.request_auto_vm_recompilation()

  # 컨트롤 릭에 init 패스 실행 요청하기(모든 유닛 초기화)
  rig.request_control_rig_init()

  # 컨트롤 릭에 전체 블루프린트 컴파일 실행 요청하기
  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 커스텀 명령

이 코드는 추가 기능을 활성화하는 샘플 스크립트를 로드합니다.

예를 들어 add_controls_for_selected 는 선택된 본에서 컨트롤을 생성하는 함수와 함께 추가 규칙을 활성화합니다. 이러한 규칙은 Engine\Plugins\Animation\ControlRig\Content\Python\RigHierarchy\add_controls_for_selected.py에 위치한 커스텀 Python 스크립트에 의해 결정됩니다.

선택에 대한 컨트롤 추가