首页 > 解决方案 > 如何读取系统使用情况(CPU、RAM 等)

问题描述

在 unity3d 中,我试图读取系统使用情况,以便在一个人玩 VR 游戏时查看 CPU 和 RAM 使用情况。我知道如何在电脑屏幕上显示它,以及如何让它远离玩家的 VR 屏幕。

据我所知,我一直在谷歌周围寻找。他们中的大多数导致相同的答案,我似乎无法正常工作。

我一直在查看帖子:https ://answers.unity.com/questions/506736/measure-cpu-and-memory-load-in-code.html这将我带到stackoverflow页面:如何获取CPU在 C# 中的用法?

在这些帖子中,他们总是遇到 CPU 使用率停留在 100% 的问题,即使这是不正确的。我一直在尝试 System.Threading.Thread.Sleep(1000)。但这会将整个游戏锁定为 1fps,因为它每秒等待 1 秒。即使有 1fps,我也无法获得 100% 的其他读数。

在这段代码中,我使用了睡眠线程,它将游戏速度降低到 1fps

using UnityEngine;
using System.Diagnostics;
using TMPro;

public class DebugUIManager : MonoBehaviour
{
    private PerformanceCounter cpuCounter;
    [SerializeField] private TMP_Text cpuCounterText;

    private void Start()
    {
        cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total");
    }

    private void Update()
    {
        cpuCounterText.text = getCurrentCpuUsage();
    }

    private string getCurrentCpuUsage()
    {
        dynamic firstValue = cpuCounter.NextValue() + "% CPU";
        System.Threading.Thread.Sleep(1000);
        dynamic secondValue = cpuCounter.NextValue() + "% CPU";

        return secondValue;
    }
}

每当我改变

    private string getCurrentCpuUsage()
    {
        dynamic firstValue = cpuCounter.NextValue() + "% CPU";
        System.Threading.Thread.Sleep(1000);
        dynamic secondValue = cpuCounter.NextValue() + "% CPU";

        return secondValue;
    }

    private string getCurrentCpuUsage()
    {
        return cpuCounter.NextValue() + "%";
    }

游戏不会以fps下降,但它也没有做任何事情。

我没有收到任何错误消息,因为它运行没有问题。但我真的很想知道如何获得 CPU 使用率,所以我可以自己弄清楚其余的。

任何有帮助的答案将不胜感激。

标签: c#unity3d.net-4.0

解决方案


我试过了,也无法PerformanceCounter正常运行(总是100%像你一样返回)

但是我在这里找到了一个很好的选择并用它来重建你DebugUIManager

using System;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using TMPro;
using UnityEngine;

public class DebugUIManager : MonoBehaviour
{
    [Header("Components")]

    [SerializeField] private TMP_Text cpuCounterText;

    [Header("Settings")]

    [Tooltip("In which interval should the CPU usage be updated?")]
    [SerializeField] private float updateInterval = 1;

    [Tooltip("The amount of physical CPU cores")]
    [SerializeField] private int processorCount;


    [Header("Output")]
    public float CpuUsage;

    private Thread _cpuThread;
    private float _lasCpuUsage;

    private void Start()
    {
        Application.runInBackground = true;

        cpuCounterText.text = "0% CPU";

        // setup the thread
        _cpuThread = new Thread(UpdateCPUUsage)
        {
            IsBackground = true,
            // we don't want that our measurement thread
            // steals performance
            Priority = System.Threading.ThreadPriority.BelowNormal
        };

        // start the cpu usage thread
        _cpuThread.Start();
    }

    private void OnValidate()
    {
        // We want only the physical cores but usually
        // this returns the twice as many virtual core count
        //
        // if this returns a wrong value for you comment this method out
        // and set the value manually
        processorCount = SystemInfo.processorCount / 2;
    }

    private void OnDestroy()
    {
        // Just to be sure kill the thread if this object is destroyed
        _cpuThread?.Abort();
    }

    private void Update()
    {
        // for more efficiency skip if nothing has changed
        if (Mathf.Approximately(_lasCpuUsage, CpuUsage)) return;

        // the first two values will always be "wrong"
        // until _lastCpuTime is initialized correctly
        // so simply ignore values that are out of the possible range
        if (CpuUsage < 0 || CpuUsage > 100) return;

        // I used a float instead of int for the % so use the ToString you like for displaying it
        cpuCounterText.text = CpuUsage.ToString("F1") + "% CPU";

        // Update the value of _lasCpuUsage
        _lasCpuUsage = CpuUsage;
    }

    /// <summary>
    /// Runs in Thread
    /// </summary>
    private void UpdateCPUUsage()
    {
        var lastCpuTime = new TimeSpan(0);

        // This is ok since this is executed in a background thread
        while (true)
        {
            var cpuTime = new TimeSpan(0);

            // Get a list of all running processes in this PC
            var AllProcesses = Process.GetProcesses();

            // Sum up the total processor time of all running processes
            cpuTime = AllProcesses.Aggregate(cpuTime, (current, process) => current + process.TotalProcessorTime);

            // get the difference between the total sum of processor times
            // and the last time we called this
            var newCPUTime = cpuTime - lastCpuTime;

            // update the value of _lastCpuTime
            lastCpuTime = cpuTime;

            // The value we look for is the difference, so the processor time all processes together used
            // since the last time we called this divided by the time we waited
            // Then since the performance was optionally spread equally over all physical CPUs
            // we also divide by the physical CPU count
            CpuUsage = 100f * (float)newCPUTime.TotalSeconds / updateInterval / processorCount;

            // Wait for UpdateInterval
            Thread.Sleep(Mathf.RoundToInt(updateInterval * 1000));
        }
    }
}

在此处输入图像描述


推荐阅读