我正在尝试为 Xbox(控制台)上的游戏开发 FPS 计数器。我成功开发了一个基本的 UWP 应用程序,该应用程序使用两种技术来计算 FPS:简单计数和平滑平均测量。它会在左上角的屏幕上显示这两个结果(下面的屏幕截图显示了在开发者模式下在 Xbox Series S 上运行的应用程序)。
这是在我的本地计算机上运行的应用程序:
问题是我在文档中找不到任何有关如何将计数器覆盖在游戏本身之上的信息,从而使我能够在玩游戏的同时将 FPS 计数器放在左上角进行实时测量,类似Steam 所做的事情。
我在某些地方读到这是不可能的,因为在执行游戏时 Xbox 会暂停 UWP 应用程序,以便将所有硬件专用于游戏,这是有道理的。然而,Discord 最近登陆了 Xbox,它可以在玩家通过麦克风讲话时发送覆盖游戏的通知,Spotify 还可以在游戏过程中在后台播放音乐。
有什么已知的方法可以实现这一目标吗?
这是我的应用程序的简化版本,可以在需要时在本地运行以进行测试:
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;
}
}
平滑平均测量服务.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);
}
}
由于您所描述的原因,您不能。虽然 UWP 可以在后台运行,但它无法访问屏幕,因此无法与游戏叠加。