祸起蛋炒饭 2024-01-15 16:59 采纳率: 0%
浏览 5

求UE4 C++异步切换关卡

使用UE4 C++ 执行UGameplayStatics::OpenLevel() 耗时太久

求一个使用C++代码异步执行切换关卡并有进度值显示的例子代码 求个解决办法额

  • 写回答

1条回答 默认 最新

  • CSDN-Ada助手 CSDN-AI 官方账号 2024-01-15 18:30
    关注

    【以下回答由 GPT 生成】

    解决方案

    1. 创建一个异步任务类

    首先,我们需要创建一个异步任务类来执行切换关卡的操作,并提供一个方法来获取进度值。下面是一个简单的示例代码:

    #include "AsyncTaskSwitchLevel.h"
    #include "Engine/LevelStreaming.h"
    
    // 定义一个异步任务类
    class FAsyncTaskSwitchLevel : public FNonAbandonableTask
    {
    public:
        // 构造函数,传入需要切换的关卡名称
        FAsyncTaskSwitchLevel(const FString& InLevelName)
            : LevelName(InLevelName)
            , bIsDone(false)
        {
        }
    
        // 实现执行任务的方法
        void DoWork()
        {
            // 切换关卡的逻辑
            UGameplayStatics::OpenLevel(GWorld, FName(*LevelName), false);
    
            // 标记任务已完成
            bIsDone = true;
        }
    
        // 实现获取进度值的方法
        float GetProgress() const
        {
            // 根据切换关卡的进度返回进度值
            // 这里简单返回一个固定的值,实际可以根据具体需求进行实现
            return 0.5f;
        }
    
        // 指定任务的类型
        TStatId GetStatId() const
        {
            RETURN_QUICK_DECLARE_CYCLE_STAT(FAsyncTaskSwitchLevel, STATGROUP_ThreadPoolAsyncTasks);
        }
    
        // 判断任务是否已完成的标志
        bool IsDone() const
        {
            return bIsDone;
        }
    
    private:
        FString LevelName;
        bool bIsDone;
    };
    

    2. 调用异步任务类进行关卡切换并获取进度值

    在你希望进行异步关卡切换的地方,可以通过以下方式来调用异步任务类:

    // 创建一个任务指针
    TSharedPtr<FAsyncTaskSwitchLevel, ESPMode::ThreadSafe> AsyncTask = MakeShareable(new FAsyncTaskSwitchLevel("LevelName"));
    
    // 将任务添加到异步任务管理器中并开始执行
    AsyncTaskManager.AddTask(AsyncTask.ToSharedRef());
    
    // 循环检查任务是否完成
    while (!AsyncTask->IsDone())
    {
        // 获取任务的进度值,并进行相应的处理
        float Progress = AsyncTask->GetProgress();
    
        // 显示进度值
        UE_LOG(LogTemp, Warning, TEXT("Progress: %f"), Progress);
    
        // 延时一段时间(可选)
        FPlatformProcess::Sleep(0.1f);
    }
    
    // 关卡切换完成
    

    这样,就可以通过异步任务类来进行关卡切换,并且在切换的过程中获取到进度值进行显示。

    3. 异步任务管理器

    上述代码中的 AsyncTaskManager 是一个异步任务管理器,用来管理所有的异步任务。你可以根据自己的需求来实现一个异步任务管理器,或者使用 Unreal Engine 提供的工具类 FTaskGraphInterface

    class FAsyncTaskManager
    {
    public:
        // 添加任务到管理器并开始执行
        void AddTask(TWeakPtr<FAsyncTaskSwitchLevel> InTask)
        {
            if (InTask.IsValid())
            {
                TaskList.Add(InTask);
                FTaskGraphInterface::Get().GetNamedTaskGraph().AddTask(InTask.Pin().ToSharedRef(), ENamedThreads::GameThread);
            }
        }
    
        // 检查是否还有任务在执行
        bool HasPendingTasks() const
        {
            for (auto Task : TaskList)
            {
                if (Task.IsValid() && !Task.Pin()->IsDone())
                {
                    return true;
                }
            }
    
            return false;
        }
    
    private:
        TArray<TWeakPtr<FAsyncTaskSwitchLevel>> TaskList;
    };
    

    完整代码

    下面是一个完整的实例代码,展示了如何使用异步任务类来切换关卡并显示进度值:

    #include "AsyncTaskSwitchLevel.h"
    #include "Engine/LevelStreaming.h"
    
    // 定义一个异步任务类
    class FAsyncTaskSwitchLevel : public FNonAbandonableTask
    {
    public:
        // 构造函数,传入需要切换的关卡名称
        FAsyncTaskSwitchLevel(const FString& InLevelName)
            : LevelName(InLevelName)
            , bIsDone(false)
        {
        }
    
        // 实现执行任务的方法
        void DoWork()
        {
            // 切换关卡的逻辑
            UGameplayStatics::OpenLevel(GWorld, FName(*LevelName), false);
    
            // 标记任务已完成
            bIsDone = true;
        }
    
        // 实现获取进度值的方法
        float GetProgress() const
        {
            // 根据切换关卡的进度返回进度值
            // 这里简单返回一个固定的值,实际可以根据具体需求进行实现
            return 0.5f;
        }
    
        // 指定任务的类型
        TStatId GetStatId() const
        {
            RETURN_QUICK_DECLARE_CYCLE_STAT(FAsyncTaskSwitchLevel, STATGROUP_ThreadPoolAsyncTasks);
        }
    
        // 判断任务是否已完成的标志
        bool IsDone() const
        {
            return bIsDone;
        }
    
    private:
        FString LevelName;
        bool bIsDone;
    };
    
    class FAsyncTaskManager
    {
    public:
        // 添加任务到管理器并开始执行
        void AddTask(TWeakPtr<FAsyncTaskSwitchLevel> InTask)
        {
            if (InTask.IsValid())
            {
                TaskList.Add(InTask);
                FTaskGraphInterface::Get().GetNamedTaskGraph().AddTask(InTask.Pin().ToSharedRef(), ENamedThreads::GameThread);
            }
        }
    
        // 检查是否还有任务在执行
        bool HasPendingTasks() const
        {
            for (auto Task : TaskList)
            {
                if (Task.IsValid() && !Task.Pin()->IsDone())
                {
                    return true;
                }
            }
    
            return false;
        }
    
    private:
        TArray<TWeakPtr<FAsyncTaskSwitchLevel>> TaskList;
    };
    
    void SwitchLevelWithProgress()
    {
        // 创建一个任务指针
        TSharedPtr<FAsyncTaskSwitchLevel, ESPMode::ThreadSafe> AsyncTask = MakeShareable(new FAsyncTaskSwitchLevel("LevelName"));
    
        // 创建一个异步任务管理器
        FAsyncTaskManager AsyncTaskManager;
    
        // 将任务添加到异步任务管理器中并开始执行
        AsyncTaskManager.AddTask(AsyncTask.ToSharedRef());
    
        // 循环检查任务是否完成
        while (AsyncTaskManager.HasPendingTasks())
        {
            // 获取任务的进度值,并进行相应的处理
            float Progress = AsyncTask->GetProgress();
    
            // 显示进度值
            UE_LOG(LogTemp, Warning, TEXT("Progress: %f"), Progress);
    
            // 延时一段时间(可选)
            FPlatformProcess::Sleep(0.1f);
        }
    
        // 关卡切换完成
    }
    

    以上就是一个实现在 UE4 C++ 中使用异步操作切换关卡并显示进度值的示例代码。希望对你有帮助!如果还有其他问题,请随时提问。


    如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^
    评论

报告相同问题?

问题事件

  • 创建了问题 1月15日

悬赏问题

  • ¥15 微信会员卡等级和折扣规则
  • ¥15 微信公众平台自制会员卡可以通过收款码收款码收款进行自动积分吗
  • ¥15 随身WiFi网络灯亮但是没有网络,如何解决?
  • ¥15 gdf格式的脑电数据如何处理matlab
  • ¥20 重新写的代码替换了之后运行hbuliderx就这样了
  • ¥100 监控抖音用户作品更新可以微信公众号提醒
  • ¥15 UE5 如何可以不渲染HDRIBackdrop背景
  • ¥70 2048小游戏毕设项目
  • ¥20 mysql架构,按照姓名分表
  • ¥15 MATLAB实现区间[a,b]上的Gauss-Legendre积分