はじめに
UNET使ってて専用サーバとしてビルドしたときはHeadlessモードで実行/ビルドするのが良いらしいのですが、いざやってみるとNetworkManager.StartServer()
を呼び出すボタンをクリックできない→専用サーバとして起動できないことに気づきました(そもそもUI表示しないモードだって話)。
調べたところランタイムでHeadlessモードかどうかを知るためのAPIはなく、自分でゴニョゴニョして判断する必要がありました。
Headlessモードとは
Unity スタンドアロンプレイヤーのコマンドライン引数(公式のマニュアル)から引用。
ゲームは何も表示せず、ユーザー入力を受付しません。これはネットワークゲーム でのサーバー実行に最も便利です。
Headlessモードで起動する
ビルドしたアプリ起動時にコマンドライン引数「-batchmode」をつけるとHeadlessモードになります。
Macだと $ open (アプリ名).app --args -batchmode
で起動。
Headlessモードでビルドする
「Build Settings」で Target Platform を「Linux」にしてから「Development Build」のチェックを外して「Headless Mode」のチェックボックスにチェックを入れてビルド。
(公式マニュアルのスクショ)
Target Platform を「Linux」にしないとそもそもチェックボックスが表示されず、「Development Build」にチェックが入っていると「Headless Mode」のチェックボックスにチェックできないので注意。
エディタAPIでビルドオプションのHeadlessモードをtrue
にする
EditorUserBuildSettings.enableHeadlessMode
というAPIがあります。UnityCloudBuildを使ってる場合はこのAPIを使うみたいです。
参考:How to enable headless mode on Unity Could Build?
確認方法
2パターンあるみたいです。
2019/9/13追記
ドキュメントをたどった限りではUnity2018.2からバッチモードかどうか判断するためのAPIが追加されたみたいなので、そちらを使うと良さそうです。
Application.isBatchMode(公式ドキュメント)
追記ここまで
SystemInfo.graphicsDeviceType
で判断する
Detect Headless Mode in Unity から引用
using UnityEngine.Rendering;
>
// detect headless mode (which has graphicsDeviceType Null)
bool IsHeadless() {
return SystemInfo.graphicsDeviceType == GraphicsDeviceType.Null;
}
SystemInfo.graphicsDeviceID
で判断する
Determine if Unity is running in batch mode/headless mode から引用
Checking SystemInfo.graphicsDeviceID == 0 works.
「へ〜」と思ってiOS用にビルドしたらtrue
を返しました。/(^o^)\ Windowsだとうまく動くのかな。こっちの方法はおすすめしません。
Macのスタンドアロンだと別な方法が必要
「なるほどな〜」と思ってMacのスタンドアロンでビルドしたら-batchmode
の引数つけてもなぜか先述の値がどっちも変化しなかったので、単純にコマンドライン引数で判断するのが良さそうでした(参考:Read Command Line Arguments)。
return System.Environment.GetCommandLineArgs().Any(arg => arg == "-batchmode");
ちなみに-batchmode
で起動してみてSystemInfo
の値を全部調べたらSystemInfo.graphicsMultiThreaded
だけtrue
だったのがfalse
になりました。でもこの値で判断するのは流石にちょっと。。。
まとめ
以下のコードで判断するのがいいと思われます。
public bool isHeadlessMode
{
if (Application.isMobilePlatform)
{
return false;
}
#if UNITY_STANDALONE_OSX
return System.Environment.GetCommandLineArgs().Any(arg => arg == "-batchmode");
#else
return SystemInfo.graphicsDeviceType == GraphicsDeviceType.Null;
#endif
}