컨트롤 릭으로 애니메이팅하기 위한 Python 스크립팅

Python 스크립팅을 통해 컨트롤 릭 애니메이션 워크플로를 구동하고 확장합니다.

Choose your operating system:

Windows

macOS

Linux

Python 스크립팅시퀀서(Sequencer) 에서 컨트롤 릭(Control Rig) 애니메이팅의 다양한 부분을 자동화하고 제어하는 데 사용할 수 있습니다. 이 문서에서는 컨트롤 릭 애니메이팅과 애니메이션 모드(Animation Mode) 및 기타 다양한 애니메이션 워크플로와 함께 Python을 사용하는 기본적인 방법을 간략하게 살펴봅니다.

전제조건

컨트롤 릭 트랙 생성

컨트롤 릭 트랙을 생성하는 것은 일반적으로 시퀀서에서 트랙을 생성하는 것과는 약간 다릅니다. 컨트롤 릭 트랙을 생성하려면 컨트롤 릭 클래스가 정의되어 있어야 합니다. 다음 명령으로 컨트롤 릭 트랙을 생성할 수 있습니다.

# 에디터 월드를 얻습니다.
world = unreal.EditorLevelLibrary.get_editor_world()

# 컨트롤 릭 에셋을 얻습니다.
rig = unreal.load_asset("/Game/Animation/ControlRig/Mannequin_ControlRig")

# 릭 클래스를 얻습니다.
rig_class = rig.get_control_rig_class()

# 레벨 시퀀스와 액터 바인딩을 사용하여 클래스에서 컨트롤 릭 트랙을 찾거나 생성할 수 있습니다.
rig_track = unreal.ControlRigSequencerLibrary.find_or_create_control_rig_track(world,level_sequence, rig_class, actor_binding)

컨트롤 애니메이팅

다음 예시들은 컨트롤을 편집하고 애니메이팅할 수 있는 다양한 방법을 설명합니다.

컨트롤 선택

다음 명령을 사용하여 컨트롤을 선택하고 컨트롤 선택을 쿼리할 수 있습니다.

  # 시퀀서에서 컨트롤 릭을 얻습니다. ControlRigSequencerBindingProxy 목록을 반환합니다.
  rig_proxies = unreal.ControlRigSequencerLibrary.get_control_rigs(level_sequence)

  # 첫 번째 프록시를 얻습니다. Mannequin_ControlRig이라고 가정합니다.
  rig_proxy = rig_proxies[0]

  # ControlRigSequencerBindingProxy에서 ControlRig 오브젝트를 얻을 수 있습니다.
  rig = rig_proxy.control_rig

  # 지정된 컨트롤을 선택합니다.
  rig.select_control("body_ctrl")

  # 현재 컨트롤 선택을 얻습니다.
  selected_controls = rig.current_control_selection()
  print(selected_controls)

  # 컨트롤 선택을 지웁니다.
  rig.clear_control_selection()

컨트롤 값 얻기 및 설정하기

다음 명령을 사용하여 주어진 모든 프레임 번호의 모든 컨트롤에서 특정 값을 얻을 수 있습니다.

# 시퀀서에서 컨트롤 릭을 얻습니다. ControlRigSequencerBindingProxy 목록을 반환합니다.
rig_proxies = unreal.ControlRigSequencerLibrary.get_control_rigs(level_sequence)

# 0 프레임을 얻습니다.
frame_num = unreal.FrameNumber(0)

# 첫 번째 프록시를 얻습니다. Mannequin_ControlRig이라고 가정합니다.
rig_proxy = rig_proxies[0]

# ControlRigSequencerBindingProxy에서 ControlRig 오브젝트를 얻을 수 있습니다.
rig = rig_proxy.control_rig

# 로컬 컨트롤 값을 얻습니다. 각 컨트롤 타입에는 고유한 타입의 함수가 있습니다.
transform = unreal.ControlRigSequencerLibrary.get_local_control_rig_transform(level_sequence, rig, "body_ctrl", frame_num)
bool = unreal.ControlRigSequencerLibrary.get_local_control_rig_bool(level_sequence, rig, "twist_ctrl_vis", frame_num)

print(transform)
print(bool)

다음 명령을 사용하여 주어진 모든 프레임 번호의 모든 컨트롤에서 특정 값을 설정할 수도 있습니다.

# 시퀀서에서 컨트롤 릭을 얻습니다. ControlRigSequencerBindingProxy 목록을 반환합니다.
rig_proxies = unreal.ControlRigSequencerLibrary.get_control_rigs(level_sequence)

# 첫 번째 프록시를 얻습니다. Mannequin_ControlRig이라고 가정합니다.
rig_proxy = rig_proxies[0]

# ControlRigSequencerBindingProxy에서 ControlRig 오브젝트를 얻을 수 있습니다.
rig = rig_proxy.control_rig

# 현재 시간을 얻습니다.
current_time = unreal.LevelSequenceEditorBlueprintLibrary.get_current_time()

# 현재 시간을 FrameNumber 오브젝트로 변환합니다.
current_frame = unreal.FrameNumber(current_time)

# 컨트롤에 대한 적절한 값 오브젝트를 생성합니다.
transform_value = unreal.Transform(location=[0, 10, 20], rotation=[0,30,0], scale=[1,1,1])

bool_value = True

# 로컬 컨트롤 값을 설정합니다. 각 컨트롤 타입에는 고유한 타입의 함수가 있습니다.
# 각 타입의 함수에는 기본값이 true인 set_key 플래그도 있습니다
unreal.ControlRigSequencerLibrary.set_local_control_rig_transform(level_sequence, rig, "body_ctrl", frame_num, transform_value)
unreal.ControlRigSequencerLibrary.set_local_control_rig_bool(level_sequence, rig, "twist_ctrl_vis", frame_num, bool_value, set_key = False)

애니메이션 모드

애니메이션 모드 툴도 Python 스크립팅의 영향을 받을 수 있습니다. 다음과 같은 예시가 제공됩니다.

트윈 툴

트윈 툴에 다음 명령을 사용할 수 있습니다.

# 값을 -1 ~ 1 사이로 설정합니다.
# -1은 이전 프레임에 블렌딩됩니다.
# 1은 다음 프레임에 블렌딩됩니다.
tween_value = -1

unreal.ControlRigSequencerLibrary.tween_control_rig(level_sequence, rig, tween_value)

스냅퍼 툴

스냅퍼 툴에 다음 명령을 사용할 수 있습니다. 드라이버 오브젝트가 애니메이팅되는 경우, 드라이버 오브젝트를 활성 시퀀스에 추가해야 합니다.

# 시퀀서에서 컨트롤 릭을 얻습니다. ControlRigSequencerBindingProxy 목록을 반환합니다.
rig_proxies = unreal.ControlRigSequencerLibrary.get_control_rigs(level_sequence)

# 첫 번째 프록시를 얻습니다. Mannequin_ControlRig이라고 가정합니다.
rig_proxy = rig_proxies[0]

# ControlRigSequencerBindingProxy에서 ControlRig 오브젝트를 얻을 수 있습니다.
rig = rig_proxy.control_rig

# 액터에 추가하기 위해 에디터 액터 서브시스템을 얻습니다.
editor_actor_subsystem = unreal.get_editor_subsystem(unreal.EditorActorSubsystem)

# 에디터 월드에 큐브를 추가하고 위치를 설정합니다.
cube_mesh = unreal.load_asset("/Engine/BasicShapes/Cube")
cube_location = unreal.Vector(0, 10, 20)
cube_actor = editor_actor_subsystem.spawn_actor_from_object(cube_mesh, cube_location)

# 시작 및 끝 프레임 범위를 설정합니다.
start_frame = unreal.FrameNumber(0)
end_frame = unreal.FrameNumber(5)

# 부모 및 자손에 대한 ControlRigSnapperSelection objects 오브젝트를 생성합니다.
parent = unreal.ControlRigSnapperSelection()
children = unreal.ControlRigSnapperSelection()

# ActorForWorldTransforms 오브젝트를 생성합니다.
# 큐브 액터를 부모로 설정합니다.
parent_actor = unreal.ActorForWorldTransforms()
parent_actor.actor = cube_actor

# ControlRigForWorldTransforms 오브젝트를 생성합니다.
# 적절한 컨트롤 릭 및 왼손 컨트롤을 컨트롤로 설정합니다.
# 여기에 여러 컨트롤 이름이 있을 수 있습니다.
child_control_rig = unreal.ControlRigForWorldTransforms()
child_control_rig.control_rig = rig
child_control_rig.control_names = ["hand_l_ctrl"]

# ActorForWorldTransforms 오브젝트를 가져와 부모 ControlRigSnapperSelection으로 설정합니다.
# ControlRigForWorldTransforms 오브젝트를 가져와 자손 ControlRigSnapperSelection으로 설정합니다.
parent.actors = [parent_actor]
children.control_rigs = [child_control_rig]

# 스냅 세팅을 생성하고 설정합니다.
snap_settings = unreal.ControlRigSnapSettings()
snap_settings.keep_offset = False
snap_settings.snap_position = True
snap_settings.snap_rotation = True
snap_settings.snap_scale = False

# 그런 다음, 0~5 프레임의 큐브에 왼손 컨트롤을 스냅합니다.
unreal.ControlRigSequencerLibrary.snap_control_rig(level_sequence, start_frame, end_frame, children, parent, snap_settings)

스페이스 전환

스페이스 전환에 다음 명령과 예시를 사용할 수 있습니다.

스페이스 전환을 시작하려면, 스페이스 키프레임을 생성해야 합니다. 컨트롤의 스페이스를 기본 부모, 월드 스페이스 또는 주어진 프레임 번호의 다른 컨트롤에 설정할 수 있습니다.

# 시퀀서에서 컨트롤 릭을 얻습니다. ControlRigSequencerBindingProxy 목록을 반환합니다.
rig_proxies = unreal.ControlRigSequencerLibrary.get_control_rigs(level_sequence)

# 첫 번째 프록시를 얻습니다. Mannequin_ControlRig이라고 가정합니다.
rig_proxy = rig_proxies[0]

# ControlRigSequencerBindingProxy에서 ControlRig 오브젝트를 얻을 수 있습니다.
rig = rig_proxy.control_rig

# 왼손 컨트롤 스페이스를 0 프레임에서 월드 스페이스로 설정합니다.
control_name = "hand_l_ctrl"
space = unreal.ControlRigSequencerLibrary.get_world_space_reference_key()
time = unreal.FrameNumber(value = 0)

unreal.ControlRigSequencerLibrary.set_control_rig_space(level_sequence, rig, control_name, space, time)

# 그런 다음, 스페이스 전환을 30 프레임에서 헤드 컨트롤로 설정합니다.
space = unreal.RigElementKey(type = unreal.RigElementType.CONTROL, name = "head_ctrl")
time = unreal.FrameNumber(value = 30)

unreal.ControlRigSequencerLibrary.set_control_rig_space(level_sequence, rig, control_name, space, time)

# 마지막으로, 스페이스 전환을 60 프레임에서 기본 부모로 설정합니다.
space = unreal.ControlRigSequencerLibrary.get_world_space_reference_key()
time = unreal.FrameNumber(value = 60)

unreal.ControlRigSequencerLibrary.set_control_rig_space(level_sequence, rig, control_name, space, time)

스페이스 키프레임이 생성되면, 다음 명령을 사용하여 해당 키프레임을 원하는 프레임 번호로 이동할 수 있습니다.

# 시퀀서에서 컨트롤 릭을 얻습니다. ControlRigSequencerBindingProxy 목록을 반환합니다.
rig_proxies = unreal.ControlRigSequencerLibrary.get_control_rigs(level_sequence)

# 첫 번째 프록시를 얻습니다. Mannequin_ControlRig이라고 가정합니다.
rig_proxy = rig_proxies[0]

# ControlRigSequencerBindingProxy에서 ControlRig 오브젝트를 얻을 수 있습니다.
rig = rig_proxy.control_rig

# 스페이스 키 설정(Set Space Key) 예시에서 스페이스 키가 왼손 컨트롤의 0, 30, 60에 있다고
# 가정해 보겠습니다. 스페이스 키를 30 프레임에서 45 프레임으로 이동해보겠습니다.
control_name = "hand_l_ctrl"
old_time = unreal.FrameNumber(value = 30)
new_time = unreal.FrameNumber(value = 45)

unreal.ControlRigSequencerLibrary.move_control_rig_space(level_sequence, rig, control_name, old_time, new_time)

다음 명령을 사용하여 스페이스 키프레임을 삭제할 수 있습니다.

# 시퀀서에서 컨트롤 릭을 얻습니다. ControlRigSequencerBindingProxy 목록을 반환합니다.
rig_proxies = unreal.ControlRigSequencerLibrary.get_control_rigs(level_sequence)

# 첫 번째 프록시를 얻습니다. Mannequin_ControlRig이라고 가정합니다.
rig_proxy = rig_proxies[0]

# ControlRigSequencerBindingProxy에서 ControlRig 오브젝트를 얻을 수 있습니다.
rig = rig_proxy.control_rig

# 스페이스 키 이동(Move Space Key) 예시에서 스페이스 키가 왼손 컨트롤의 0, 45, 60에 있다고
# 가정해 보겠습니다. 스페이스 키를 45 프레임에서 제거해보겠습니다.
control_name = "hand_l_ctrl"
time = unreal.FrameNumber(value = 45)

unreal.ControlRigSequencerLibrary.delete_control_rig_space(level_sequence, rig, control_name, time)

다음 명령을 사용하여 특정 스페이스에 최종 애니메이션을 구울 수 있습니다.

# 시퀀서에서 컨트롤 릭을 얻습니다. ControlRigSequencerBindingProxy 목록을 반환합니다.
rig_proxies = unreal.ControlRigSequencerLibrary.get_control_rigs(level_sequence)

# 첫 번째 프록시를 얻습니다. Mannequin_ControlRig이라고 가정합니다.
rig_proxy = rig_proxies[0]

# ControlRigSequencerBindingProxy에서 ControlRig 오브젝트를 얻을 수 있습니다.
rig = rig_proxy.control_rig

# 선택한 릭 컨트롤을 모두 얻습니다.
control_names = rig.current_control_selection()

# 레벨 시퀀스에서 시작 및 끝 프레임을 얻고 세팅을 굽기 위해 FrameNumber 오브젝트를 생성합니다.
start_frame_num = level_sequence.get_playback_start()
end_frame_num = level_sequence.get_playback_end()

start_frame = unreal.FrameNumber(value = start_frame_num)
end_frame = unreal.FrameNumber(value = end_frame_num)

# 스페이스에 대한 굽기 세팅을 설정합니다. 기본 부모 스페이스에 구울 것입니다.

space_bake_settings = unreal.RigSpacePickerBakeSettings()
space_bake_settings.target_space = unreal.ControlRigSequencerLibrary.get_default_parent_key()
space_bake_settings.start_frame = start_frame
space_bake_settings.end_frame = end_frame
space_bake_settings.reduce_keys = False
space_bake_settings.tolerance = 0

unreal.ControlRigSequencerLibrary.bake_control_rig_space(level_sequence, rig, control_names, space_bake_settings)

애니메이션 모드 세팅

Python 스크립팅을 사용하여 애니메이션 모드 세팅을 편집할 수 있습니다. 각 프로퍼티에서는 다음과 같은 용어를 사용합니다.

이름

설명

bDisplayHierarchy

캐릭터에 본을 그립니다.

bDisplayNulls

캐릭터에 Null을 그립니다.

bHideManipulators

뷰포트에서 모든 컨트롤을 숨깁니다. 계층구조 표시 또는 Null 표시 가 활성화된 경우 본과 Null도 숨깁니다.

bCoordSystemPerWidgetMode

뷰포트에서 기즈모 모드 변경 시 좌표 공간을 복원합니다.

bOnlySelectRigControls

활성화하면 뷰포트에서 컨트롤 릭 컨트롤만 선택할 수 있습니다. 캐릭터를 포함한 다른 모든 오브젝트는 선택할 수 없습니다.

bLocalTransformsInEachLocalSpace

활성화하면 트랜스포메이션 기즈모가 로컬 좌표로 설정된 경우, 선택한 각 컨트롤을 각자의 로컬 트랜스폼 스페이스를 기준으로 변환합니다.

GizmoScale

기즈모 스케일을 늘이거나 줄입니다.

다음 명령을 사용할 수 있습니다.

# 모드 세팅 클래스를 로드하고 기본 오브젝트를 얻습니다.
ControlRigSettingsClass = unreal.load_class(None, '/Script/ControlRigEditor.ControlRigEditModeSettings')
ControlRigSettings = unreal.get_default_object(ControlRigSettingsClass)

# 쿼리된 데이터를 출력합니다.
print(ControlRigSettings.get_editor_property('bDisplayHierarchy'))
print(ControlRigSettings.get_editor_property('bDisplayNulls'))
print(ControlRigSettings.get_editor_property(GizmoScale))

# 프로퍼티를 설정합니다.
ControlRigSettings.set_editor_property('bDisplayHierarchy', True)
ControlRigSettings.set_editor_property('bDisplayNulls', True)
ControlRigSettings.set_editor_property('GizmoScale', 5)

굽기 및 병합하기

컨트롤 릭에 굽기

시퀀서의 액터에 이미 애니메이션 시퀀스가 있는 경우, 컨트롤 릭에 현재 애니메이션을 구워 컨트롤 릭 트랙을 생성할 수 있습니다. 다음 명령을 사용하여 그러한 작업을 수행할 수 있습니다.

# 현재 에디터 레벨을 얻습니다.
editor_system = unreal.get_editor_subsystem(unreal.UnrealEditorSubsystem)
world = editor_system.get_editor_world()

# 애니메이션 시퀀스 익스포트 옵션을 얻습니다.
anim_seq_export_options = unreal.AnimSeqExportOption()
anim_seq_export_options.export_transforms = True
anim_seq_export_options.export_curves = True

# 키 허용치 숫자 및 키 감소 스테이트를 얻습니다.
tolerance = 0.01
reduce_keys = False

# 컨트롤 릭에 굽습니다.
unreal.ControlRigSequencerLibrary.bake_to_control_rig(world, level_sequence, rig_class, anim_seq_export_options, False, tolerance, actor_binding)

애니메이션 시퀀스에 굽기

컨트롤 릭 애니메이션이 완료되면, 다음 명령을 사용하여 언리얼 엔진의 다른 영역에 사용될 애니메이션 시퀀스로 애니메이션을 내보낼 수 있습니다.

# 현재 레벨 시퀀스를 얻습니다.
level_sequence = unreal.LevelSequenceEditorBlueprintLibrary.get_current_level_sequence()

# SK Mannequin이라는 SkeletaMeshActor 바인딩을 얻습니다.
# 이는 Mannequin_ControlRig를 레벨 에디터로 드래그할 때 기본 이름입니다.
binding = level_sequence.find_binding_by_name("SK Mannequin")

# 레벨 에디터 월드를 얻습니다.
editor_subsystem = unreal.get_editor_subsystem(unreal.UnrealEditorSubsystem)
world = editor_subsystem.get_editor_world()

# 애니메이션 시퀀스 익스포트 옵션을 생성합니다.
anim_seq_export_options = unreal.AnimSeqExportOption()
anim_seq_export_options.export_transforms = True
anim_seq_export_options.export_morph_targets = True

# 에셋 툴을 얻습니다.
# 빈 AnimSequence를 생성합니다. - /Game/Test_Anim
asset_tools = unreal.AssetToolsHelpers.get_asset_tools()
anim_sequence = unreal.AssetTools.create_asset(asset_tools, asset_name = "Test_Anim", package_path = "/Game/", asset_class = unreal.AnimSequence, factory = unreal.AnimSequenceFactory())

# 생성한 AnimSequence에 굽습니다.
unreal.SequencerTools.export_anim_sequence(world, level_sequence, anim_sequence, anim_seq_export_options, binding, False)

# 링크된 애니메이션 시퀀스를 생성하려면, 마지막 아규먼트를 True로 변경하면 됩니다
unreal.SequencerTools.export_anim_sequence(world, level_sequence, anim_sequence, anim_seq_export_options, binding, True)

애니메이션 레이어 병합하기

컨트롤 릭 트랙 안에 여러 개의 섹션과 레이어를 사용하는 경우, 다음과 같은 접기 명령을 사용하여 애니메이션을 하나의 레이어로 굽고 병합할 수 있습니다.

# 시퀀서에서 컨트롤 릭을 얻습니다. ControlRigSequencerBindingProxy 목록을 반환합니다.
rig_proxies = unreal.ControlRigSequencerLibrary.get_control_rigs(level_sequence)

# 첫 번째 프록시를 얻습니다. Mannequin_ControlRig이라고 가정합니다.
rig_proxy = rig_proxies[0]

# ControlRigSequencerBindingProxy에서 MovieSceneControlRigParameterTrack 오브젝트를 얻을 수 있습니다.
# 해당 트랙을 통해 트랙의 모든 섹션을 하나의 섹션으로 접을 수 있습니다.
rig_track = rig_proxy.track

unreal.ControlRigSequencerLibrary.collapse_control_rig_anim_layers
(level_sequence, rig_track, key_reduce = False, tolerance = 0.001)