Unreal Engine で IK リターゲッタ アセットを作成して使用し、IK リグ を使用するキャラクターおよびオブジェクトのアニメーションをリターゲティングする場合、カスタム仕様の Python スクリプト を使用することで、IK リターゲッタのアセットのワークフローを制御および自動化することができます。
このドキュメントでは、IK リターゲッタ アセットを編集および操作するために参照および使用することができる Python スクリプトの概要と例を提供します。
概要
IK リターゲッタ アセットは次の複数のパーツで構成されています。
-
リターゲティング関係を定義する ソース IK リグと ターゲット IK リグ。
-
ソース IK リグとターゲット IK リグからの ソース スケルタルメッシュおよび ターゲット スケルタルメッシュ のオーバーライド。
-
ソースとターゲット間の リターゲティング チェーン。各チェーン間の関係を定義します。
-
ソースとターゲットのどちらかの リターゲティング ポーズ のリスト。リターゲティングが解決する開始ポーズを定義します。
-
グローバル、リターゲティング ルート、および各 リターゲティング チェーン のプロパティのリスト。
-
エディタ内プレビュー専用のプレビュー シーン。
IK リターゲッタ データ モデルでは、次の用語を使用します。
-
ソース IK リグ および ターゲット IK リグ:ソースからターゲットにモーションを転送するために、リターゲティング チェーンをまとめてマッピングするために使用される IK リグです。
-
ソース メッシュおよび ターゲット メッシュ:リターゲティングのソースおよびターゲットのプロポーションを定義し、ソース アニメーションをプレビューするためにアクセスするスケルタルメッシュ。
-
ソースのリターゲティング ポーズ および ターゲットのリターゲティング ポーズ:ソースまたはターゲットのどちらかがモーションを転送するために使用するポーズ。理想的なのは、ターゲットがソース ポーズに一致していることです。
-
Global Settings (グローバル設定):リターゲティング全体に影響するマクロ レベルの設定。
-
Root Settings (ルート設定):リターゲティング ルートに影響する設定。
-
Chain Settings (チェーン設定):指定したリターゲティング チェーンに影響する設定。
IK リターゲッタにアクセスする
どのような IK リターゲッタ アセットに対するスクリプティングでも、最初のステップは、IKRetargeter
とインタラクションする主なオブジェクトへのアクセス権を取得することです。このオブジェクトにアクセス権を取得する方法は、プロジェクトに応じて複数あります。
既存の RTG アセットをロードする
既存の IK リターゲッタ アセット (rtg
) にアクセスするには、次のサンプル スクリプトを使用してアセットをロードするだけです。
import unreal
# ファイル パスがプロジェクト内のアセットの場所に対して正しいことを確認します。
rtg = unreal.load_asset(name = '/Game/Characters/Mannequins/Rigs/RTG_Mannequin', outer = None)
新しい RTG アセットを作成する
新しい IK リターゲッタ アセットを作成するには、次のファクトリを使用できます。
# アセット ツールを取得します。
asset_tools = unreal.AssetToolsHelpers.get_asset_tools()
# ファイル パスで定義された場所に IK リターゲッタ アセットを作成します。たとえば、「`.../Game/RTG_Mannequin`」です。
rtg = asset_tools.create_asset(asset_name='RTG_Mannequin', package_path='/Game/', asset_class=unreal.IKRetargeter, factory=unreal.IKRetargetFactory())
IK リターゲッタを編集する
コントローラーにアクセスして編集の準備をする
コントローラーは、IK リターゲッタに変更を行うために使用できる中心的なオブジェクトです。コントローラーには、編集に使用できるさまざまな機能が備わっています。次の例は、Python スクリプトを使用して IK リターゲッタ アセットを編集できるメソッドのサブセットです。
# IK リターゲッタ コントローラーを取得します。
rtg_controller = unreal.IKRetargeterController.get_controller(rtg)
ソース IK リグ、ターゲット IK リグおよびメッシュを新しいアセットに割り当てる
リターゲティングを実行するには、ソース IK リグおよびターゲット IK リグを指定する必要があります。ここでは、Manny キャラクターから Quinn キャラクターへのアニメーションをリターゲティングするために、IK リターゲッタ アセットを作成しようとしているため、ソースとターゲットの両方として IK_Mannequin
を割り当てることができます。
Manny と Quinn のスケルタルメッシュ キャラクターと IK_Mannequin
IK リグ アセットには、サードパーソン テンプレート プロジェクト を使用してアクセスすることができます。
# ソース IK リグとターゲット IK リグをロードします。
source_ik_rig = unreal.load_asset(name = '/Game/Characters/Mannequins/Rigs/IK_Mannequin', outer = None)
target_ik_rig = unreal.load_asset(name = '/Game/Characters/Mannequins/Rigs/IK_Mannequin', outer = None)
# ソース IK リグとターゲット IK リグを割り当てます。
rtg_controller.set_ik_rig(unreal.RetargetSourceOrTarget.SOURCE, source_ik_rig)
rtg_controller.set_ik_rig(unreal.RetargetSourceOrTarget.TARGET, target_ik_rig)
また、ソース IK リグまたはターゲット IK リグを取得することができます。これは、リターゲティング チェーンのクエリに役立ちます。
# IK リターゲッタ アセットに割り当てられたソース IK リグとターゲット IK リグを取得します。
rtg_controller.get_ik_rig(unreal.RetargetSourceOrTarget.SOURCE)
rtg_controller.get_ik_rig(unreal.RetargetSourceOrTarget.TARGET)
ソース/ターゲット IK リグを設定できるだけでなく、ソース/ターゲット プレビュー メッシュへのオーバーライドを提供することができます。これにより、IK リグが提供するデフォルトのプレビュー メッシュがオーバーライドされます。
# スケルタルメッシュをロードします。
source_skel_mesh = unreal.load_asset(name = '/Game/Characters/Mannequins/Meshes/SKM_Manny_Simple.SKM_Manny_Simple')
target_skel_mesh = unreal.load_asset(name = '/Game/Characters/Mannequins/Meshes/SKM_Quinn_Simple.SKM_Quinn_Simple')
# ソース スケルタルメッシュとターゲット スケルタルメッシュを割り当てます。
rtg_controller.set_preview_mesh(unreal.RetargetSourceOrTarget.SOURCE, source_skel_mesh)
rtg_controller.set_preview_mesh(unreal.RetargetSourceOrTarget.TARGET, target_skel_mesh)
# IK リターゲッタ アセットに割り当てられたソース スケルタルメッシュとターゲット スケルタルメッシュを取得します。
rtg_controller.get_preview_mesh(unreal.RetargetSourceOrTarget.SOURCE)
rtg_controller.get_preview_mesh(unreal.RetargetSourceOrTarget.TARGET)
リターゲティング チェーン マッピングを編集およびクエリする
エディタと同様に、Python を使用してリターゲティング チェーンの自動マッピングを実行することができます。また、文字列のあいまい一致、文字列の完全一致、または全体の マッピングのクリア などの自動マッピングのオプションも使用できます。
# 文字列のあいまい一致を使用してチェーンをマッピングします。これにより、強制的に再マッピングされます。
rtg_controller.auto_map_chains(unreal.AutoMapChainType.FUZZY, True)
# 文字列の完全一致を使用してチェーンをマッピングします。これにより、強制的に再マッピングされます。
rtg_controller.auto_map_chains(unreal.AutoMapChainType.EXACT, True)
# すべてのマッピングをクリアします。
rtg_controller.auto_map_chains(unreal.AutoMapChainType.CLEAR, True)
自動マッピングを行う必要がない場合は、各ターゲット チェーンのマッピングを取得または設定することができます。
# 指定されたターゲット チェーンにマッピングされているソース チェーンを取得します。
source_mapped_chain_name = rtg_controller.get_source_chain("Spine")
# Python スクリプトの形式 ("Source", “Target”) で、ターゲットのマッピング先のソース チェーンを設定します。
rtg_controller.set_source_chain("Spine", "Spine")
リターゲティング ポーズを追加、編集、クエリする
リターゲティング ポーズは、ソースまたはターゲットがリターゲティングする必要のある基本ポーズを決定するために使用されます。これは、ターゲット キャラクターがソースと異なるポーズをとっている場合や、ソースが適切な前面の軸に向いている必要がある場合に役立ちます。
このコマンドを使用すると、ソースまたはターゲットのリターゲティング ポーズをクエリすることができます。
# ターゲットのすべてのリターゲティング ポーズを取得します。
all_target_poses = rtg_controller.get_retarget_poses(unreal.RetargetSourceOrTarget.TARGET)
リターゲティング ポーズの名前とソースであるかターゲットであるかを指定すると、リターゲティング ポーズの作成、複製、名称変更、除去を実行することができます。
# 新しいリターゲティング ポーズを作成します
rtg_controller.create_retarget_pose("my_new_pose", unreal.RetargetSourceOrTarget.TARGET)
# 新しいポーズを複製します。
rtg_controller.duplicate_retarget_pose("my_new_pose", "duplicated_pose", unreal.RetargetSourceOrTarget.TARGET)
# 複製したポーズの名前を変更します。
rtg_controller.rename_retarget_pose("duplicated_pose", "renamed_pose", unreal.RetargetSourceOrTarget.TARGET)
# 複製したポーズを除去します。
rtg_controller.remove_retarget_pose("renamed_pose", unreal.RetargetSourceOrTarget.TARGET)
次に、現在のリターゲティング ポーズを新しく作成したポーズに設定することができます。
rtg_controller.set_current_retarget_pose("my_new_pose", unreal.RetargetSourceOrTarget.TARGET)
print(rtg_controller.get_current_retarget_pose_name(unreal.RetargetSourceOrTarget.TARGET))
新しいリターゲティング ポーズができたので、Python スクリプトでポーズを編集することができます。リターゲティング ルートは、リターゲティング ポーズで平行移動および回転のオフセットのデルタ値を保持できる唯一のボーンです。その他すべてのボーンでは、リターゲティング ポーズは、相対的な回転オフセットのデルタ値のみを格納できます。
たとえば、ターゲットのリターゲティング ルートを正しい方向に向けるためには、上に移動させ、反転させる必要があります。次の Python スクリプトでは、これを 15 ユニット上に移動させて、90 度回転させます。
# 平行移動のためのベクターを作成します。
translation_offset = unreal.Vector()
translation_offset.z = 15
# リターゲティング ルートの平行移動オフセットを設定します。
rtg_controller.set_root_offset_in_retarget_pose(translation_offset, unreal.RetargetSourceOrTarget.TARGET)
print(rtg_controller.get_root_offset_in_retarget_pose(unreal.RetargetSourceOrTarget.TARGET))
# 回転のローテータを作成します。
rotation_offset = unreal.Rotator()
rotation_offset.roll = 90
# リターゲティング ルートの回転オフセットを設定します。これは任意のボーンに対して機能し、定義済みのボーン名が必要です。
rtg_controller.set_rotation_offset_for_retarget_pose_bone("pelvis", rotation_offset.quaternion(), unreal.RetargetSourceOrTarget.TARGET)
print(rtg_controller.get_rotation_offset_for_retarget_pose_bone("pelvis", unreal.RetargetSourceOrTarget.TARGET))
最後に、ボーンのリストをリセットして、元のトランスフォームに戻すことができます。
rtg_controller.reset_retarget_pose("my_new_pose", ["pelvis"], unreal.RetargetSourceOrTarget.TARGET)
リターゲティング ポーズを自動で整列
# すべてのボーンを自動的に整列させ、ターゲットのリターゲティング ポーズに適用します。
rtg_controller.auto_align_all_bones(unreal.RetargetSourceOrTarget.TARGET)
# ボーンのリストを定義し、それらをソースに合わせて、ターゲットのリターゲティング ポーズに適用します。
bones = ["spine_01", "spine_02", "spine_03"]
rtg_controller.auto_align_bones(bones, unreal.RetargetAutoAlignMethod.CHAIN_TO_CHAIN, unreal.RetargetSourceOrTarget.TARGET)
グローバル設定を編集およびクエリする
リターゲッタでは、歩幅調整プロパティを編集できるグローバル設定や、リターゲティング ルート、FK、IK などのリターゲティングの各フェーズを編集することができます。これらのフェーズは、次の Python スクリプトを使用してクエリおよび編集することができます。
# グローバル設定を取得して、IK を変更し、グローバル設定を設定します。
global_settings = rtg_controller.get_global_settings()
global_settings.set_editor_property("enable_ik", False)
rtg_controller.set_global_settings(global_settings)
ルート設定を編集およびクエリする
リターゲッタでは、ルート設定で、リターゲティング ルートに関連するプロパティを編集します。これにより、臀部への平行移動または回転のオフセット、垂直または水平方向のモーションのスケーリング、または垂直または水平面での IK ゴールに及ぼす影響のスケーリングを行うことができます。これらのプロパティは、次の Python スクリプトを使用してクエリおよび編集することができます。
# ルート設定を取得して、臀部を 10 ユニット上に移動し、ルート設定を行います。
root_settings = rtg_controller.get_root_settings()
root_settings.translation_offset = unreal.Vector(0,0,10)
rtg_controller.set_root_settings(root_settings)
チェーン設定を編集およびクエリする
リターゲッタでは、チェーン設定で、各リターゲティング チェーンに関連するプロパティを編集します。FK チェーンでは、このプロパティの編集で、回転リターゲティング モードを変更できます。また、IK チェーンでは、IK ゴールのソース位置への固定、IK へのオフセットの追加、または IK の垂直方向でのスケーリングを行うことができます。これらのプロパティは、以下の Python スクリプトを使用してクエリおよび編集できます。
# 具体的に左脚のチェーンを取得します。
left_leg_chain_settings = rtg_controller.get_retarget_chain_settings("LeftLeg")
# または、すべてのチェーンからのクエリにより、1 行の for ループ条件を使用してチェーンを取得することができます。
chains = rtg_controller.get_all_chain_settings()
left_leg_chain_settings = next((chain.settings for chain in chains if chain.source_chain == "LeftLeg"), None)
# FK 設定を編集します。
left_leg_chain_settings.fk.rotation_mode = unreal.RetargetRotationMode.INTERPOLATED
left_leg_chain_settings.fk.pole_vector_matching = 1
# IK 設定を編集します。
left_leg_chain_settings.ik.blend_to_source = 1
left_leg_chain_settings.ik.static_offset = unreal.Vector(0,5,0)
# 速度プラント設定を編集します。
left_leg_chain_settings.speed_planting.enable_speed_planting = True
left_leg_chain_settings.speed_planting.speed_curve_name = "ball_l_translation_speed_XYZ"
# リターゲティング チェーンの設定を行います。
rtg_controller.set_retarget_chain_settings("LeftLeg", left_leg_chain_settings)
ポスト リターゲティング フェーズ
# RTG_Mannequin アセットをロード
rtg = unreal.load_asset(name = '/Game/Characters/Mannequins/Rigs/RTG_Mannequin')
rtg_controller = unreal.IKRetargeterController.get_controller(rtg)
# 操作回数を取得
num_ops = rtg_controller.get_num_retarget_ops()
# 最初の操作オブジェクトを取得
first_op = rtg_controller.get_retarget_op_at_index(0)
# 最初の操作インデックスを取得
first_op_index = rtg_controller.get_index_of_retarget_op(first_op)
# 操作が有効になっているか確認
is_op_enabled = rtg_controller.get_retarget_op_enabled(first_op_index)
# 操作を無効にする
rtg_controller.set_retarget_op_enabled(first_op_index, False)
# 結果を確認
is_op_enabled = rtg_controller.get_retarget_op_enabled(first_op_index)
rtg_controller.set_retarget_op_enabled(first_op_index, True)
# スタック内のオペレーションを移動
rtg_controller.move_retarget_op_in_stack(first_op_index, 1)
first_op_index = rtg_controller.get_index_of_retarget_op(first_op)
# カーブ再マッピング操作を追加
added_curve_op_index = rtg_controller.add_retarget_op(unreal.CurveRemapOp)
added_curve_op = rtg_controller.get_retarget_op_at_index(added_curve_op_index)
added_curve_op.set_editor_property("copy_all_source_curves", True)
curve_pair_element = unreal.CurveRemapPair()
curve_pair_element.set_editor_property("source_curve", "source")
curve_pair_element.set_editor_property("target_curve", "target")
added_curve_op.set_editor_property("curves_to_remap", [curve_pair_element])
# 削除操作
rtg_controller.remove_retarget_op(added_curve_op_index)
# ピン ボーン操作を追加
added_pin_bone_op_index = rtg_controller.add_retarget_op(unreal.PinBoneOp)
added_pin_bone_op = rtg_controller.get_retarget_op_at_index(added_pin_bone_op_index)
translate_vector = unreal.Vector()
translate_vector.x = 120
translate_vector.y = 120
translate_vector.z = 120
offset_transform = unreal.Transform()
offset_transform.translation = translate_vector
bone_pair_element = unreal.PinBoneData()
bone_pair_element.set_editor_property("bone_to_pin", "ik_foot_root")
bone_pair_element.set_editor_property("bone_to_pin_to", "root")
added_pin_bone_op.set_editor_property("pin_type", unreal.PinBoneType.ROTATE_ONLY)
added_pin_bone_op.set_editor_property("pin_to", unreal.RetargetSourceOrTarget.SOURCE)
added_pin_bone_op.set_editor_property("maintain_offset", False)
added_pin_bone_op.set_editor_property("local_offset", offset_transform)
added_pin_bone_op.set_editor_property("global_offset", offset_transform)
added_pin_bone_op.set_editor_property("bones_to_pin", [bone_pair_element])
# 削除操作
rtg_controller.remove_retarget_op(added_pin_bone_op_index)
# ルート モーション ジェネレーター操作を追加 - ボーンの名前を自動入力
added_rm_gen_op_index = rtg_controller.add_retarget_op(unreal.RootMotionGeneratorOp)
added_rm_gen_op = rtg_controller.get_retarget_op_at_index(added_rm_gen_op_index)
translate_vector = unreal.Vector()
translate_vector.x = 120
translate_vector.y = 120
translate_vector.z = 120
offset_transform = unreal.Transform()
offset_transform.translation = translate_vector
added_rm_gen_op.set_editor_property("global_offset", offset_transform)
added_rm_gen_op.set_editor_property("maintain_offset_from_pelvis", False)
added_rm_gen_op.set_editor_property("propagate_to_non_retargeted_children", True)
added_rm_gen_op.set_editor_property("root_height_source", unreal.RootMotionHeightSource.SNAP_TO_GROUND)
added_rm_gen_op.set_editor_property("root_motion_source", unreal.RootMotionSource.GENERATE_FROM_TARGET_PELVIS)
added_rm_gen_op.set_editor_property("rotate_with_pelvis", False)
# 削除操作
rtg_controller.remove_retarget_op(added_rm_gen_op_index)
複製とリターゲティングでアニメーションのリターゲティングをバッチ処理する
リターゲティングしたアニメーションをバッチ処理するには、Python で複製やリターゲティングと同じコマンドを実行することができます。
# アセット サブシステムを使用して、アセット データを取得します。
asset_subsystem = unreal.get_editor_subsystem(unreal.EditorAssetSubsystem)
# Anim シーケンス、Anim ブループリント、Pose アセットなどに使用できるアセット データのリストを取得します。
assets_to_retarget = [
asset_subsystem.find_asset_data("/Game/Characters/Mannequins/Animations/Manny/MM_Fall_Loop"),
asset_subsystem.find_asset_data("/Game/Characters/Mannequins/Animations/Manny/MM_Idle")]
retarget_asset = unreal.load_asset(name = '/Game/Characters/Mannequins/Rigs/RTG_Mannequin')
source_mesh = None # ソース IK リグのメッシュを使用します
target_mesh = None # ターゲット IK リグのメッシュを使用します
batch_op = unreal.IKRetargetBatchOperation.duplicate_and_retarget(
assets_to_retarget,
source_mesh,
target_mesh,
retarget_asset,
search = "",
replace = "",
prefix = "",
suffix = "",
remap_referenced_assets = True)