Python脚本批量解算Demo
发布于:2024-10-18
功能说明
适用于番剧文戏(非武打类的简单动作)的批量化解算,配置好服装好,通过脚本自动化解算
前期准备工作
UE编辑器中做好服装准备工作
角色与服装准备:角色蓝图上挂载Style3D组件,配置好服装(碰撞分组、物理属性调节等)
Sequencer准备:配置好Style3D缓存录制轨道(设置镜头、动作等)
示例工程与脚本
角色蓝图中配置了运行时自动Posefitting
示例Python脚本功能
通过脚本录制服装缓存;
通过脚本配置角色蓝图 、缓存录制参数;
操作步骤
在脚本目录中,用终端打开
通过脚本配置蓝图 和 Sequence 中缓存录制参数: ue_command_style3d_config.py
通过脚本控制缓存生成:ue_command_style3d_run.py
输入以下指令运行
(引擎中Python路径 脚本名)
ue_style3d_task.py
# -*-coding: utf-8 -*-
# ue ver 5.1.1
import os
import json
ue版本5.3.2配置 style3d 服装解算参数 和 Sequence 中生成缓存相关配置def config_style3d(enginePath, projLuncherPath, scriptPath, frame_start, frame_end, fps, ue_bp_path, ue_map_asset_path, ue_seq_path, save_package_name,
save_package_path, style3d_asset_path, style3d_clothconfig):ueLogCmds = ('LogSourceControl off,'
'SourceControl off,'
'LogEditorAssetSubsystem off,'
'LogEditorScripting off,'
'LogHttp off,'
'LogUtils off,'
'LogHttpListener off,'
'LogAssetRegistry off,'
'LogFileManager off,'
'LogFeaturePack off,'
'LogUnrealNames off,'
'LogDirectoryWatcher off')
ueCmd = (
"%s %s -LogCmds=\"%s\" -run=pythonscript -script=\"import sys;sys.path.append('%s');\
import style3d_config_garment_cache;\
style3d_config_garment_cache.do_cloth_solution('%d', '%d', '%d', '%s', '%s', '%s', '%s', '%s', '%s', '%f', '%d', '%f')\""
% (
enginePath,
projLuncherPath,
ueLogCmds,
scriptPath,
frame_start,
frame_end,
fps,
ue_bp_path,
ue_map_asset_path,
ue_seq_path,
save_package_name,
save_package_path,
style3d_asset_path,
style3d_clothconfig["record_rate_scale"],
style3d_clothconfig["iterations"],
style3d_clothconfig["air_damping"]
)
)
CmdRet = os.popen(ueCmd).read()
print(CmdRet)启动 MRQ 来渲染生成服装缓存渲染好的序列存放在Saved\MovieRender中def render_MRQ_seq(enginPath, projPath, map, seq, configPath):
rendercmd = '{0} {1} {2} -game -LevelSequence="{3}" '
'-MoviePipelineConfig="{4}" -windowed -resx=2880 -resy=1620 -log -notexturestreaming'.format(enginPath, projPath, map, seq, configPath)
print(rendercmd)
os.system(rendercmd)引擎目录enginePath = 'E:/UnrealEngine/UE5.3/UE_5.3/Engine/Binaries/Win64/UnrealEditor-Cmd.exe'工程目录projLuncherPath = 'E:/AutoPatch/UEProject/Style3D_Automation/Demo_zdhgx/Demo_zdhgx.uproject'脚本目录scriptPath = 'E:/AutoPatch/UEProject/Style3D_Automation/scripts'阶段一 配置 Style3Dframe_start = 0
frame_end = 300
fps = 30
ue_bp_path = 'MetaHumans/Char1/BP_Char1'
ue_map_asset_path = '/Game/DemoProject/Map/Map_2'
save_cache_path = ''
style3d_clothconfig = {"record_rate_scale": 0.2,"iterations": 300,"air_damping": 0.01}task_configs = [
{
"ue_seq_path": '/Game/DemoProject/Sequence/Seq_01/Sequence01_Dance03',
"save_cache_name": 'Cache_Seq1',
"style3d_asset_path": '/Game/Style3D/Cloth_02',
"enable": True
},
{
"ue_seq_path": '/Game/DemoProject/Sequence/Seq_02/Sequence02_Dance12',
"save_cache_name": 'Cache_Seq2',
"style3d_asset_path": '/Game/Style3D/Cloth_02',
"enable": True
},
{
"ue_seq_path": '/Game/DemoProject/Sequence/Seq_03/Sequence03_Fitting01',
"save_cache_name": 'Cache_Seq3',
"style3d_asset_path": '/Game/Style3D/Cloth_02',
"enable": True
}
]enable用True、False控制task是否执行for task_config in task_configs:
if task_config["enable"]:
# 阶段一 配置Style3D服装资产、解算参数、Sequence配置
config_style3d(enginePath, projLuncherPath, scriptPath, frame_start, frame_end, fps, ue_bp_path, ue_map_asset_path, task_config["ue_seq_path"], task_config["save_cache_name"], save_cache_path, task_config["style3d_asset_path"], style3d_clothconfig) # 阶段二 渲染生成服装缓存
configPath = '/Game/Template/Blueprints/Render/Pending_MoviePipelinePrimaryConfig.Pending_MoviePipelinePrimaryConfig'
render_MRQ_seq(enginePath, projLuncherPath, ue_map_asset_path, task_config["ue_seq_path"], configPath)
#break</code></pre><p></p><h3><span style="font-size: 15px; line-height: 22.5px;">ue_command_style3d_</span><a target="_blank" rel="noopener noreferrer nofollow" href="http://config.py" data-link-id="" data-link-title="" data-link-description="" data-link-sync-mode="master" data-link-display-mode="title" data-link-type=""><span style="font-size: 15px; line-height: 22.5px;">config.py</span></a></h3><pre><code># -*-coding: utf-8 -*-ue ver 5.1.1import os
import unreal as ue
import jsondef track_to_dict(track):
t = {
'name' : str(track.get_display_name()),
'type' : track.get_class().get_name(),
'sections' : []
}for section in track.get_sections():
section_range = section.get_range()
t['sections'].append({
'range' : {
'has_start' : section_range.has_start,
'start' : section_range.inclusive_start,
'has_end' : section_range.has_end,
'end' : section_range.exclusive_end,
},
'type': section.get_class().get_name()
})
return tdef do_cloth_solution(frame_start, frame_end, fps, ue_bp_path, ue_map_asset_path, ue_seq_path, save_package_name,
save_package_path, style3d_asset_path, record_rate_scale, iterations, air_damping):
"""
Args:
frame_start: shot start frame num, int32, eg: 950 frame_end: shot end frame num, int32, eg: 1058
fps: shot fps, int32, eg: 25
ue_bp_path: solution used bp asset ue path, string, eg: "/Game/character/hanli_default/BP/bp_hanli_default"
ue_map_asset_path: map asset ue path
ue_seq_path: sequence asset ue path
save_package_name: solution file name for save in ue, string
save_package_path: solution file ue path for save in ue, string
style3d_asset_path: style3d cloth asset path
style3d_clothconfig: { 'record_rate_scale': 0.3,
'iterations': 50,
'air_damping': 0.1,
}
Returns:
solution_finish_path: file ue path of solution finished in ue, string
"""
"""
ue.log_warning("style3d_clothconfigfile_path:" + style3d_clothconfigfile_path)
if ue.EditorAssetLibrary.does_asset_exist(style3d_clothconfigfile_path):
ue.log_warning("have style3d_clothconfigfile_path!")
blueprint_clothconfig_asset = ue.EditorAssetLibrary.load_asset(style3d_clothconfigfile_path)
bp_class = ue.load_object(None, blueprint_clothconfig_asset.generated_class().get_path_name())
bp_cdo = ue.get_default_object(bp_class)
bp_cdo.set_editor_property('new_cache_name', 'hahahaaha')
ue.EditorAssetLibrary.save_asset(style3d_clothconfigfile_path)
"""
# 此处假设 Style3D 组件已经在蓝图 Actor 上挂载,服装资产也已经挂载到 Style3D 组件, 只是需要配置缓存名称和部分解算参数
if ue.EditorAssetLibrary.does_asset_exist(ue_bp_path):
ue.log_warning("have ue_bp_path: " + ue_bp_path)
bp_asset = ue.load_asset(ue_bp_path)
#style3d_clothconfig_obj = json.loads(style3d_clothconfig)
#style3d_clothconfig_obj = {"record_rate_scale": 0.4,"simulate_time_scale": 1.2,"iterations": 60,"air_damping": 0.2}
subsystem: ue.SubobjectDataSubsystem = ue.get_engine_subsystem(ue.SubobjectDataSubsystem)
root_data_handle: ue.SubobjectDataHandle = subsystem.k2_gather_subobject_data_for_blueprint(context=bp_asset)
objects = []
#get components in blueprint
for handle in root_data_handle:
subobject = subsystem.k2_find_subobject_data_from_handle( handle )
objects.append( ue.SubobjectDataBlueprintFunctionLibrary.get_object( subobject ) )
#remove duplicates
objects = list(dict.fromkeys(objects))
#check if Style3DComponent and update the parameters
for object in objects:
if "Style3DComponent" in str(object):
ue.log_warning("have style3d_component!")
style3d_component = object
#style3d_component.set_editor_property('new_cache_name', save_package_name)
style3d_component.get_editor_property('cache_record_setting').set_editor_property('record_rate_scale', float(record_rate_scale))
style3d_component.get_editor_property('solver_property').set_editor_property('iterations', int(iterations))
style3d_component.get_editor_property('solver_property').set_editor_property('air_damping', float(air_damping))
if ue.EditorAssetLibrary.does_asset_exist(style3d_asset_path):
style3d_asset = ue.load_asset(style3d_asset_path)
style3d_component.set_editor_property('meta_data_asset', style3d_asset)
ue.EditorAssetLibrary.save_asset(ue_bp_path)
else:
ue.log_warning("have not find ue_bp_path!")
# 此处假设 Style3D 缓存录制轨道已经在 Sequence 中配置完成, 只是需要配置缓存名称,起始帧和结束帧
ue.log_warning("ue_seq_path: " + ue_seq_path)
if ue.EditorAssetLibrary.does_asset_exist(ue_seq_path):
ue.log_warning("have ue_seq_path!")
world = ue.EditorLoadingAndSavingUtils.load_map(ue_map_asset_path)
sequence = ue.load_asset(ue_seq_path, ue.LevelSequence)
bindings = sequence.get_bindings()
#ue.log_warning(bindings)
for binding in bindings:
tracks = binding.get_tracks()
for track in tracks:
for section in track.get_sections():
section_class_str = str(section.get_class())
ue.log_warning(section_class_str)
if section_class_str.find("Style3DMovieSceneGarmentCacheSection") != -1:
#section.set_start_frame_seconds(0)
#section.set_end_frame_seconds(100)
section.get_editor_property('params').set_editor_property('garment_cache_name', save_package_name)
#integrate_info = section.get_editor_property('params').get_editor_property('garment_integrate_info')
#style3d_asset_name = integrate_info.get_editor_property('garment_asset_map')['default'].get_editor_property('garment_asset').get_name()
style3d_asset_name = 'test'
ue.LevelSequenceEditorBlueprintLibrary.refresh_current_level_sequence()
ue.EditorAssetLibrary.save_asset(ue_seq_path)
solution_finish_path = '/Game/Style3D/GarmentCache/'# + style3d_asset_name + '/' + save_package_name
return solution_finish_path
附录
Unreal Python 脚本文档学习