# 前言 输入`run`显示所有命令说明。 - PVW: 切换PVW - PGM: 切换PGM - 0: 切换Operator - 3: 切换三级 - HandCam: 切换手持相机 - 11: 切换FreeMove - ReMidi: 刷新midi板子 - DebugFrame: debug frame - EnterArea: 进入Area (可填uuid) - xs: 进入异世界雪山1 Area (测试用) - DMXAlign: 强行对齐DMX-Area - ReDeck: 强行加载当前区域的镜头数据并刷新StreamDeck - IdolStatus: 角色动作状态 - AllIdolStatus: 所有角色动作状态 - IdolRelativeTr: 所有角色位置信息 - MotionLog: 角色动作Log - IdolCache: 角色缓存情况(ServerOnly) - GetMotionOffset: 获取动作时间偏移 - MotionReceiveStatus: 角色动作数据接收情况 - ResetOffsetTime: 重置所有角色动作包时间偏移 - SetRes: 设置目标分辨率,如run SetRes 1920 1080 - HipsTranslation: 使用Hips位移 - IdolCostume: 加4个团服角色 - ShowUI: UE4中的ShowUI指令迁移 - BindPGM2: 重新绑定PGM2的固定机位 - LipSync: 设置LipSync音频-静音阈值 - UdexGlove: 使用宇叠科技新手套(部分角色适用) - GenerateMeshConfig: 生成 mesh config(技术用) 涉及到: - TsLiveDirectorGameInstance.ts - TsDirectorConsoleCommandHandler.ts # 命令执行逻辑 ## Run TsDirectorConsoleCommandHandler.ts ```ts static HandleConsoleCommand(gameInstance: TsLiveDirectorGameInstance, consoleCommand: string): void { if(consoleCommand == '' || consoleCommand.toLocaleLowerCase() == 'help'){ TsDirectorConsoleCommandHandler.Help() return } var parts = consoleCommand.split(' ') var funcName = parts[0] var func = TsDirectorConsoleCommandHandler.GetFunctionByName(funcName) if (func == null) { console.error('Not exist cmd ' + consoleCommand) return } switch (parts.length) { case 1: func(gameInstance); break; case 2: func(gameInstance, parts[1]); break; case 3: func(gameInstance, parts[1], parts[2]); break; case 4: func(gameInstance, parts[1], parts[2], parts[3], parts[4]); break; case 5: func(gameInstance, parts[1], parts[2], parts[3], parts[4], parts[5]); break; default: console.error('Cmd paramenter is wrong!') } } ``` 主要的几个切换导播台的命令基本是调用`gameInstance.SetDirectorModeStr("XXX")`。 进入Area函数:为调用`TsDirectorConsoleCommandHandler._EnterArea(gameInstance, "0C1E0DD349EDD9860ED8BDBB55A736F3")`。`_EnterArea`的代码为: ```ts static _EnterArea(gameInstance: TsLiveDirectorGameInstance, areaUUID: string): void { let mapEnvironment = Utils.GetMapEnvironmentManager(gameInstance.GetWorld()); if (mapEnvironment && mapEnvironment.LayerManager) { mapEnvironment.LayerManager.EnterAreaByCMD(areaUUID); } } ``` TsLiveDirectorGameInstance.ts ```typescript Run(CMDStr: $Ref) : void{ let consoleCommand = $unref(CMDStr) TsDirectorConsoleCommandHandler.HandleConsoleCommand(this, consoleCommand) } ``` ## SetDirectorModeStr 位于`ULiveDirectorGameInstance` TsLiveDirectorGameInstance.ts ## 其他有用函数 ```ts static _HipsTranslation(gameInstance: TsLiveDirectorGameInstance, value:number): void { var actors = UE.NewArray(UE.Actor) UE.GameplayStatics.GetAllActorsOfClass(gameInstance, TsIdolActor.StaticClass(), $ref(actors)) for (var i = 0; i < actors.Num(); i++) { var model = actors.GetRef(i) as TsIdolActor if (model) { var anim = model.Mesh.GetAnimInstance() as UE.IdolAnimInstance let fullbodyNode = Reflect.get(anim, 'AnimGraphNode_Fullbody') as UE.AnimNode_FullBody if (fullbodyNode) { //fullbodyNode.bUseHipsTranslation = value > 0 } anim.SetRootMotionMode(value > 0 ? UE.ERootMotionMode.NoRootMotionExtraction : UE.ERootMotionMode.RootMotionFromEverything) model.RootComponent.K2_SetRelativeLocationAndRotation(new UE.Vector(0, 0, model.CapsuleComponent.CapsuleHalfHeight), new UE.Rotator(0, 0, 0), false, null, false) console.warn("use hips translation " + (value > 0)) } } } ``` # RuntimeEditor插件 # 三级导播台 run 3 # MotionProcess 资产位于:UIAssets/Character/WBP_CharacterItem UI逻辑位于:TsCharacterItem.ts的TsCharacterItem