Skip to content

Loading 页面与启动加载 UI ​

Loading 页面属于客户端 GameUI。项目可以关闭或换肤框架启动时自动显示的 Loading,也可以在场景切换、资源预热和客户端数据准备期间显示自己的临时遮罩。它不是 App 打开前的原生启动图或平台 splash screen。

先判断要改哪一种 Loading ​

需求推荐入口
不需要框架启动 Loading在当前 GameDataGameUI 中关闭 ShowDefaultLoading
保留启动 Loading,但更换背景、图片、文案、进度条和布局创建 GameDataLoadingUI,并由 GameDataGameUI.DefaultLoadingUI 引用
场景切换或业务加载期间临时显示使用 LoadingUI / GameEntryLoadingSystem.ShowLoading(...)
页面结构与内置 Loading 完全不同使用 Page、Label、Image、Progress 等控件自行搭建
修改 App 打开前的启动图、安装包图标或平台 splash screen走平台包体配置,不使用 GameUI

框架启动 Loading 优先使用数编配置。这样不用为了关闭页面或调整样式专门注册初始化事件,也不会与框架自己的启动进度更新重复创建两层遮罩。

最快关闭框架默认 Loading ​

如果当前 GameDataGameMode.GameUI 已经指向项目自己的 GameDataGameUI,只需在数据编辑器中取消勾选:

text
ShowDefaultLoading = false

关闭后,框架不会在游戏启动时自动创建 Loading;项目手动创建的 LoadingUI、自定义遮罩以及原生平台启动图都不受影响。

新项目通常仍使用 gamesparkcore.ScopeData.GameDataGameUI.Default。依赖库数据不应直接修改,此时按下面的方式配置:

  1. 在项目自己的 GameEntry 数据中创建一个 GameDataGameUI,可以继承 GameSparkCore 的默认 UI 配置。
  2. 将这个条目的 ShowDefaultLoading 设为 false。
  3. 将当前 GameDataGameMode.GameUI 改为指向项目自己的 GameDataGameUI。
  4. 保存并生成数编代码,然后重新进入游戏。

如果取消勾选后仍然出现默认页,优先检查当前 GameMode 的 GameUI Link 是否仍指向 GameSparkCore 默认配置。

用 GameData 自定义启动 Loading ​

GameSparkCore 已提供与当前框架默认视觉一致的 GameDataLoadingUI 默认数据和“Loading界面模板”。项目可以继承它,只覆盖自己需要改变的字段;后续框架默认样式扩展时,也不需要复制一套启动代码。

推荐步骤:

  1. 在项目数据中基于 GameSparkCore 的“Loading界面模板”创建 GameDataLoadingUI,或继承 gamesparkcore.ScopeData.GameDataLoadingUI.Default。
  2. 修改背景、品牌图、提示文字、进度条、取消按钮或布局字段。
  3. 在项目自己的 GameDataGameUI 中保持 ShowDefaultLoading = true,并将 DefaultLoadingUI 指向新的 GameDataLoadingUI。
  4. 确认当前 GameDataGameMode.GameUI 指向这个项目配置。
  5. 保存、生成并重新进入游戏查看效果。

常用字段:

  • 背景:BackgroundColor、BackgroundCornerRadius、BackgroundLayout。
  • 品牌字标:BrandWordmarkImage、BrandWordmarkSourceWidth、BrandWordmarkSourceHeight、BrandWordmarkLayout。将图片设为空可不创建字标。
  • 品牌说明:BrandSubtitle、BrandSubtitleFontSize、BrandSubtitleTextColor、BrandSubtitleLayout。将 BrandSubtitle 设为 null 可不创建说明。
  • 加载提示:DefaultLoadingMessage、LoadingTextFontSize、LoadingTextColor、LoadingTextLayout。
  • 进度显示:ProgressBarColor、ProgressBarCornerRadius、ProgressBarLayout、ProgressTextFontSize、ProgressTextColor、ProgressTextLayout。
  • 取消按钮:CancelButtonText、CancelButtonColor、CancelButtonCornerRadius、CancelButtonLayout。将 CancelButtonText 设为 null 可不创建按钮。
  • 自动隐藏:CompleteAutoHideDelay、FailedAutoHideDelay、FailedTextColor。

布局字段使用与普通 GameUI 控件一致的 Layout 数据,可设置尺寸、位置、对齐、拉伸比例和边距。图片路径遵循 GameUI 资源规则:项目 ui/ 下的图片,数据路径从 ui/ 内部开始写;更多规则见 项目资源路径。

兼容行为 ​

  • 旧项目没有 ShowDefaultLoading 数据时仍按默认值 true 显示,不会因为升级依赖而突然丢失启动遮罩。
  • DefaultLoadingUI 未配置时,框架使用历史内置样式的兼容默认值。
  • 无参 new LoadingUI()、CreateSimple(...)、CreateWithProgress(...) 和 CreateFull(...) 继续可用,行为保持兼容。
  • ShowDefaultLoading = false 只关闭框架自动创建的启动 Loading,不会禁止项目代码主动创建其他 Loading。

在代码中复用数编样式 ​

业务 Loading 也可以使用同一个 GameDataLoadingUI。这适合场景切换、资源下载等需要复用项目视觉,但出现时机由代码控制的场景:

csharp
#if CLIENT
using GameUI.Control;

var configuration = GameEntry.ScopeData.GameDataLoadingUI.BattleLoading.Data;
if (configuration is not null)
{
    var loading = new LoadingUI(configuration);
    loading.Show("正在进入战场...", progress: 0.2f);
    loading.UpdateProgress(0.7f, "加载场景资源...");
    loading.SetComplete("准备完成");
}
#endif

GameEntryLoadingSystem.ShowLoading(...) 和静态预设工厂使用兼容默认样式。如果临时 Loading 也要使用项目数编样式,应显式调用 new LoadingUI(configuration)。

临时 Loading 的最快用法 ​

框架提供了 LoadingUI 和 GameEntryLoadingSystem。它们只在客户端可用。

csharp
#if CLIENT
using GameUI.Control;

var loading = GameEntryLoadingSystem.ShowLoading(
    message: "正在进入战场...",
    showProgress: true,
    showCancel: false);

loading.UpdateProgress(0.35f, "加载场景资源...");
loading.UpdateProgress(0.80f, "初始化界面...");
loading.SetComplete("准备完成");
#endif

也可以直接创建不同预设:

csharp
#if CLIENT
var simple = LoadingUI.CreateSimple("加载中...");
simple.Show();

var progress = LoadingUI.CreateWithProgress("加载资源中...", showCancel: true);
progress.Show(progress: 0.2f);
progress.UpdateProgress(0.6f, "同步玩家数据...");
progress.Hide();
#endif

常用 API:

  • LoadingUI.CreateSimple(message):只有提示文字。
  • LoadingUI.CreateWithProgress(message, showCancel):提示文字 + 进度条,可选取消按钮。
  • LoadingUI.CreateFull(message):完整加载界面。
  • Show(message, progress) / Hide():显示和隐藏。
  • UpdateProgress(progress, message):更新进度,progress 范围是 0.0f 到 1.0f。
  • SetComplete(message) / SetFailed(message):显示完成或失败状态后按数编延迟自动隐藏。

完全自定义页面 ​

如果页面结构与内置 Loading 完全不同,可以自己用 Page、Label、Image、Progress 等控件搭一个全屏页面。关键是把层级接到标准 Loading 层:

csharp
#if CLIENT
using GameCore.GameSystem.Enum;
using GameUI.Brush;
using GameUI.Control.Advanced;
using GameUI.Control.Extensions;
using GameUI.Control.Primitive;
using System.Drawing;

var root = new Page()
    .Background((ColorBrush)new SolidColorBrush(Color.FromArgb(220, 8, 12, 20)))
    .ZIndex(StandardUIType.Loading.ExpectedZIndex ?? 10000);
root.AddToRoot();

var title = new Label()
    .Text("星际远征")
    .FontSize(42)
    .TextColor(Color.White)
    .Center()
    .RelativeOffset(0, -80);
title.AddToParent(root);

var progress = new Progress()
    .Size(420, 10)
    .Center()
    .RelativeOffset(0, 20);
progress.AddToParent(root);

progress.Value = 0.5f;

// Loading 结束且不再复用时调用 Destroy,避免控件、事件和 native 资源残留。
root.Destroy();
#endif

注意事项:

  • 临时 Loading 结束后优先调用 Destroy()。只有需要复用或临时摘树时,才用 RemoveFromParent() / RemoveFromVisualTree()。
  • 字体要提前放入项目字体引用,见 自定义字体。

启动生命周期 ​

客户端初始化顺序里有几个常用事件:

  1. Game.OnGameDataInitialization
  2. Game.OnGameplaySettingsInitialization
  3. Game.OnGameUIInitialization
  4. Game.OnGameStart

框架在 OnGameplaySettingsInitialization 读取事件传入的当前 GameDataGameMode 及其 GameUI 配置,并根据 ShowDefaultLoading / DefaultLoadingUI 创建启动 Loading。后续初始化事件只负责更新进度;OnGameStart 将其标记完成并按配置延迟隐藏。

因此,关闭或换肤框架启动 Loading 应修改 GameData,不需要在 OnGameDataInitialization 中写代码补丁。普通业务 UI 初始化建议放在 OnGameUIInitialization 之后;需要更早显示项目自己的遮罩时,确保代码只使用客户端可用 API,并为 StandardUIType.Loading.ExpectedZIndex 提供 fallback。

不要直接依赖底层 game_on_game_stage(status) 的数字状态来写业务 Loading。公开项目代码里优先使用 Game 生命周期事件、Scene.LoadState / Scene.Loaded 和 Scene.OnLoadEnd。

和场景加载的关系 ​

GameStart 表示游戏脚本生命周期已开始,不代表客户端地图场景已经加载完成。依赖地图、地形、预放置对象或底层 SceneGraph 的 UI 初始化,应等待目标场景加载成功:

csharp
using GameCore.SceneSystem;

var scene = Scene.GetOrCreate(GameEntry.ScopeData.GameDataScene.new_scene);
if (scene.Loaded)
{
    OnSceneLoaded();
}
else
{
    scene.OnLoadEnd += OnSceneLoaded;
}

多场景项目可以结合 scene.LoadState、scene.Loaded、OnLoadEnd 或场景加载事件更新 Loading 文案与进度。不要用固定延迟猜测地图加载完成时间。

排查清单 ​

  • 关闭或换肤不生效:确认当前 GameDataGameMode.GameUI 指向项目自己的配置,而不是仍指向 gamesparkcore 默认配置。
  • 启动时出现两层 Loading:保留框架默认页时不要再注册一套相同的启动 Loading;需要完全接管时先设置 ShowDefaultLoading = false。
  • 自定义图片不显示:确认资源位于项目 ui/,数据路径从 ui/ 内部开始写,并正确填写字标源图片尺寸。
  • 临时 Loading 看不见:确认代码在 #if CLIENT 内,并已经调用 Show() 或将自定义页面加入 UI 树。
  • 被其他 UI 遮住:使用 StandardUIType.Loading.ExpectedZIndex ?? 10000。
  • 退出后再次进入残留旧遮罩:临时 Loading 结束时调用 Destroy(),并清理事件订阅。
  • 依赖场景的控件初始化失败:不要把 GameStart 当作场景加载完成,等待 Scene.Loaded 或 OnLoadEnd。