ぼっちプログラマのメモ

UE4とかVRとかについて書いたり書かなかったり。

Anim Nodeに不正な値が設定された際に、ノードを Warning / Error 表示にしたり AnimBPをコンパイルエラーにする方法について

ログにErrorやWarning出しても気づかない可能性があるので、NodeをError, Warning状態にしたりエラーを発生させようというお話です。なお、AnimNode, AnimGraphNode という単語が出てきますが本記事ではそれについて解説しません。以下の記事が参考になるかと思います
UE4 アニメ―ションノードの作成(ボーンのトランスフォーム)を試してみる - Qiita

はじめに

自作の疑似物理プラグインKawaii Physics」にて、Anim Nodeをとある設定にするとクラッシュするという報告を受けました。

f:id:pafuhana1213:20200516165718p:plain
Rootと同じボーンをExcludeBoneに指定するとクラッシュするバグを修正 by kyi · Pull Request #12 · pafuhana1213/KawaiiPhysics · GitHub


クラッシュを回避すること自体は簡単だったのですが、事実上ノードが機能しなくなるので「不正な値がノードに設定されているよ!修正してね!」ということを作業者に伝えたい所です。また、ログに出力する対応が実装楽ですが…ログを確認してくれないことは稀によくあるので効果としては薄くなることが多いです。
[UE4] UE_LOGについてあれこれ|株式会社ヒストリア


ということで、Anm Nodeに不正な値が設定された際に「問題が発生していることがひと目で分かる」 & 「修正を促す」方法を探して見つけたのが、ValidateAnimNodePostCompile 関数です。下図のように、ERROR! や WARNING! 表示にできる上にAnimBPのコンパイルエラーも起こすことができます!
f:id:pafuhana1213:20200516170926p:plain

コンパイルエラーを起こせるのがとても素敵です。エラーを修正しないとAnimBPを動作させることができないので作業者に修正を強いることができます。また、パッケージ作成時にも同様にError / Warning出力 & パッケージ作成が発生するため、不正な値が入っている状態でパッケージが作られてしまうことを回避できます!

それではValidateAnimNodePostCompile 関数をどのようにして使うのかについて説明します。といっても超簡単です。

続きを読む

【UE4 Android】アプリのバージョン情報(VersionCode, VersionName)を設定・取得する方法について

記事作成のリハビリを兼ねて、先日調べた内容をサクッと書いてみる
検証バージョンは UE4.25.0

はじめに

Androidアプリのバージョン情報には整数のVersionCode と 文字列の VersionNameの2つがあります。
VersionCodeはストア上での管理で用いられるものです。そして、過去にストアにアップロードしたVersionCodeとの重複が許されないため、ストアにアップするたびに値を追加する必要があります。
VersionNameはユーザへの表示のみを目的としたもので自由に設定することが可能です(例:1.2.3-beta)

参考:
アプリのバージョニング  |  Android デベロッパー  |  Android Developers
versionCodeとversionNameの 違い | アプリ開発のお勉強! アプリリ

バージョン情報の設定方法について

一般的なAndroid開発の場合は build.gradle という名前のファイルにVersionCode, VersionNameを記述するのですが、UE4を使ったAndroid開発の場合はプロジェクト設定で記述することになります。
f:id:pafuhana1213:20200509161407p:plain

上の赤枠のStore Version が Version Code、下の赤枠のVersion Displayが Version Name にあたります。
(名前合わせたほうが混乱しなかったのでは…)

Store Version Offsetで設定した値は、横にある( )内のCPUをサポートするアプリのStore Version に加算されます。そのため、例えばプロジェクト設定のPlatform - Android にあるBuildカテゴリの設定を以下のようにすると、作成したパッケージ( APK )のVersionCodeは10+1=11になります。
f:id:pafuhana1213:20200509162156p:plain

ここでカンの良い人は ↑↑図のStore Version Offsetの設定は破綻する可能性があることに気づきます!いったい何が問題なのでしょうか…?






はじめに設定した通り、Version Codeは重複が許されません。そのため、armv7 対応版と arm64対応版をそれぞれストアにアップするプロジェクトの場合、 Store Versionを「11」に設定してアップしようとすると armv7 版は VersionCodeの重複が原因で失敗するはずです。

そのため、実際にStore Version Offsetを運用する際は以下のように重複を回避することを考慮する必要があります。ちなみに、 パッケージが1種類だけプロジェクトの場合は Store Version Offsetを 初期値の0から変更する必要はありません。
f:id:pafuhana1213:20200509163248p:plain

バージョン情報の取得方法について

アプリを更新するかしないかの判定など、 アプリ起動中にStoreVersionを知りたいケースが時々あるかと思います。ということで取得方法についてもご紹介。

プロジェクト設定で設定したStoreVersion や VersionNameなどは UAndroidRuntimeSettings で保持されています。そのため、

.h ファイル

#pragma once

#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "AndroidRuntimeSettings.h"
#include "MyBlueprintFunctionLibrary.generated.h"

/**
 * 
 */
UCLASS()
class BUILD0425_API UMyBlueprintFunctionLibrary : public UBlueprintFunctionLibrary
{
	GENERATED_BODY()

	UFUNCTION(BlueprintCallable)
	static int GetStoreVersion();

};

.cpp ファイル

#include "MyBlueprintFunctionLibrary.h"

int UMyBlueprintFunctionLibrary::GetStoreVersion()
{
	return GetMutableDefault<UAndroidRuntimeSettings>()->StoreVersion;
}

.build.cs 以下の内容を追加

PrivateDependencyModuleNames.AddRange(new string[] {"AndroidRuntimeSettings" } );

とすることで、StoreVersionを取得することが可能です。
f:id:pafuhana1213:20200509164548p:plain


VersionCode ではなく、StoreVersionであることに注意です! 繰り返しになりますが、VersionCode は StoreVersion とStore Version Offset を足したものです。そのため、VersionCodeの値が欲しい場合は UAndroidRuntimeSettingsが持つ以下のプロパティの値も取得する必要があります。

// Offset to add to store version for APKs generated for armv7
UPROPERTY(GlobalConfig, EditAnywhere, Category = "APK Packaging", meta = (DisplayName = "Store Version offset (armv7)"))
int32 StoreVersionOffsetArmV7;

// Offset to add to store version for APKs generated for arm64
UPROPERTY(GlobalConfig, EditAnywhere, Category = "APK Packaging", meta = (DisplayName = "Store Version offset (arm64)"))
int32 StoreVersionOffsetArm64;

// Offset to add to store version for APKs generated for x86_64
UPROPERTY(GlobalConfig, EditAnywhere, Category = "APK Packaging", meta = (DisplayName = "Store Version offset (x86_64)"))
int32 StoreVersionOffsetX8664;

おしまい

余談:
In-app updates for games のベータが最近公開されたけども今後はこれが主流になっていくのかしら…?
developers-jp.googleblog.com

UE4.23から入った「Editor Validator Subsystem」を使って、アセット保存時などで走るチェック処理(Validate Assets)を拡張しよう!

追記

公開当初は「4.24から入った」というタイトルでしたが…4.23からでしたああああああああああああ
申し訳ありませんんんんんんんんんんんんんんんんんんんんんんんんんんんんんんんんんんんんんんんんn

はじめに

SubSystemって何?という方はまず以下のページをご確認ください。
プログラミング サブシステム | Unreal Engine ドキュメント

UE4.24でEdiorSubSystem継承のSubSystemが幾つか追加されています。そして、その中のEditor Validator Subsystemはアセット保存時などで走るチェック処理(Validate Assets)を簡単に拡張できるという非常に強力な仕組みです!例えば「対象のStatic MeshアセットがLODを持っていない場合はエラーを出す」というチェック・通知処理をBPでサクッと作ることができます

このような仕組みを用意することで「不適切な設定なアセットが混じることで余分な負荷・エラーが発生する」ことを防止できます。特に中規模・大規模プロジェクトでは致命的になりがちなので早めの段階で用意しておきましょう!

Editor Validator Subsystemの使い方

「対象のStatic MeshアセットがLODを持っていない場合はエラーを出す」を例にどのようにしてEditor Validator Subsystemを使うのかを説明します。

Editor Utility Blueprintを作成

f:id:pafuhana1213:20191231221303p:plain
f:id:pafuhana1213:20191231221737p:plain
はじめに、EditorValidatorBaseクラスをベースにしてEditor Utility Blueprintを作成します。この作成したBPにて「チェック対象にするクラスの指定」と「対象のアセットに対して行うチェック処理」を実装していきます。

チェック対象にするクラスを指定

f:id:pafuhana1213:20191231221942p:plain
f:id:pafuhana1213:20191231222034p:plain
まずはCan Validate Asset関数をオーバーライドし、どのアセットクラスを対象とするか指定します。今回はStatic Meshアセットを対象とするので上図のようにします。

対象のアセットに対して行うチェック処理を実装

f:id:pafuhana1213:20191231223442p:plain
f:id:pafuhana1213:20191231224247p:plain
次にValidate Loaded Asset関数をオーバーライドし、チェック処理の内容を書いていきます。

チェック処理を通過した場合は、Asset Passesノードを呼び、ReturnノードでValidを返します。
チェック処理に引っかかった場合は、Asset Failsノードを呼び、ReturnノードでInvalidを返します。このAsset Failsノードの各引数ピンで指定する内容はエラー画面にて表示されるのでちゃんと設定しましょう!

Editor Validator SubsystemにEditor Utility Blueprintを登録(新規作成時のみ)

f:id:pafuhana1213:20191231230854p:plain
次に、Add Validatorノードを使うことで実装したチェック処理をEditor Validator Subsystemに登録します。
(BPの場合、Editor Validator SubsystemはEditor Scripting系のBPからしかアクセスできないため、EditorUtilityWidgetなどで実装する必要があります)

なお、エディタ起動時に各EditorValidatorBase継承のBPは自動的にEditor Validator Subsystemに登録されます。 そのため、上記の処理はEditorValidatorBase継承のBPの作成した後にエディタを再起動すれば不要です。(UEditorValidatorSubsystem::Initialize参照)

アセットのチェック処理を走らせてみよう

f:id:pafuhana1213:20191231232314p:plain
これで準備完了です!試しにLODを持っていないStatic Meshアセットを保存するか、右クリックメニューからチェック処理(Validate Assets)を走らせてみましょう!

f:id:pafuhana1213:20191231232401p:plain
こんな感じにエラーが出ます!最前面にウィンドウが出てくるので、ログに出力する場合と違って無視される可能性が低い…かと思います!

f:id:pafuhana1213:20191231232522p:plain
また、EditorUtilityWidgetなどから明示的にチェック処理を走らせることもできます。そのため、AssetRegistryを使って自動抽出したアセットに対してチェック処理を走らせたりすることができます。

最後に

簡単ではありましたが、Editor Validator Subsystemを使ってアセットのチェック処理を拡張する方法について紹介しました!実装が簡単な上に、エンジン標準のチェック処理に追加する形になるのでワークフローも組みやすいかとと思います。また、ログ出力と違って最前面にエラー文を出せるというのは大きな強みかと思います!是非試してみてください!

おまけ

具体的にどういう仕組みになっているのか知りたい方は UEditorValidatorSubsystem::ValidateAssets の実装をご確認ください。

おしまい

UE4標準のTimeSynth機能を使ってイントロ付きループを実装してみた

ガチ勢の皆様へ

少し長くなるかもなので先に結論から

  • ループマーカー対応の話ではありません。イントロ用・ループ用のサウンドアセットを個別に用意する必要があります
    • ゴメンナサイ
  • BPMと小節・伯単位による管理が可能になったという話です
  • アセット側で再生する小節・拍数などの設定ができますが、BPを使った実装も『少し』必要です
  • UE4.24現在でもベータ機能です
  • 処理負荷が増えるのでご注意ください
  • ○DXか○MODか○wise使えばいいじゃん…という言葉は聞こえません。…聞こえないって言ってるだろ!!!

はじめに

ステージ開始時にBGMのイントロ部分を再生し、その後はループ部分を流す『イントロ付きループ』はゲームでよく見ます(聞きます?)。…が、UE4の標準機能で実装すると様々な工夫・妥協をする必要がありました。

詳細は上記の記事を見ていただくとして…問題を簡単にまとめると以下の通りです。

  • BP, SoundCueにおけるDelayノードでは精度が足りず、イントロとループは自然にならない・安定しない
    • シームレスな音楽の連続再生を実現するにはサンプリングレートでのタイミング精度が求められる
      • 原理的に48kHzの音声ファイルなら、1秒間に48000フレーム
    • Fade In/Outによるクロスフェードでごまかす手もあるが使えないケースがある上に実装コストが少し高い

UE4初期からこの問題を抱えており、個人的にもずっとモヤモヤしていたのですが…
UE4.22で入ったTimeSynth機能を使うことで
高精度かつ(比較的)簡単にイントロループを実現可能になりました!

www.youtube.com
ということで実装してみました。素人耳ですが…たぶんいい感じかと思います!!!(音飛びは録画の問題
以降は↑の作業手順について自分用メモも兼ねて書いていきます。

続きを読む

2019年内でリリースされたUE4の各バージョンを復習してみる - UE4.22編 - (順次更新)

はじめに

年末年始で思ってたよりも時間が取れたので、
2019年内にリリースされたUE4の各バージョン(UE4.22, 23, 24)を復習。
全部はしない上にメモ代わりなので雑な文章になると思います。ご了承くださいましまし
docs.unrealengine.com

続きを読む

UE4エディタ上で、Googleスプレッドシートの内容をDataTableに反映してみた

はじめに

UE4にはDataTableという機能があり、この機能を活用することで大量のデータを効率よく管理することができます。そして、csvjsonとの連携機能を持っているため、
「みんな大好きExcelで編集」
→ 「UE4エディタが変更を検出して自動インポート( Auto-Import )」
→ 「DataTableに反映」
というフローが一般的になっています。
データ駆動型のゲームプレイエレメント | Unreal Engine ドキュメント
[UE4] CSVデータを扱う方法 DataTable編|株式会社ヒストリア
【UE4】DataTableの使い方-その① ~基本編~【★~★★】 - キンアジのブログ

ただExcelを毎回開くのが少し面倒です(環境によってはExcelがそもそもインストールされてないことも)。
また、Excelをインポート → DataTableに反映という流れの都合上、パッケージで動作中にExcelを使ったパラメータ編集をするのは難しいです。そのため、Excelを編集するたびにパッケージを作成し…という手間がありました。

なんか良い手はないかなぁと思っていた時に…

「うちはGoogleスプレッドシートからデータ抽出してるよ。そのおかげでパッケージでもデータをガンガン編集できるよ」

という講演をどこかで聞き、おお!これは実装してみよう!…と思ったのが約2年前。やっと実装してみました。

www.youtube.com
Googleスプレッドシートの内容がDataTableに無事反映されています。素晴らしい。

ということで、やってみたことを自分用メモを兼ねて書いていきます。なお、この辺りに関しては完全に初心者なのでもっといい方法があるかもしれません。ご存知の方はこそっと教えて下さい!

続きを読む

揺れ骨用自作AnimNode「Kawaii Physics」の内部実装解説的なもの その1

はじめに

疑似物理プラグインであるKawaii Physicsを先日リリースしました。髪、スカート、胸などの揺れものを「かんたんに」「かわいく」揺らすことができます。
f:id:pafuhana1213:20190726145840j:plain
f:id:pafuhana1213:20190726144035g:plain
f:id:pafuhana1213:20190726144050g:plain
github.com

エンジン標準のPhysics AssetやAnim Dynamicsは高性能かつ多機能なのですが…慣れるまでは調整大変といった声を聞こえてきたので、自作AnimNodeの勉強も兼ねて作った感じです。趣味プロジェクトです(ここ大事)。

せっかくなので、AnimNodeの自作やKawaii Pyhscisの内部実装に関して単にですがまとめようと思います(未来の自分用メモという意味合いもあります)。
これで皆さん自由に拡張・不具合修正できますね!

なお、本記事ではKawaii Physicsの使い方に関する説明はしません。そちらに関しては、Githubで公開しているサンプルと簡易ドキュメントをご確認くださいまし…。

参考

www.unrealengine.com
qiita.com
qiita.com
あと、エンジンコード

続きを読む