# 大致步骤 使用UnrealEditor-Cmd执行资源导入、处理、输出功能。 1. 导入资产 (这段可以参考FBX) 1. 角色 2. 动画 FBX 2. 处理资产 1. IKRig 2. RetargetRig 3. ControlRig? 3. 输出资产 1. FBX? 2. 使用MovieRenderQueue 渲染 MP4? ## 短期需求 1. AI 动捕、或者GPT生成 BVH、FBX。 2. 特定骨骼结构。 3. UE骨骼确定。 4. 可能需要高并发(后面再考虑) 5. 输出视频。 6. 工期1~2周。 ## 需要解决的问题是 - [ ] 支持多种格式的文件 - [ ] `CustomCommandFunction`编写以及生成**IKRig**、**IKRetarget**资产 - [ ] 输出FBX或者MP4 ## 输出文件 - *.BVH - ## 生产环境 使用Docker或者其他容器工具制作处理用的镜像,之后使用群集系统控制运行? ## CustomCommandFunction 关检测 UCommandlet # 测试方法 ```bash D:\UnrealEngine\UE_5.1\Engine\Binaries\Win64\UnrealEditor-Cmd.exe D:\UnrealEngine\Project\AIAutomationTools\AIAutomationTools.uproject -run=AIAnimationAutomationCommandlet ``` 如果带有配置文件 ```bash D:\UnrealEngine\UE_5.1\Engine\Binaries\Win64\UnrealEditor-Cmd.exe D:\UnrealEngine\Project\AIAutomationTools\AIAutomationTools.uproject -run=AIAnimationAutomationCommandlet -importsettings=C:\\Users\\BlueRose\\Desktop\\ImportJson.json ``` ```json { "ImportGroups": [ { "GroupName": "Group11", //导入文件名 "Filenames": [ "C:\\Users\\BlueRose\\Desktop\\untitled2_Anim.FBX" ], //生成资产的文件夹 "DestinationPath": "Animation", //使用的Factory类名 "FactoryName": "FbxFactory", "bReplaceExisting": 1, "bSkipReadOnly": 0, //导入动画资产的设置 "ImportSettings": { "OriginalImportType": 2, "MeshTypeToImport": 2, "Skeleton": "/Game/1/untitled2_Skeleton.untitled2_Skeleton" } } ] } ``` # 其他资料 ## IKRig & IKRetarget= `Engine\Plugins\Animation\IKRig` - FAssetTypeActions_AnimationAssetRetarget - FAssetTypeActions_IKRigDefinition:UIKRigDefinition - FAssetTypeActions_IKRetargeter:UIKRetargeter ## Retarger ```c++ /** The runtime processor that converts an input pose from a source skeleton into an output pose on a target skeleton. * To use: * 1. Initialize a processor with a Source/Target skeletal mesh and a UIKRetargeter asset. * 2. Call RunRetargeter and pass in a source pose as an array of global-space transforms * 3. RunRetargeter returns an array of global space transforms for the target skeleton. / ``` ## UEditorUtilityLibrary ## Python参考: `Plugins\MovieScene\MovieRenderPipeline\Content\Python` ## 渲染影片(旧版) MovieRenderPipelineCommandLine ```bash "D:\Program Files\UE_4.24\Engine\Binaries\Win64\UE4Editor.exe" D:\Projects\UnrealProjects\renderMovieTest\renderMovieTest.uproject /Game/maps/shot0010 -MovieSceneCaptureType="/Script/MovieSceneCapture.AutomatedLevelSequenceCapture" -LevelSequence="/Game/Sequences/Shot0010" -MovieFolder="D:\Projects\UnrealProjects\renderMovieTest\outputs" -NoLoadingScreen -game ``` void FMovieRenderPipelineCoreModule::StartupModule() 处理CommandLine变量 ```c++ // Look to see if they supplied arguments on the command line indicating they wish to render a movie. if (IsTryingToRenderMovieFromCommandLine(SequenceAssetValue, SettingsAssetValue, MoviePipelineLocalExecutorClassType, MoviePipelineClassType)) { UE_LOG(LogMovieRenderPipeline, Log, TEXT("Detected that the user intends to render a movie. Waiting until engine loop init is complete to ensure ")); // Register a hook to wait until the engine has finished loading to increase the likelihood that the desired classes are loaded. FCoreUObjectDelegates::PostLoadMapWithWorld.AddRaw(this, &FMovieRenderPipelineCoreModule::OnMapLoadFinished); } ``` 通过委托调用渲染,最终到void FMovieRenderPipelineCoreModule::InitializeCommandLineMovieRender() ```c++ void FMovieRenderPipelineCoreModule::InitializeCommandLineMovieRender() { #if WITH_EDITOR //const bool bIsGameMode = !GEditor; //if (!bIsGameMode) //{ // UE_LOG(LogMovieRenderPipeline, Fatal, TEXT("Command Line Renders must be performed in -game mode, otherwise use the editor ui/python and PIE. Add -game to your command line arguments.")); // FPlatformMisc::RequestExitWithStatus(false, MoviePipelineErrorCodes::Critical); // return; //} #endif // Attempt to convert their command line arguments into the required objects. UMoviePipelineExecutorBase* ExecutorBase = nullptr; UMoviePipelineQueue* Queue = nullptr; uint8 ReturnCode = ParseMovieRenderData(SequenceAssetValue, SettingsAssetValue, MoviePipelineLocalExecutorClassType, MoviePipelineClassType, /*Out*/ Queue, /*Out*/ ExecutorBase); if (!ensureMsgf(ExecutorBase, TEXT("There was a failure parsing the command line and a movie render cannot be started. Check the log for more details."))) { // Take the failure return code from the detection of our command line arguments. FPlatformMisc::RequestExitWithStatus(/*Force*/ false, /*ReturnCode*/ ReturnCode); return; } else { UE_LOG(LogMovieRenderPipeline, Log, TEXT("Successfully detected and loaded required movie arguments. Rendering will begin once the map is loaded.")); if (Queue) { UE_LOG(LogMovieRenderPipeline, Log, TEXT("NumJobs: %d ExecutorClass: %s"), Queue->GetJobs().Num(), *ExecutorBase->GetClass()->GetName()); } else { UE_LOG(LogMovieRenderPipeline, Log, TEXT("ExecutorClass: %s"), *ExecutorBase->GetClass()->GetName()); } } // We add the Executor to the root set. It will own all of the configuration data so this keeps it nicely in memory until finished, // and means we only have to add/remove one thing from the root set, everything else uses normal outer ownership. ExecutorBase->AddToRoot(); ExecutorBase->OnExecutorFinished().AddRaw(this, &FMovieRenderPipelineCoreModule::OnCommandLineMovieRenderCompleted); ExecutorBase->OnExecutorErrored().AddRaw(this, &FMovieRenderPipelineCoreModule::OnCommandLineMovieRenderErrored); ExecutorBase->Execute(Queue); } ``` # 多线程 https://blog.csdn.net/j756915370/article/details/122752719 Runtime\Core\Public\Async\ - FFutureState - FTaskGraphImplementation ### 2.6 TaskGraph 系统中的 Wait 在 TaskGraph 中,无论是 Event->Wait() 还是 FTaskGraphInterface::Get().WaitUntilTaskCompletes() ,最终都是调用到 FTaskGraphImplementation::WaitUntilTasksComplete 中的。