愛をもってゲームをつくるゴリラのブログ

UE5勉強中のゴリラがいろいろ頑張ります。

ゲーム内の1日のサイクルをつくる

はじめに

シミュレーションゲーム等で
必要となってくる、ゲーム内のサイクルの構築について説明いたします。

サンプルプロジェクト

GooglDriveにてサンプルプロジェクトを配布しています。
作りに不明な点ありましたらご連絡ください。

drive.google.com

バージョン

ソースコードも含めていますので、ビルド環境が必要となります。
以下の環境で作成しました。
UE4 Ver.4.24.0
Microsoft VisualStudio Community 2017 - Ver.15.9.5

実装解説

DayCycleGameStateBase.h

今回、時間の計算はGameState で行っています。
マルチプレイヤーにしない前提で作成していますので、
親クラスを GameStateBase クラスで作成します。 今回用意した変数は以下になります。

時間の計算に必要となるのは下記の3つになります。

//! 1日の時間を 24:00 とすると 2400
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "DayCycle")
float MaxDay;

//! ゲーム内の1日の長さ[分] (Default は 10分)
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "DayCycle")
float DayLength;

//! ゲーム内時間の表示間隔[分](Default は 5分間隔)
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "DayCycle")
int32 MinuteInterval;

サンプルプロジェクトではWidgetで現在時刻を表示したり、
時間によって太陽の位置と空の色を変えるために、 イベントディスパッチャーを用意しました。

// 1つ引数を取り、型がfloatで引数名がTimeOfDay のイベントディスパッチャー宣言
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FTimeOfDayEventDispatcher, float, TimeOfDay);
// 2つ引数を取り、型がint32で引数名がHour, Minute のイベントディスパッチャー宣言
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FTimeEventDispatcher, int32, Hour, int32,  Minute);

UPROPERTY(BlueprintAssignable, Category = "DayCycle")
FTimeOfDayEventDispatcher OnTimeOfDayDispatcher;

UPROPERTY(BlueprintAssignable, Category = "DayCycle")
FTimeEventDispatcher OnTimeDispatcher;

DayCycleGameStateBase.cpp

TimeOfDay += (MaxDay/ (DayLength * 60.f)) * DeltaSeconds ;

(MaxDay/ (DayLength * 60.f)) は 1秒に増えるゲーム内の時間を計算しています。
そこに DeltaSeconds をかけることで、1フレームに増えるゲーム内の時間となります。

TimeOfDay = FMath::Fmod(TimeOfDay, MaxDay) ;

こちらは 24:00 をまわると 0:00 になるように 1日の時間で割った余りを現在のゲーム時間としています。

俺のゲームは 1日の時間は 36 時間だ! という人は MaxDay を 3600 に設定してください。

Hour = TimeOfDay / 100.f;
int32 tmp = FMath::Fmod(TimeOfDay, 100.f) * 0.6f;

何時の計算は TimeOfDay を 100で割った値で算出していて、
何分の計算は 100で割った余りに0.6をかけて 最大値が 60 になるように補間をしています。

Minute = tmp / MinuteInterval;
Minute *= MinuteInterval;

MinuteIntervalに設定した分単位になるように計算を行っています。

W_DayCycle

f:id:m-goolee-y:20191221013514p:plain

DayCycleGameStateBase で用意した OnTimeDispather で現在時刻(何時何分)を
取得してテキストに反映しています。

BP_DayCycleSky

f:id:m-goolee-y:20191221014624p:plain

BP_SkySphere を親クラスにして空の色の変化は BP_SkySphere の処理をそのまま使っています。
現在時刻に合わせた太陽の位置を計算してディレクショナルライトを回転させています。

まとめ

濃い内容ではありませんでしたが、ゲーム内の1日のサイクルが作れたかと思います。

前回のこちらの記事と合わせたAIのスケジュール機能について次回は書きたいと考えています。

goolee.hatenablog.com

何か質問や、ご指摘等ありましたら、ぜひぜひご連絡ください。