Unreal Engine で IK リグ を作成および使用してキャラクターやオブジェクトをアニメートする場合、カスタム仕様の Python スクリプト を使用して IK リグ アセットのワークフローを制御および自動化することができます。
このドキュメントでは、IK リグ アセットを編集したり連動させたりするために参照および使用することができる Python スクリプトの概要を説明し、例を提供します。
概要
IK リグは、Unreal Engine のスケルタルメッシュ アセットにモーション データを適用することができるコントロールとソルバのセットです。IK リグは、次の複数のパーツで構成されています。
-
ボーン、目標、目標設定 および ボーン設定 の階層。
-
階層のボーンと、それらの間の関係性に影響する IK ソルバのリスト。
- 目標は IK ソルバを操作するために使用され、目標設定とボーン設定はソルバの動作を定義するために使用されます。
-
IK リターゲティング に使用される リターゲティング ルート および リターゲティング チェーン のリスト。
-
エディタ内プレビュー専用のプレビュー シーン。
IK リグ システムは、「モデル > 表示 > コントローラー」の設計式を使用して構築されています。データ モデル自体は、次の用語を使用します。
-
ソルバ:チェーン内のボーンを回転および位置設定する インバース キネマティクス ソリューションを含みます。複数のソルバを同時に使用して、最終ポーズの IK のエフェクトをさらにカスタマイズすることもできます。
-
目標:IK チェーンの エフェクタ ポイント として機能します。目標をソルバと併用して、目標位置に到達するように入力ポーズを変更します。目標は、複数のソルバに割り当てることができます。
-
目標の設定:IK 目標内に存在するソルバ固有の設定。目標へのソルバの割り当てごとに、異なるソルバ固有の設定オブジェクトがあります。
-
目標の設定:ボーン内に存在するソルバ固有の設定。ボーンへのソルバの割り当てごとに、異なるソルバ固有の設定オブジェクトがあります。
-
リターゲティング ルート:ソースからターゲットへの転送に使用されるキャラクター モーションのルート。
-
リターゲティング チェーン:ソースからターゲットにモーションを転送するために定義されるボーンのチェーン。
IK リグにアクセスする
どの IK リグに対するスクリプト処理でも、最初のステップでは、インタラクションを行う主なオブジェクトへのアクセス権を取得するか、The IKRigDefinition を設定します。状況に応じて、これを行う方法は複数あります。以下の例は、Python スクリプトを使用して IK リグ オブジェクトを定義する方法を示しています。
既存の IKR アセットをロードする
既存の IK リグ アセット (ikr) にアクセスするには、次のサンプル スクリプトを使用してアセットをロードするだけです。
import unreal
# ファイル パスがプロジェクト内のアセットの場所に対して正しいことを確認します。
ikr = unreal.load_asset(name = '/Game/Characters/Mannequins/Rigs/IK_Mannequin', outer = None)
新しい IKR アセットを作成する
新しい IK リグ アセットを作成するには、次のファクトリを使用できます。
# アセット ツールを取得します。
asset_tools = unreal.AssetToolsHelpers.get_asset_tools()
# ファイル パスで定義された場所に IK リグを作成します。たとえば、「` …/Game/IK_Mannequin`」などです。
ikr = asset_tools.create_asset(asset_name='IK_Mannequin',
package_path='/Game/', asset_class=unreal.IKRigDefinition,
factory=unreal.IKRigDefinitionFactory())
IK リグを編集する
コントローラーにアクセスして編集の準備をする
コントローラーは、IK リグに変更を加えるために使用できる中心的なオブジェクトです。コントローラーには、編集に使用できるさまざまな機能が備わっています。次の例は、Python スクリプトを使用して IK リグ アセットを編集できるメソッドのサブセットです。
# IK リグ コントローラーを取得します。
ikr_controller = unreal.IKRigController.get_controller(ikr)
新しい IK リグのスケルタルメッシュを割り当てる
新しい IK リグを作成する場合、スケルタルメッシュを割り当てる必要があります。次の Python スクリプトを使用して、スケルタルメッシュ アセットを IK リグや参照にロードして割り当てたり、IK リグに割り当てられているスケルタルメッシュ アセットを取得したりすることができます。
# スケルタルメッシュ アセットをロードします。
skel_mesh = unreal.load_asset(name = '/Game/Characters/Mannequins/Meshes/SKM_Manny_Simple')
# スケルタルメッシュ アセットを IK リグに割り当てます。
ikr_controller.set_skeletal_mesh(skel_mesh)
# IK リグに割り当てられたスケルタルメッシュを取得します。
set_mesh = ikr_controller.get_skeletal_mesh()
自動リターゲティング チェーンと自動 FBIK
コントローラからコマンドを適用して、リターゲティング チェーンと目標を持つフル ボディ IK ソルバを自動的に生成できます。自動生成は、一般的に知られている二足歩行のスケルトンに基づいています。
# 一般的に知られている二足歩行スケルトンから自動生成されたリターゲティング チェーンを適用する
ikr_controller.apply_auto_generated_retarget_definition()
# 一般的に知られている二足歩行スケルトンから自動生成されたフル ボディ IK ソルバを適用します。
ikr_controller.apply_auto_fbik()
IK ソルバを追加、編集、クエリする
コントローラーを介して、さまざまな IK ソルバを簡単に追加できます。ソルバを追加するには、IK リグ ソルバ クラスを指定する必要があります。プロジェクトで使用されるカスタム仕様の IK リグ ソルバが存在する可能性があるため、これは必須です。基本クラスが IKRigSolver である限り、すべてのクラス入力が機能します。
# FBIK ソルバ、Body Mover ソルバ、Limb ソルバ、Pole ソルバ、および Set Transform ソルバを IK リグに追加します。
fbik_index = ikr_controller.add_solver(unreal.IKRigFBIKSolver)
bodymover_index = ikr_controller.add_solver(unreal.IKRig_BodyMover)
limb_index = ikr_controller.add_solver(unreal.IKRig_LimbSolver)
pole_index = ikr_controller.add_solver(unreal.IKRig_PoleSolver)
settransform_index = ikr_controller.add_solver(unreal.IKRig_SetTransform)
ソルバを追加すると、コントローラーはソルバ インデックスを出力します。このインデックスでは、IK リグが解決するソルバの順序を決定します。インデックスを使用してソルバの動作ステートを切り替えたり、スタック内でソルバを移動させたり、特定のソルバを削除したりできます。
# 特定のソルバを有効または無効にします。
ikr_controller.set_solver_enabled(bodymover_index, False)
# ソルバを移動します。
ikr_controller.move_solver_in_stack(bodymover_index, limb_index)
# ソルバを削除します。
ikr_controller.remove_solver(bodymover_index)
ikr_controller.remove_solver(limb_index)
ikr_controller.remove_solver(pole_index)
ikr_controller.remove_solver(settransform_index)
また、次のスクリプトを使用して、ソルバ インデックスや IK リグ内のすべてのソルバをクエリすることもできます。
# IK リグ コントローラーのインデックスの最初のソルバを取得します。
fbik_solver = ikr_controller.get_solver_at_index(fbik_index)
# IK リグ コントローラーに関連付けられているソルバの数を取得します。
num_solvers = ikr_controller.get_num_solvers()
ソルバのルート ボーンを設定する
ソルバが機能するためには、解決を開始するルート ボーンが必要です。これには、ルート ボーンを設定するためのソルバ インデックスが必要になります。次のスクリプトを使用して、ソルバのルート ボーンを設定できます。
# 最初のソルバのルート ボーンを設定し、取得します。
ikr_controller.set_root_bone("pelvis", 0)
root_bone = ikr_controller.get_root_bone(0)
IK 目標を追加 / 編集 / クエリする
IK ソルバを操作するためには、目標が必要です。目標は、目標ボーンの有無を問わず追加することができ、名前を変更することもできます。
# IK リグに目標を追加します。作成時にボーンを割り当てることもできます。
ikr_controller.add_new_goal("hand_l_goal", None)
ikr_controller.add_new_goal("TEMP_hand_r_goal", "hand_r")
# 既存の目標にボーンを割り当てます。
# ボーン内の目標をクエリすることも、目標でボーンをクエリすることもできます。
ikr_controller.set_goal_bone("hand_l_goal", "hand_l")
ikr_controller.get_goal_name_for_bone("hand_l")
ikr_controller.get_bone_for_goal("hand_l_goal")
# 目標の名前を変更します。
ikr_controller.rename_goal("TEMP_hand_r_goal", "hand_r_goal")
# 目標を削除します。
ikr_controller.remove_goal("hand_r_goal")
また、IK リグのすべての目標をクエリすることもできます。
# IK リグのすべての目標を取得します。
ikr_controller.get_all_goals()
目標のプロパティを編集するには、目標のオブジェクトを取得して、いずれかのエディタ プロパティを編集できます。
# 目標オブジェクトを取得し、位置のアルファを設定します。
goal = ikr_controller.get_goal("hand_r_goal")
goal.set_editor_property("position_alpha", 0.5)
new_alpha = goal.get_editor_property("position_alpha")
目標をソルバに接続する
目標が追加されたら、それらをソルバに接続する必要があります。接続する前に、目標がソルバに接続されているかどうかを確認することができます。
# 目標が任意のソルバまたは特定のソルバに接続されているかを確認します。
ikr_controller.is_goal_connected_to_any_solver("hand_r_goal")
ikr_controller.is_goal_connected_to_solver("hand_r_goal", 0)
# 目標とソルバを接続するか、接続を解除します。
ikr_controller.connect_goal_to_solver("hand_r_goal", 0)
ikr_controller.disconnect_goal_from_solver("hand_r_goal", 0)
目標とボーンの設定を追加 / 編集 / クエリする
目標をソルバに接続したら、その特定の目標に対する目標の設定にアクセスすることができます。目標とソルバ間の接続ごとに、独自の設定があります。
次の例では、hand_r_goal が FBIK ソルバと Body Mover ソルバに接続されています。そのため 2 つの異なる目標設定があり、それぞれが対応するソルバに関連付けられています。
# 目標名とソルバを入力し、目標の特定の設定を取得します。
hand_r_goal_settings = ikr_controller.get_goal_settings_for_solver("hand_r_goal", 0)
# 特定のエフェクタ設定のプロパティを編集します。
hand_r_goal_settings.pull_chain_alpha = 0
hand_r_goal_settings.strength_alpha = 1
ソルバは必要に応じてボーンごとの設定をサポートできますが、すべてのソルバでこれが必要なわけではありません。IK リグとともにシッピングされるソルバでは、FBIK ソルバのみにボーンごとの設定があります。この設定例は、目標設定で前述した内容に似ています。
# 腕にボーン設定を追加します。
ikr_controller.add_bone_setting("lowerarm_l", 0)
ikr_controller.add_bone_setting("lowerarm_r", 0)
ikr_controller.add_bone_setting("clavicle_l", 0)
ikr_controller.add_bone_setting("clavicle_r", 0)
# ボーン設定を取得します。
left_lowerarm_setting = ikr_controller.get_bone_settings("lowerarm_l", 0)
right_lowerarm_setting = ikr_controller.get_bone_settings("lowerarm_r", 0)
left_clav_setting = ikr_controller.get_bone_settings("clavicle_l", 0)
right_clav_setting = ikr_controller.get_bone_settings("clavicle_r", 0)
# 希望の角度と回転の剛性を設定します。
left_lowerarm_setting.use_preferred_angles = True
left_lowerarm_setting.preferred_angles = unreal.Vector(0,0,90)
right_lowerarm_setting.use_preferred_angles = True
right_lowerarm_setting.preferred_angles = unreal.Vector(0,0,90)
left_clav_setting.rotation_stiffness = 1
right_clav_setting.rotation_stiffness = 1
他のスケルタルメッシュとの互換性を確認する
IK リグはスケルトンに依存しません。これは、IK リグを同様のスケルトン階層間で共有できることを意味します。Python を使用すると、シンプルなコマンドを使用して IK リグのメッシュの互換性を確認できます。
# この IK リグが定義されたスケルタルメッシュと互換性があるかどうかを確認します。
compatible_skel_mesh = unreal.load_asset(name = '/Game/Characters/Mannequins/Meshes/SKM_Quinn_Simple')
print(ikr_controller.is_skeletal_mesh_compatible(compatible_skel_mesh))
リターゲティング ルートとチェーンを追加、編集、クエリする
リターゲティングの IK リグを設定するには、リターゲティング ルートとリターゲティング チェーンが必要です。これらは、次のサンプルの Python スクリプトを使用して作成できます。
# リターゲティング ルートを設定または取得します。
ikr_controller.set_retarget_root("pelvis")
retarget_root = ikr_controller.get_retarget_root()
リターゲティング チェーンの場合、開始ボーン、終了ボーン、または目標を入力することなく作成できます。これらは、必要に応じて後からチェーンに追加できます。
# 開始ボーン、終了ボーン、目標を含むリターゲティング チェーンを追加します。
ikr_controller.add_retarget_chain("LeftArm", "upperarm_l", "hand_l", "hand_l_goal")
# リターゲティング チェーンを追加します。
ikr_controller.add_retarget_chain("TEMP_RightArm", "", "", "")
# リターゲティング チェーンの名前を変更します。
ikr_controller.rename_retarget_chain("TEMP_RightArm", "RightArm")
# リターゲティング チェーンの開始ボーン、終了ボーン、および目標を設定します。
ikr_controller.set_retarget_chain_start_bone("RightArm", "upperarm_r")
ikr_controller.set_retarget_chain_end_bone("RightArm", "hand_r")
ikr_controller.set_retarget_chain_goal("RightArm", "hand_r_goal")
# リターゲティング チェーンの開始ボーン、終了ボーン、目標を取得します。
ikr_controller.get_retarget_chain_start_bone("RightArm")
ikr_controller.get_retarget_chain_end_bone("RightArm")
ikr_controller.get_retarget_chain_goal("RightArm")
# リターゲティング チェーンを削除します。
ikr_controller.remove_retarget_chain("RightArm")
IK リグのすべてのリターゲティング チェーンをクエリすることができます。
# IK リグのすべてのリターゲティング チェーンを取得します。
all_retarget_chains = ikr_controller.get_retarget_chains()