Tencent / GAutomator

Automation for mobile games
1.34k stars 384 forks source link

UE4 call_registered_handler 实现建议 #101

Open FLOWERCLOUD opened 3 years ago

FLOWERCLOUD commented 3 years ago

UE4 中这里通过添加命令字的方式来调用用户sdk接口。 image 文件链接 这里的方式会随着用户接口增加,协议命令字会越来越多,命令字本身就偏框架底层,应尽量少变动。 复用unity中 CALL_REGISTER_HANDLER 的方式这个是否更好, ret = engine.call_registered_handler('get_character_swip', str(params)) ret = engine.call_registered_handler('set_change_rotator',str(params)) ret = engine.call_registered_handler('get_character_scale',str(params)) 然后sdk 也是通过call_registered_handler传入的参数来调用对应的用户函数即可。 sdk 类似下面这样。我这里的方式也不是很美观,最好是能像unity 的方式 register 用户函数,然后也有GET_REGISTERED_HANDLERS 这样的协议。

    void FCommandHandler::HanldeCallRegisteredHandler()
    {
        UE_LOG(GALog, Log, TEXT("CallRegisteredHandler"));
        const TSharedPtr<FJsonObject>& object = ValuePtr->AsObject();
        FString cmd = object->GetStringField("name");
        FString args = object->GetStringField("args");
        FString result = ExecuteRegisteredHandler(cmd, args);
        CommandResponse.ReponseJsonType = ResponseDataType::STRING;
        CommandResponse.ResponseJson = FString::Printf(TEXT("%s"), *result);
        return;

    }
FString ExecuteRegisteredHandler(FString& cmd, FString& args)
    {
        UE_LOG(GALog, Log, TEXT("ExecuteRegisteredHandler  cmd %s ,arg %s"), *cmd, *args);
         if (cmd == FString("UWorldExec"))
        {
            for (TObjectIterator<UUserWidget> Itr; Itr; ++Itr)
            {
                UUserWidget* UserWidget = *Itr;

                if (UserWidget == nullptr || !UserWidget->GetIsVisible() || UserWidget->WidgetTree == nullptr) {
                    continue;
                }
                UWorld* World = Itr->GetWorld();

                if (World != nullptr && World -> GetPlayerControllerIterator())
                {

                    for (FConstPlayerControllerIterator Iterator = World->GetPlayerControllerIterator(); Iterator; ++Iterator)
                    {
                        APlayerController* PlayerController = Iterator->Get();
                        if (PlayerController && PlayerController->IsLocalPlayerController())
                        {
                            FString LevelName = World->GetMapName();
                            UE_LOG(GALog, Log, TEXT("ExecuteRegisteredHandler LevelName %s, cmd %s ,arg %s"), *LevelName, *cmd, *args);
                            FString result = PlayerController->ConsoleCommand(args);
                            UE_LOG(GALog, Log, TEXT("ExecuteRegisteredHandler exec_result %s"), *result);
                            return "true";
                        }
                    }
                    return "false";
                }
            }
        }
        else if (cmd == FString("SetComboBoxString"))
        {
            TArray<FString> array;
            args.ParseIntoArray(array, TEXT(","), true);
            if (array.Num() > 1)
            {
                return SetComboBoxString(array[0], array[1]);
            }
            return FString("invalid args");
        }
        else if (cmd == FString("GetSelectedOption"))
        {
            return GetSelectedOption(args);
        }
        else if (cmd == FString("GetAllOptions"))
        {
            return GetAllOptions(args);
        }
        else if (cmd == FString("GetWidgetBound"))
        {
            TArray<FString> array;
            args.ParseIntoArray(array, TEXT(","), true);
            if (array.Num() > 1)
            {
                return GetWidgetBound(array[0], array[1]);
            }
            FString content;
            return GetWidgetBound(args, content);
        }
        else {

            FName cmd2 = FName(*(cmd));
            FString outpar = callRegisterHandler(cmd2, args);
            return outpar;
        }
        return "false";
    }
David-pzk commented 3 years ago

感谢FLOWERCLOUD为GAutomator提供的建议! 这个issues应该包括两个部分:一是UE4SDK中命令字的形式容易导致后台臃肿,二是建议增加CallRegisteredHandler的调用功能。这两个问题的回答如下: 1、由于目前UE4项目SDK中接口暂时没有继续增加的计划,所以这部分修改的优先级较低。但如果有相关安排,我们会考虑您的建议; 2、目前在UE4SDK中提供了FCommandHandler::CallRegisterHandler初始接口供用户调用UE4内置函数,我们在之后也会进一步优化该接口的调用方式。但由于UE4与unity编译过程存在差异,该接口需要内置函数遵守UE4反射生成机制,参数和返回值也要遵守内定结构体限制。