如何让UWP FPS计数器悬浮显示在Xbox主机游戏之上?
Xbox主机FPS计数器悬浮显示方案咨询
我正在为Xbox主机开发一款FPS计数器,已完成基础UWP应用开发:
- 采用简单计数和平滑平均两种技术计算FPS
- 可在开发模式下的Xbox Series S及本地设备运行,结果显示在屏幕左上角
应用在Xbox Series S开发模式下的运行状态:
应用在本地设备上的运行状态:
核心问题
我无法在官方文档中找到相关说明,以实现将该计数器悬浮在游戏上方,让玩家在游戏过程中实时查看左上角的FPS数据,达到类似Steam的效果。
已知背景
- 部分资料显示此功能无法实现,原因是Xbox运行游戏时会暂停UWP应用,将硬件资源全部分配给游戏
- 但Discord已登陆Xbox,可在玩家语音时弹出悬浮通知;Spotify也能在游戏期间后台播放音乐,说明存在UWP应用在游戏运行时保持活跃并显示内容的例外场景
请问是否存在已知的实现方案?
简化版测试代码
MainPage.xaml
<Page x:Class="FPSCounter.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:FPSCounter" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" Background="Transparent"> <Grid> <StackPanel HorizontalAlignment="Left" VerticalAlignment="Top"> <TextBlock x:Name="basicFPSTextBlock" FontSize="24"/> <TextBlock x:Name="smoothedFPSTextBlock" FontSize="24"/> </StackPanel> </Grid> </Page>
MainPage.xaml.cs
public sealed partial class MainPage : Page { private readonly BasicCounterService counterService; private readonly SmoothedAverageMeasurementService fpsCounter; public MainPage() { InitializeComponent(); SetWindowPositionAndSize(); counterService = new BasicCounterService(); fpsCounter = new SmoothedAverageMeasurementService(0, 0.9); StartFPSCounter(); } private void SetWindowPositionAndSize() { ApplicationView.GetForCurrentView(); double desiredWidth = 50; double desiredHeight = 50; ApplicationView.GetForCurrentView().SetPreferredMinSize(new Size(desiredWidth, desiredHeight)); ApplicationView.GetForCurrentView().TryResizeView(new Size(desiredWidth, desiredHeight)); } private async void StartFPSCounter() { while (true) { int basicFPS = await counterService.CalculateFPS(); double smoothedFPS = await fpsCounter.CalculateSmoothedAverage(); UpdateFPSUI(basicFPS, smoothedFPS); } } private async void UpdateFPSUI(int basicFPS, double smoothedFPS) { await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { basicFPSTextBlock.Text = $"Basic FPS: {basicFPS}"; smoothedFPSTextBlock.Text = $"Smoothed FPS: {Math.Round(smoothedFPS)}"; if (ApplicationView.GetForCurrentView().ViewMode == ApplicationViewMode.CompactOverlay) { } else { } }); } }
BasicCounterService.cs
internal class BasicCounterService { private readonly Stopwatch stopwatch; private int frameCount; public BasicCounterService() { stopwatch = new Stopwatch(); frameCount = 0; } public async Task<int> CalculateFPS() { stopwatch.Start(); while (stopwatch.Elapsed.TotalSeconds < 1) { await Task.Delay(16); frameCount++; } stopwatch.Stop(); int fps = frameCount; frameCount = 0; stopwatch.Reset(); return fps; } }
SmoothedAverageMeasurementService.cs
internal class SmoothedAverageMeasurementService { private readonly double smoothing; private double measurement; private readonly Stopwatch stopwatch; private int frameCount; public SmoothedAverageMeasurementService(double initialMeasurement, double smoothingFactor) { measurement = initialMeasurement; smoothing = smoothingFactor; stopwatch = new Stopwatch(); frameCount = 0; } public async Task<double> CalculateSmoothedAverage() { stopwatch.Start(); while (stopwatch.Elapsed.TotalSeconds < 1) { await Task.Delay(16); frameCount++; } stopwatch.Stop(); double currentMeasurement = frameCount; measurement = (measurement * smoothing) + (currentMeasurement * (1.0 - smoothing)); frameCount = 0; stopwatch.Reset(); return Math.Round(measurement); } }
内容的提问来源于stack exchange,提问作者Vinicius Donatto
相关产品推荐
相关产品推荐

