Author Archives: lovewcycle

【Unity6】Macでビルドしたものを実行した際にGameMode通知が出るのに対応する

Unity6.2(6000.2.7f2), MacOS Sequoia 15.6で動作を確認しています

問題

Macでビルドしたアプリケーションを実行した際に
以下のような通知が出てくることがあります

これはmacOSSequoia(15.0以降)で導入されたGameMode機能を使用するということですね
Unityを使ってゲームを作っているのであれば
パフォーマンスが優先されるのでとても助かる機能であるかと思います。

しかし
デスクトップ常駐型のゲームなどを作っている場合にも
パフォーマンスが優先されてしまうと困る場合があるかと思います。

原因

そもそもGameModeの判定をどこで行っているのかということですが
ビルド後のアプリケーションのplistの中に

LSApplicationCategoryType
public.app-category.games

のような記述がありそこで判定していることが予測できます。
xcodeでplistを開くと他のカテゴリなども見ることができますね。

対応策

UnityのPostProcessでビルド後にplistを書き換えて対応します。
メソッドのみを切り出し示します。


/// <summary>
/// plistを編集してCategoryをgamesからutilitiesに変更し、MacOSのGame Mode通知を無効化する
/// </summary>
/// <param name="report"></param>
private void DisableMacOSGameModeNotification(BuildReport report)
{
	if (report.summary.platform != BuildTarget.StandaloneOSX)
	{
		return;
	}

	string pathToBuiltProject = report.summary.outputPath;
	string plistPath = Path.Combine(pathToBuiltProject, "Contents", "Info.plist");

	if (File.Exists(plistPath))
	{
		string plistContent = File.ReadAllText(plistPath);
		bool modified = false;

		// Unity側で書き込まれる
		// public.app-category.games を別のカテゴリに置き換え
		if (plistContent.Contains("public.app-category.games"))
		{
			plistContent = plistContent.Replace(
				"public.app-category.games",
				"public.app-category.utilities"
			);
			modified = true;
			Debug.Log("Info.plist updated: Changed category from games to utilities");
		}
		else if (!plistContent.Contains("LSApplicationCategoryType"))
		{
			// カテゴリが存在しない場合は追加
			int lastDictIndex = plistContent.LastIndexOf("</dict>");
			if (lastDictIndex > 0)
			{
				string insertion = "\t<key>LSApplicationCategoryType</key>\n\t<string>public.app-category.utilities</string>\n";
				plistContent = plistContent.Insert(lastDictIndex, insertion);
				modified = true;
				Debug.Log("Info.plist updated: Added utilities category");
			}
		}
		else
		{
			Debug.Log("LSApplicationCategoryType already set to non-games category");
		}

		if (modified)
		{
			File.WriteAllText(plistPath, plistContent);
			Debug.Log("Info.plist file saved successfully");
		}
	}
	else
	{
		Debug.LogError($"Info.plist not found at: {plistPath}");
	}
}

このコードをIPostprocessBuildWithReportを継承したクラスの
OnPostprocessBuildで呼べば動作します。

今回は便宜上utilitiesにしていますが
Game以外であれば多分GameModeにはならないかと思います。

【Unity6】 Splash Screen Unity Logoが含まれてビルドサイズが増加するのを防ぐ

Unity6000.1.9f1で動作を確認しています

問題

空の2DのURPのプロジェクトをビルドした際に
ログからビルドサイズを確認したところ

2.7mbのSplash Screen Unity Logo
が含まれていることに気がつきました。

PlayerSettingからSplashScreenはOffになっているのにもかかわらず
ビルドに含まれているのはもったいないですね。

対応策

軽く調べたらUnityのフォーラムにも同様な問題が上がっていましたが特に解決されていませんでしたが
手元で以下のような操作を行うとビルドに含まれなくなることが確認できました

1.Show Unity Logoのチェックマークを先に外す
2.そのあとShowSplashScreenのチェックマークを外す

スプラッシュを出したくないという目的では
ShowSplashScreenの方をOffにしてしまう可能性が高いので
修正して欲しいですね〜

【UE5】 DataTableの選択肢をフィルタリングする

以前書いた記事では
データテーブルの要素を取り出す事はできましたが
データテーブルが必要であるときにはフィルタリングできていませんでした。

こちらでフィルタリング機能についての議論がなされており
使用にあたって若干曲があることが伺えます.

UPROPERTY(EditDefaultsOnly,meta=(RowType="/Script/TESTProject.MyDataTable"))
UDataTable* DT_Test;
UPROPERTY(EditDefaultsOnly, Meta=(RequiredAssetDataTags="/Script/TESTProject.MyDataTable"))
TObjectPtr<UDataTable> DT_Test2;

これらは手元のUE5.3.2環境では動作しませんでした。
(コードに誤りがあるかもしれません)
上記のリンク内では動作していたような記述もあるので以前のバージョンでは使用できていたのかもしれません。

対応方法

UPROPERTY(EditDefaultsOnly, meta = (RequiredAssetDataTags = "RowStructure=/Script/TESTProject.MyDataTable"))
UDataTable* DT_Test;

こちらのコードでは動作することが確認できました。

RowStructur=~がかなり冗長になっており
metaの中では文字列結合やマクロを使用する事ができないのでプロパティ毎に書かないといけないため
使い勝手はあまり良くないかもしれません。

RowTypeのほうが使えればきれいに書けるのですが
バグなら早く治ってほしいですね…

【UE5】 WidgetのNavigationを両方のスティックで移動できるようにする

UEの標準の機能であるNavigationを使用してWidgetの選択しているボタンを移動する実装を行った際に対応したことのメモ

症状

Navigation機能を使用してWidgetの移動を実装している際
GamePadを使用したときに特にconfigを設定しないと左スティックのみでしか動かない状態になっているかと思います。

まずは他のキーでも移動ができるように
ヒストリア様のこちらの記事を参考に実装しました。

記事を参考に追加したキーでの移動はできるようになったのですが
以下のようにスティックを追加しても片方のスティックの入力しか動作しないままでした。

KeyEventRules.Emplace(EKeys::Gamepad_LeftStick_Up, EUINavigation::Up);
KeyEventRules.Emplace(EKeys::Gamepad_LeftStick_Down, EUINavigation::Down);
KeyEventRules.Emplace(EKeys::Gamepad_LeftStick_Left, EUINavigation::Left);
KeyEventRules.Emplace(EKeys::Gamepad_LeftStick_Right, EUINavigation::Right);

調査

FNavigationConfig.cppのコンストラクタで以下のようにデフォルト値が定義されています。

FNavigationConfig::FNavigationConfig()
	: bTabNavigation(true)
	, bKeyNavigation(true)
	, bAnalogNavigation(true)
	, AnalogNavigationHorizontalThreshold(0.50f)
	, AnalogNavigationVerticalThreshold(0.50f)
{
	AnalogHorizontalKey = EKeys::Gamepad_LeftX;
	AnalogVerticalKey = EKeys::Gamepad_LeftY;

	KeyEventRules.Emplace(EKeys::Left, EUINavigation::Left);
	KeyEventRules.Emplace(EKeys::Gamepad_DPad_Left, EUINavigation::Left);

	KeyEventRules.Emplace(EKeys::Right, EUINavigation::Right);
	KeyEventRules.Emplace(EKeys::Gamepad_DPad_Right, EUINavigation::Right);

	KeyEventRules.Emplace(EKeys::Up, EUINavigation::Up);
	KeyEventRules.Emplace(EKeys::Gamepad_DPad_Up, EUINavigation::Up);

	KeyEventRules.Emplace(EKeys::Down, EUINavigation::Down);
	KeyEventRules.Emplace(EKeys::Gamepad_DPad_Down, EUINavigation::Down);
}

ここでどのスティックを使用するかを設定しているようでした。

AnalogHorizontalKey = EKeys::Gamepad_LeftX;
AnalogVerticalKey = EKeys::Gamepad_LeftY;

つまり右スティックを使用したい場合には派生先で以下のように書き換えることになります。

AnalogHorizontalKey = EKeys::Gamepad_RightX;
AnalogVerticalKey = EKeys::Gamepad_RightY;

しかし今回実現したいのは両方のスティックなので少し違います。

FNavigationConfig.hに以下のようなクラスが用意されています。

/** A Navigation config that supports UI Navigation with both analog sticks + D-Pad. */
class FTwinStickNavigationConfig : public FNavigationConfig
{
public:
	SLATE_API FTwinStickNavigationConfig();
	
protected:
	SLATE_API virtual bool IsAnalogHorizontalKey(const FKey& InKey) const override;
	SLATE_API virtual bool IsAnalogVerticalKey(const FKey& InKey) const override;
};

つまり、FNavigationConfigではなくFTwinStickNavigationConfigを継承したクラスを作成して
そちらを使用することで両方のスティックを動作させる事が可能です。

対応方法

最終的には以下のようなクラスを作成して、GameInstanceで設定することで両方のスティックでの移動が実現できました。

class YOUR_GAME_API FMyCustomTwinStickNavigationConfig : public FTwinStickNavigationConfig
{
public:
	FMYCustomTwinStickNavigationConfig();
};

inline FMYCustomTwinStickNavigationConfig::FMYCustomTwinStickNavigationConfig()
{
        //WASDキーでNavigation移動できるように
	KeyEventRules.Emplace(EKeys::A, EUINavigation::Left);
	KeyEventRules.Emplace(EKeys::D, EUINavigation::Right);
	KeyEventRules.Emplace(EKeys::W, EUINavigation::Up);
	KeyEventRules.Emplace(EKeys::S, EUINavigation::Down);
}

【UE5】 UE5 Localizationがパッケージで動作しなかった問題

結論から書くと
Internationalization SupportがEnglishになっていたのが問題でした。

UEで多言語化を実装していたときに遭遇した問題の解決方法のメモ

症状

多言語化対応は英語、日本語、中国語(簡体字)、中国語(繁体字)
EditorのStandAloneでは正常に表示、言語の切り替えができていたのに
パッケージングすると英語 <-> 日本語のみしか正常に動作しなくなっていた。

対応.1

ProjectSettings -> Packaging ->Licalizations to Package
で必要な言語を選択

対応.2

ProjectSettings -> Packaging -> Internationalization Support
に適切なものを設定
どれが適切かは、対応する言語によって異なるので
こちらを確認して対応する必要があります。

その他の多言語化周りの細かい設定部分についてこちらの公式ページにまとまっているので
ここを読むのが正しい情報を得られると思います。