C++er 向け UE4.18 変更点メモ

Unreal Engine 4.18 Release Notes

上記の PROGRAMMING UPGRADE NOTES 内の記述を元に、
UE4 C++er 向けに UE4.18 でちょっと気になる変更点をピックアップしてメモ。

比較的大きい変更点

FStringAssetReference, FStringClassReference, TAssetPtr, TAssetSubclassOf のリネーム

New: As part of the cross-level actor references change, several types and headers were renamed:
FStringAssetReference is now FSoftObjectPath
FStringClassReference is now FSoftClassPath
TAssetPtr is now TSoftObjectPtr
TAssetSubclassOf is now TSoftClassPtr
StringAssetReference.h/StringClassReference.h is now SoftObjectPath.h
AssetPtr.h is now SoftObjectPtr.h

ええ・・・なにこれ・・・

変更前変更後
FStringAssetReferenceFSoftObjectPath
FStringClassReferenceFSoftClassPath
TAssetPtrTSoftObjectPtr
TAssetSubclassOfTSoftClassPtr

クラス名丸ごとリネームとはなかなかしんどい。

などと悲しみを抱えつつ、改めて、ソースコードをよく読んでみると、以下の記述が。

DEPRECATED(4.18, "FAssetPtr was renamed to FSoftObjectPtr as it is not necessarily an asset")
typedef FSoftObjectPtr FAssetPtr;

// Not deprecating these yet as it will lead to too many warnings in games
//DEPRECATED(4.18, "TAssetPtr was renamed to TSoftObjectPtr as it is not necessarily an asset")
template<class T=UObject>
using TAssetPtr = TSoftObjectPtr<T>;

//DEPRECATED(4.18, "TAssetSubclassOf was renamed to TSoftClassPtr")
template<class TClass = UObject>
using TAssetSubclassOf = TSoftClassPtr<TClass>;
// Not deprecating these yet as it will lead to too many warnings in games
//DEPRECATED(4.18, "FStringAssetReference was renamed to FSoftObjectPath as it is now not always a string and can also refer to a subobject")
typedef FSoftObjectPath FStringAssetReference;

//DEPRECATED(4.18, "FStringClassReference was renamed to FSoftClassPath")
typedef FSoftClassPath FStringClassReference;

エイリアステンプレート(C++11)と typedef が定義されている。
これなら旧クラス名でもビルドは通る

が、コードを見る限りは 「DEPRECATED をつけたかったけど、 Warning が大量に出るので仕方なくコメントアウトしてる」という状態なので、おそらく非推奨には違いない

実は、既に UE4 公式マニュアルもリネームが施されており、旧クラス名から切り替わったという事実すら書かれていない

アセットの非同期ロード
ランタイム中にアセットをロードおよびアンロードするためのメソッド。
アセットの参照

このことからみても、旧クラス名はいずれ完全に使えなくなる可能性が高い。
いつ消されても困らないように、今後はできるかぎり新クラス名で書くようにした方が安全だと思われる。

UKismetMathLibrary::RandomUnitVectorInCone の機能整理

Functions that returned random unit vectors from within cones (whether this required a stream or not) have now been refactored into degree- and radian-based counterparts. The suffix “With yaw and pitch” has also been replaced with “Elliptical” for brevity.

  • WithYawAndPitchElliptical とリネーム
  • InDegree / InRadian と 2 種類のサフィックスをつけた関数に整理
  • FRandomStream を使用したバージョンも追加

変更前

    /** 
     * Returns a random vector with length of 1, within the specified cone, with uniform random distribution. 
     * @param ConeDir   The base "center" direction of the cone.
     * @param ConeHalfAngle     The half-angle of the cone (from ConeDir to edge), in radians.
     */
    UFUNCTION(BlueprintPure, Category = "Math|Random", meta=(NotBlueprintThreadSafe))
    static FVector RandomUnitVectorInCone(FVector ConeDir, float ConeHalfAngle);

    /**
    * RandomUnitVectorWithYawAndPitch
    *
    * @param MaxYaw - The Yaw-angle of the cone (from ConeDir to horizontal-edge), in degrees.
    * @param MaxPitch - The Pitch-angle of the cone (from ConeDir to vertical-edge), in degrees.    
    */
    UFUNCTION(BlueprintPure, Category = "Math|Random", meta = (Keywords = "RandomVector", NotBlueprintThreadSafe))
    static FVector RandomUnitVectorInConeWithYawAndPitch(FVector ConeDir, float MaxYawInDegrees, float MaxPitchInDegrees);

変更後

/**
* Returns a random vector with length of 1, within the specified cone, with uniform random distribution.
* @param ConeDir The base "center" direction of the cone.
* @param ConeHalfAngleInRadians The half-angle of the cone (from ConeDir to edge), in radians.
*/
UFUNCTION(BlueprintPure, Category = "Math|Random", meta=(NotBlueprintThreadSafe))
static FVector RandomUnitVectorInConeInRadians(FVector ConeDir, float ConeHalfAngleInRadians);

/**
* Returns a random vector with length of 1, within the specified cone, with uniform random distribution.
* @param ConeDir The base "center" direction of the cone.
* @param ConeHalfAngleInDegrees The half-angle of the cone (from ConeDir to edge), in degrees.
*/
UFUNCTION(BlueprintPure, Category = "Math|Random", meta=(NotBlueprintThreadSafe))
static inline FVector RandomUnitVectorInConeInDegrees(FVector ConeDir, float ConeHalfAngleInDegrees)
{
	return RandomUnitVectorInConeInRadians(ConeDir, FMath::DegreesToRadians(ConeHalfAngleInDegrees));
}

/**
* Returns a random vector with length of 1, within the specified cone, with uniform random distribution.
* The shape of the cone can be modified according to the yaw and pitch angles.
*
* @param MaxYawInRadians The yaw angle of the cone (from ConeDir to horizontal edge), in radians.
* @param MaxPitchInRadians The pitch angle of the cone (from ConeDir to vertical edge), in radians.
*/
UFUNCTION(BlueprintPure, Category = "Math|Random", meta = (Keywords = "RandomVector Pitch Yaw", NotBlueprintThreadSafe))
static FVector RandomUnitVectorInEllipticalConeInRadians(FVector ConeDir, float MaxYawInRadians, float MaxPitchInRadians);

/**
* Returns a random vector with length of 1, within the specified cone, with uniform random distribution.
* The shape of the cone can be modified according to the yaw and pitch angles.
*
* @param MaxYawInDegrees The yaw angle of the cone (from ConeDir to horizontal edge), in degrees.
* @param MaxPitchInDegrees The pitch angle of the cone (from ConeDir to vertical edge), in degrees.
*/
UFUNCTION(BlueprintPure, Category = "Math|Random", meta = (Keywords = "RandomVector Pitch Yaw", NotBlueprintThreadSafe))
static inline FVector RandomUnitVectorInEllipticalConeInDegrees(FVector ConeDir, float MaxYawInDegrees, float MaxPitchInDegrees)
{
	return RandomUnitVectorInEllipticalConeInRadians(ConeDir, FMath::DegreesToRadians(MaxYawInDegrees), FMath::DegreesToRadians(MaxPitchInDegrees));
}
/**
* Returns a random vector with length of 1, within the specified cone, with uniform random distribution.
* @param ConeDir The base "center" direction of the cone.
* @param ConeHalfAngleInRadians The half-angle of the cone (from ConeDir to edge), in radians.
* @param Stream The random stream from which to obtain the vector.
*/
UFUNCTION(BlueprintPure, Category="Math|Random", meta = (Keywords = "RandomVector"))
static FVector RandomUnitVectorInConeInRadiansFromStream(const FVector&amp; ConeDir, float ConeHalfAngleInRadians, const FRandomStream&amp; Stream);

/**
* Returns a random vector with length of 1, within the specified cone, with uniform random distribution.
* @param ConeDir The base "center" direction of the cone.
* @param ConeHalfAngleInDegrees The half-angle of the cone (from ConeDir to edge), in degrees.
* @param Stream The random stream from which to obtain the vector.
*/
UFUNCTION(BlueprintPure, Category="Math|Random", meta = (Keywords = "RandomVector"))
static inline FVector RandomUnitVectorInConeInDegreesFromStream(const FVector&amp; ConeDir, float ConeHalfAngleInDegrees, const FRandomStream&amp; Stream)
{
	return RandomUnitVectorInConeInRadiansFromStream(ConeDir, FMath::DegreesToRadians(ConeHalfAngleInDegrees), Stream);
}

/**
* Returns a random vector with length of 1, within the specified cone, with uniform random distribution.
* The shape of the cone can be modified according to the yaw and pitch angles.
*
* @param MaxYawInRadians The yaw angle of the cone (from ConeDir to horizontal edge), in radians.
* @param MaxPitchInRadians The pitch angle of the cone (from ConeDir to vertical edge), in radians.
* @param Stream The random stream from which to obtain the vector.
*/
UFUNCTION(BlueprintPure, Category = "Math|Random", meta = (Keywords = "RandomVector"))
static FVector RandomUnitVectorInEllipticalConeInRadiansFromStream(const FVector&amp; ConeDir, float MaxYawInRadians, float MaxPitchInRadians, const FRandomStream&amp; Stream);

/**
* Returns a random vector with length of 1, within the specified cone, with uniform random distribution.
* The shape of the cone can be modified according to the yaw and pitch angles.
*
* @param MaxYawInDegrees The yaw angle of the cone (from ConeDir to horizontal edge), in degrees.
* @param MaxPitchInDegrees The pitch angle of the cone (from ConeDir to vertical edge), in degrees.
* @param Stream The random stream from which to obtain the vector.
*/
UFUNCTION(BlueprintPure, Category = "Math|Random", meta = (Keywords = "RandomVector"))
static inline FVector RandomUnitVectorInEllipticalConeInDegreesFromStream(const FVector&amp; ConeDir, float MaxYawInDegrees, float MaxPitchInDegrees, const FRandomStream&amp; Stream)
{
	return RandomUnitVectorInEllipticalConeInRadiansFromStream(ConeDir, FMath::DegreesToRadians(MaxYawInDegrees), FMath::DegreesToRadians(MaxPitchInDegrees), Stream);
}

コード上の軽微な変更点

FWaveInstance::DistanceAttenuation が追加され、一部のメンバが private

New: To implement the source bus feature, we needed to split out volume attenuation vs distance attenuation. The bus audio needs to be mixed pre-distance-attenuation to avoid getting double-attenuated as the audio is output from the buses. This added some complexity with volume setting/getting in higher level code so if you were retrieving volume of playing sounds for a custom C++ feature, you may want to look at new volume getters and setters. To help with this, we made all volume setting and getting private to wave instances (FWaveInstance).

減衰に関する項目が追加され、それに伴い Volume, VolumeMultiplier, VolumeApp が private に。
その代わりに Setter/Getter が追加されている。

struct ENGINE_API FWaveInstance
{
	// 省略
private:

	/** Current volume */
	float Volume;

	/** Volume attenuation due to distance. */
	float DistanceAttenuation;

	/** Current volume multiplier - used to zero the volume without stopping the source */
	float VolumeMultiplier;

	/** The volume of the wave instance due to application volume or tab-state */
	float VolumeApp;

public:
	// 省略

	/** Setters for various volume values on wave instances. */
	void SetVolume(const float InVolume) { Volume = InVolume; }
	void SetDistanceAttenuation(const float InDistanceAttenuation) { DistanceAttenuation = InDistanceAttenuation; }
	void SetVolumeApp(const float InVolumeApp) { VolumeApp = InVolumeApp; }
	void SetVolumeMultiplier(const float InVolumeMultiplier) { VolumeMultiplier = InVolumeMultiplier; }

	/** Returns the volume multiplier on the wave instance. */
	float GetVolumeMultiplier() const { return VolumeMultiplier; }

	/** Returns the volume of the sound including distance attenuation. */
	float GetVolumeWithDistanceAttenuation() const;

	/** Returns the distance attenuation of the source voice. */
	float GetDistanceAttenuation() const;

	/** Returns the volume due to application behavior for the wave instance. */
	float GetVolumeApp() const { return VolumeApp; }

UTexture2D 一部プロパティ削除と Getter 追加

UTexture2D::RequestedMips was removed and should be replaced by GetNumRequestedMips()
UTexture2D::ResidentMips was removed and should be replaced by GetNumResidentMips()
UTexture2D::PendingMipChangeRequestStatus was removed and streaming status should be handled through HasPendingUpdate() and IsReadyForStreaming()

RequestedMips, ResidentMips, PendingMipChangeRequestStatus が削除されている。
その代わりに Getter として GetNumRequestedMips(), GetNumResidentMips(), HasPendingUpdate() が追加。
IsReadyForStreaming() は元々存在する関数だったが const がついた。

class UTexture2D : public UTexture
{
// 136 行目
	/** true if the texture is currently being updated through StreamIn() or StreamOut(). */
	FORCEINLINE bool HasPendingUpdate() const { return PendingUpdate != nullptr; }

// 222 行目
	/** The number of mips currently in memory. */
	ENGINE_API int32 GetNumResidentMips() const;

	/** When the texture is being updated from StreamIn() or StreamOut(), returns the number of mips requested. */
	int32 GetNumRequestedMips() const;

// 322 行目
	/**
	 * Returns whether the texture is ready for streaming aka whether it has had InitRHI called on it.
	 *
	 * @return true if initialized and ready for streaming, false otherwise
	 */
	ENGINE_API bool IsReadyForStreaming() const;

Messaging モジュールの一部機能が MessagingCommon モジュールへ分離

Messaging: If you use the common helper classes, replace “Messaging” with “MessagingCommon” in your Build.cs files and remove the “Helpers/” subdirectory from your include statements (unless you actually include header files from “Messaging”, in which case you need to keep “Messaging” and add “MessagingCommon”).

MessagingCommon モジュールが追加され、Messaging モジュールのヘルパー機能がそちらに分離された。
具体的には、 Engine\Source\Runtime\Messaging\Public\Helpers 以下、

  • FileMessageAttachment.h
  • MessageBridgeBuilder.h
  • MessageEndpoint.h
  • MessageEndpointBuilder.h
  • MessageHandlers.h

が移動している。
Helper ディレクトリを挟まなくなったので、以前から使用していた場合、Build.cs に MessagingCommon を追記するだけでなく include 時のパス書き換えも必要になる。

機能追加

EditFixedOrder

New: To disable array reordering, use the metadata flag EditFixedOrder on the TArray.

UE4.18 の TArray 順序入れ替え機能(Array Reordering)を不可にする metadata。
Array Reordering に関しては以下を参照。

実際にやってみた。上が通常の TArray、下が meta=(EditFixedOrder) を付与した TArray。

細かい違いだが、ドラッグ可能を示す左端の点列の表示が消えていることが確認できる。

FSlateApplication::OnWindowDPIScaleChanged

Developers can now register a delegate with SlateApplication to tell when a window’s DPI changes

FSlateApplication に DPI スケール変更時のイベント通知用デリゲートが追加。
ランタイム不可。エディタ専用イベント。

/** Gets a delegate that is invoked in the editor when a windows dpi scale changes */
DECLARE_EVENT_OneParam(FSlateApplication, FOnWindowDPIScaleChanged, TSharedRef);
FOnWindowDPIScaleChanged& OnWindowDPIScaleChanged() { return OnWindowDPIScaleChangedEvent; }

その他

主に、簡単に調査しただけだけど、気になった内容。

IStereoRenderTargetManager インターフェースの追加

If you maintain a custom VR plugin that needs to allocate its own render targets, you now need to move the methods out of your IStereoRendering implementation into a IStereoRenderTargetManager implementation. You can reduce the amount of duplicate code by extending FXRRenderTargetManager instead of implementing the interface directly.

各 VRHMD のレンダリングの実装は基本的に IStereoRendering インターフェースの継承 (実際にはその間に FHeadMountedDisplayBase クラスを挟んでの継承) したクラスで定義されている。

UE4.18 からは、それに加えて新しく IStereoRenderTargetManager も継承するようになった。
こちらも、厳密には、直接継承しておらず、間に FXRRenderTargetManager を挟み、必要な部分のみ各自が override する実装になっている。

なお、IStereoRenderTargetManager で定義されている関数は、元は IStereoRendering にあったものがほとんど。
なので、今回の変更はコード整理のためのように思える。
特に、これを含めて HeadMountedDisplay モジュールは UE4.17 → UE4.18 の間でだいぶ構成が変わっており、XR と Prefix のつくファイルも多いので、おそらく今後の AR, MR を視野に入れての整理ではないかと思われる。

コマンドラインからのクック時にBP のネイティブ化する場合の nativizeAssets オプションが不要に

If you have a custom build pipeline that relies on UAT BuildCookRun automation for cooking and/or building, note that in 4.18 it is no longer necessary to specify the -nativizeAssets flag to enable Blueprint nativization.

代わりに、DefaultGame.ini の BlueprintNativizationMethod をみるようになったと書いてある。
これは、エディタでいうところの Project Settings – Project – Packaging にある設定項目のこと。

逆に、コマンドラインから ini ファイルの設定を上書きする場合は、

-ini:Game:[/Script/UnrealEd.ProjectPackagingSettings]:BlueprintNativizationMethod=<Disabled|Inclusive|Exclusive>

というようにオプションをつけるらしい。
この辺りはバッチでビルドしている場合などで影響が出てくると思う。