[Unity] UnityからWINAPIをコールする

UnityからWINAPIをコールする方法のメモ書きです。
WINAPIを呼び出すので、Windows環境限定の機能となります。

■前提条件
WINAPIを直接呼び出す手段は当然ながらUnityではサポートされていません。
WINAPIはカーネルとなるDLLとして存在します。
C#にはDLLで定義されている関数をコールする機能が存在するため、これを使えばWINAPIを呼び出すことが可能です。

しかし、ここに大きな落とし穴があります。
この外部DLLを扱えるのはUnity Pro版のみということです。
無料版でDLLの関数をコールしようとすると「This plugin is only supported in Unity Pro」という警告が出てコールに失敗します。

Unityアセットではない外部ライブラリをプラグインとして使用する場合も同様です。
Pro版がある場合は次の手順にてWINAPIの関数をコールできます。

■手順
今回はWindowsの様々な構成情報が取得できるGetSystemMetrics()関数をコールてみたいと思います。

まず、C#のスクリプトにてGetSystemMetrics()関数をコールできるようにします。

WinApi.cs

using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;

// WINAPIを定義するクラス
public class WinApi : MonoBehaviour {
    // 関数定義
    [DllImport("User32", EntryPoint = "GetSystemMetrics")]
    public static extern int GetSystemMetrics(SystemMetrics nIndex);

    // 引数値(今回はスクリーンサイズのみ)
    public enum SystemMetrics : int {
        SM_CXSCREEN = 0,
        SM_CYSCREEN = 1,
    };
}

public static extern int GetSystemMetrics(SystemMetrics nIndex);が実際にC#側から呼び出されるWINAPIの関数です。
その頭には属性[DllImport(“User32”, EntryPoint = “GetSystemMetrics”)]を定義しています。
DllImportはDLLをインポートする記述で第1引数にDLLファイル名を指定します。
拡張子(.DLL)は省略して構いません。
第2引数には関数名を指定します。

上記で定義したGetSystemMetrics()関数の引数はint型ですが、MSDNのドキュメントではシンボルで定義されています。
これに合わせてSystemMetricsというenum型を定義してGetSystemMetrics()関数の引数に指定するようにしました。

準備が出来たら実際に呼び出してみます。

DllTest.cs

using UnityEngine;
using System.Collections;

public class DllTest : MonoBehaviour {
    void Update() {
        if ( Input.GetKeyDown(KeyCode.Space) ) {
            // スペースキー押されたら画面の解像度を表示
            var screenWidth = WinApi.GetSystemMetrics(WinApi.SystemMetrics.SM_CXSCREEN);
            var screenHeight = WinApi.GetSystemMetrics(WinApi.SystemMetrics.SM_CYSCREEN);

            Debug.Log("screenWidth = " + screenWidth + ", screenHeight = " + screenHeight);
        }
    }
}

上記スクリプトをGameObjectにアタッチして実行し、スペースキーを押すと以下のように画面の解像度が表示されるはずです。

screenWidth = 1920, screenHeight = 1080
UnityEngine.Debug:Log(Object)
DllTest:Update() (at Assets/DllTest.cs:11)

WINAPIをコールする時点でクロスプラットフォームの利点を殺すことになるので、使用は極力避けるべきです。
どうしても使わざるを得なくなった場合の最終手段として考えていただければ良いと思います。

■参考サイト
UnityでC++のコードを呼び出すのを検証中 – Qiita
[C#] フォームの枠(サイズ変更可能なウィンドウ枠)の幅と高さを取得する
GetSystemMetrics