【Unity】CPU使用率を取得してみた

Post : 2023/12/3 Update : 2023/12/16

前回UnityでC#からCPU使用率を取得しようとしたら、うまくいかなった。

今回C++からパフォーマンスカウンターにアクセスして同じことをしてみる。

C++

まずはコンソールに出力してみる

▼▼▼コード全文▼▼▼

#include <Windows.h>
#include <Pdh.h>
#include <iostream>

#pragma comment(lib, "pdh.lib")

int main() 
{
    PDH_HQUERY cpuQuery;
    PDH_HCOUNTER cpuTotal;

    //パフォーマンスデータの新規クエリーを作成
    PdhOpenQuery(NULL, NULL, &cpuQuery);

    //全体のCPU使用率のカウンターをクエリーに追加
    PdhAddCounter(
        cpuQuery,
        L"\\Processor Information(_Total)\\% Processor Utility",
        NULL,
        &cpuTotal);


    // 1秒ごとにCPU使用率を表示
    for (int i = 0; i < 10; ++i) {

        PDH_FMT_COUNTERVALUE counterVal;

        //データの収集
        PdhCollectQueryData(cpuQuery);

        //CounterValue(表示可能な値)の取得
        PdhGetFormattedCounterValue(cpuTotal, PDH_FMT_DOUBLE, NULL, &counterVal);

        std::cout << "CPU Usage:" << counterVal.doubleValue << std::endl;

        Sleep(1000);
    }

    //クエリーの終了
    PdhCloseQuery(cpuQuery);

    return 0;
}
実行するとこんな感じに表示されると思います。

Unity

これをUnity側から使えるように変更します。

C++

C++側ではスレッドを立てて1秒間隔でCPU使用率を取得、変数に格納します。

#include <Windows.h>
#include <Pdh.h>
#include <thread>

#pragma comment(lib, "pdh.lib")

BOOL running = FALSE;

PDH_HQUERY cpuQuery;
PDH_HCOUNTER cpuTotal;

std::thread updateThread;

double cpuUsage;

void update();

extern "C" _declspec(dllexport) void __stdcall Start() {

    //パフォーマンスデータの新規クエリーを作成
    PdhOpenQuery(NULL, NULL, &cpuQuery);

    //全体のCPU使用率のカウンターをクエリーに追加
    PdhAddCounter(
        cpuQuery,
        L"\\Processor Information(_Total)\\% Processor Utility",
        NULL,
        &cpuTotal);

    running = TRUE;
    updateThread = std::thread(update);
}

extern "C" _declspec(dllexport) double __stdcall GetCpuUsage() {
    return cpuUsage;
}

extern "C" _declspec(dllexport) void __stdcall Stop() 
{
    running = FALSE;
    updateThread.join();
    //クエリーの終了
    PdhCloseQuery(cpuQuery);
}


void update()
{
    //データの収集(初回)
    PdhCollectQueryData(cpuQuery);
    while (running) 
    {
        // 1秒ごとにCPU使用率を取得
        Sleep(1000);

        PDH_FMT_COUNTERVALUE counterVal;

        //データの収集(前回の値からの差分)
        PdhCollectQueryData(cpuQuery);

        //CounterValueの取得
        PdhGetFormattedCounterValue(cpuTotal, PDH_FMT_DOUBLE, NULL, &counterVal);

        cpuUsage = counterVal.doubleValue;
    }
}

Unity(C#側)

UnityのUpdate関数内で取得します。(すみません適当で)

using System.Runtime.InteropServices;
using UnityEngine;

public class Scripts : MonoBehaviour
{
    static class CpuDll
    {
        [DllImport("CPU-DLL", CallingConvention = CallingConvention.StdCall)]
        public static extern int Start();

        [DllImport("CPU-DLL", CallingConvention = CallingConvention.StdCall)]
        public static extern int Stop();

        [DllImport("CPU-DLL", CallingConvention = CallingConvention.StdCall)]
        public static extern double GetCpuUsage();
    }

    void Start()
    {
        CpuDll.Start();
    }

    float elapsedTime = 0;

    void Update()
    {
        if(elapsedTime > 1) {
            Debug.Log(CpuDll.GetCpuUsage());
            elapsedTime = 0;
        }
        elapsedTime += Time.deltaTime;

    }

    private void OnApplicationQuit()
    {
        CpuDll.Stop();
    }
}

以下の感じで取得できていれば成功です!

書いてから気づいたのですが、UnityのUpdateから直接CPUを取得してもいい気がします。

以上、UnityからCPU使用率を取得する方法でした!