Skip to content

客户端环境能力 ​

GameCore.ClientEnvironment 提供客户端代码访问本地设备和平台环境的统一入口,适合实现打开外部链接、读写剪贴板、读取或切换本地化语言、查看网络状态、电量状态和只读诊断信息。

显示模式、窗口与移动端 Surface、独立帧调度、扫码、手柄及原生即时诊断使用客户端原生服务,要求 ClientRuntimeFeature.NativeClientServices,最低客户端能力版本为 9。

使用边界

  • 仅客户端可用。相关代码应放在 #if CLIENT 内。
  • 这些信息描述当前玩家的本地客户端,不同步到服务端,也不应作为玩法权威数据。
  • 剪贴板、打开链接、电量和网络信息可能受平台、权限、系统版本或用户设置影响;项目代码需要处理失败或不可用的情况。
  • 打开链接受项目 URL 白名单限制。默认白名单非常有限,主要覆盖常见 QQ 群加群链接;其他网站或应用链接需要先申请或配置白名单。

入口 ​

常用入口在 GameCore.ClientEnvironment 命名空间下:

csharp
#if CLIENT
using GameCore.ClientEnvironment;
using System.Globalization;

ClientEnvironment.TryOpenUrl("https://qm.qq.com/q/xxxx");

ClientEnvironment.Clipboard.Text = "invite-code";
var systemCulture = ClientEnvironment.Localization.SystemCulture;
ClientEnvironment.Localization.CurrentCulture = CultureInfo.GetCultureInfo("zh-CN");

bool isWifi = ClientEnvironment.Network.IsWifi;
var power = ClientEnvironment.Power.Current;
var diagnostics = ClientEnvironment.Diagnostics.Current;
#endif

ClientEnvironment 分为六组:

入口用途
ClientEnvironment.TryOpenUrl(...)请求客户端打开允许的外部 URL 或应用链接
ClientEnvironment.Clipboard读写本地剪贴板文本
ClientEnvironment.Localization读取默认语言、系统语言,并切换当前客户端本地化语言
ClientEnvironment.Network读取当前网络状态,例如是否为 Wi-Fi
ClientEnvironment.Power读取电源和电池状态
ClientEnvironment.Diagnostics读取 FPS、ping、内存等诊断快照,或由玩家主动请求上传客户端日志
ClientEnvironment.Runtime读取客户端构建号,并判断客户端二进制是否支持可选运行时能力

打开外部链接 ​

使用 TryOpenUrl(Uri) 或 TryOpenUrl(string) 请求客户端打开外部链接:

csharp
#if CLIENT
using GameCore.ClientEnvironment;

bool opened = ClientEnvironment.TryOpenUrl("https://qm.qq.com/q/xxxx");
if (!opened)
{
    Game.Logger.LogWarning("未能打开 QQ 群加群链接");
}
#endif

返回值表示客户端是否接受了打开请求,不代表目标页面、App 或浏览器一定已经加载完成。传入字符串不是绝对 URL / 应用链接,或链接未通过白名单检查时,会返回 false。

QQ 群加群链接 ​

打开 QQ 群加群页时,使用 QQ 群分享功能生成的邀请链接,例如:

text
https://qm.qq.com/q/xxxx

这里的 xxxx 是 QQ 生成的分享码,不是群号本身。比如群号是 1021737313 时,不应直接写成 https://qm.qq.com/q/1021737313;需要先在 QQ 群资料页或群管理后台生成实际的加群邀请链接,再把完整链接传给 TryOpenUrl。

默认白名单只覆盖非常有限的常见 QQ 群加群链接格式。如果项目使用的是旧版 QQ 群邀请链接,也应传入 QQ 实际生成的完整链接。

其他链接 ​

游戏官网、问卷、活动页、客服页、社区页、应用协议链接等,都需要先申请或配置项目 URL 白名单。未加入白名单前,TryOpenUrl 会返回 false,客户端也可能提示无法跳转。

建议 UI 上为失败情况准备兜底文案,例如提示玩家稍后重试、复制链接,或引导到游戏内公告 / 客服入口。

剪贴板 ​

ClientEnvironment.Clipboard.Text 读写本地剪贴板文本,Clear() 清空文本:

csharp
#if CLIENT
using GameCore.ClientEnvironment;

ClientEnvironment.Clipboard.Text = "ABC-123";
var copiedText = ClientEnvironment.Clipboard.Text;

ClientEnvironment.Clipboard.Clear();
#endif

剪贴板适合复制房间码、兑换码、邀请文本等短文本。不要把账号凭据、支付状态、背包进度或其他敏感数据写入剪贴板。

语言与本地化 ​

本地化入口使用 .NET 的 CultureInfo,而不是裸字符串:

csharp
#if CLIENT
using GameCore.ClientEnvironment;
using System.Globalization;

CultureInfo defaultCulture = ClientEnvironment.Localization.DefaultCulture;
CultureInfo systemCulture = ClientEnvironment.Localization.SystemCulture;

ClientEnvironment.Localization.CurrentCulture = CultureInfo.GetCultureInfo("en-US");
var currentName = ClientEnvironment.Localization.CurrentCulture.Name;
#endif

常见 CultureInfo.Name 形如 zh-CN、en-US。大小写形式按 .NET 和平台返回为准;如果要和配置字符串比较,建议使用大小写不敏感比较,或统一转换后再比较。

属性含义
DefaultCulture当前项目在客户端上的默认语言 / 区域性
SystemCulture玩家设备系统或平台账号报告的语言 / 区域性
CurrentCulture当前客户端本地化使用的语言 / 区域性,可写入以切换

网络、电量与电池 ​

网络入口用于读取本地网络状态:

csharp
#if CLIENT
using GameCore.ClientEnvironment;

if (ClientEnvironment.Network.IsWifi)
{
    Game.Logger.LogInformation("当前网络为 Wi-Fi");
}
#endif

电源和电池入口返回结构化快照:

csharp
#if CLIENT
using GameCore.ClientEnvironment;

var power = ClientEnvironment.Power.Current;
if (power.BatteryPercent is { } percent && percent < 20)
{
    Game.Logger.LogInformation("当前电量较低: {Percent}%", percent);
}

var battery = ClientEnvironment.Power.Battery;
var temperatureCelsius = battery.TemperatureTenthsCelsius / 10f;
#endif

BatteryPercent、LevelPercent、TimeRemaining 为可空类型;当平台无法提供该值时返回 null。其他数值字段在不可用时可能为 0,状态枚举会返回 Unknown。

只读诊断 ​

ClientEnvironment.Diagnostics.Current 返回当前客户端只读诊断快照:

csharp
#if CLIENT
using GameCore.ClientEnvironment;

var diagnostics = ClientEnvironment.Diagnostics.Current;
Game.Logger.LogInformation(
    "FPS={Fps}, Ping={Ping}ms, DrawCalls={DrawCalls}, Jank={Jank}",
    diagnostics.FramesPerSecond,
    diagnostics.PingMilliseconds,
    diagnostics.DrawCalls,
    diagnostics.JankCount);
#endif

这些值适合做项目内调试面板、性能提示或问题上报辅助信息。不要用 FPS、ping、电量或网络类型来裁决服务端玩法结果;如果玩法需要公平性或反作弊判断,应由服务端逻辑完成。

游戏内上传客户端日志 ​

游戏设置页可以提供“上传日志”按钮,让玩家主动提交本地客户端日志:

csharp
#if CLIENT
using GameCore.ClientEnvironment;

if (ClientEnvironment.Runtime.Supports(ClientRuntimeFeature.ClientLogUpload))
{
    bool accepted = ClientEnvironment.Diagnostics.TryUploadLogs();
    // accepted 为 false 时,提示玩家稍后重试。
}
#endif

此请求沿用客户端现有的日志打包和上传流程,自动关联当前游戏项目。true 仅表示客户端接受请求,不表示打包或网络上传成功;当前 API 不提供完成事件,界面不要在返回 true 后立即显示“上传成功”。仅客户端可调用,旧客户端需要先检查 ClientLogUpload 能力。

客户端版本与可选能力 ​

ClientEnvironment.Runtime 提供客户端二进制的诊断版本和可选能力判断:

客户端契约版本、当前能力表和“旧客户端”的具体边界见客户端二进制兼容与能力版本。本节保留最常用的 API 入口和客户端环境信息边界。

csharp
#if CLIENT
using GameCore.ClientEnvironment;
using GameCore.GameSystem;

long clientBuild = ClientEnvironment.Runtime.BinaryVersion;
bool supportsDisconnectEvent = ClientEnvironment.Runtime.Supports(
    ClientRuntimeFeature.HostDisconnectedEvent);

Game.OnServerDisconnected += () =>
{
    Game.Logger.LogWarning("与游戏服务端的连接已断开");
};
#endif
  • BinaryVersion 是精确客户端构建号,只用于日志、问题上报或显示。不要通过比较构建号判断功能。
  • CapabilityVersion 是高级诊断信息。项目代码应使用 Supports(ClientRuntimeFeature...),不要直接比较能力版本数字。
  • Game.OnServerDisconnected 已由框架完成旧客户端兼容判断,项目可以直接订阅;不支持该事件的旧客户端不会触发它。
  • 能力值在运行期间不会变化,并由框架缓存。选择可选实现时仍建议在初始化阶段判断一次,不要把能力判断散落到每帧或每条消息的逻辑中。

推荐模式 ​

  • 打开设置、分享、反馈或调试面板时读取一次环境信息。
  • 对可能失败的能力使用 Try... 返回值或兜底 UI,不要假设所有平台都能成功。
  • 打开外部链接前先确认目标链接属于项目允许范围;新增非 QQ 群链接时,先走白名单申请 / 配置流程。
  • 对语言字符串做比较时使用 StringComparison.OrdinalIgnoreCase,或把 CultureInfo.Name 统一规范化。
  • 只把诊断数据作为观察和上报辅助,不作为服务端权威输入。
  • 用 Runtime.Supports(...) 判断可选客户端能力;不要用 BinaryVersion 推断功能。

验证 ​

powershell
dotnet build src\GameEntry.csproj -c Client-Debug

运行客户端后验证:

  1. QQ 群邀请链接可以正常打开;未加入白名单的普通网站链接会按预期失败或提示。
  2. 剪贴板复制 / 清空符合目标平台预期。
  3. SystemCulture、CurrentCulture 与本地化 UI 显示一致。
  4. 网络、电量、电池和诊断快照在目标平台上能安全读取,并能处理不可用值。

相关文档 ​