From dd6bf9b4ef55c293870f30ccb1d426e153e2ec00 Mon Sep 17 00:00:00 2001 From: Shun Moriya <23472415+shun126@users.noreply.github.com> Date: Tue, 23 Sep 2025 13:21:12 +0900 Subject: [PATCH 1/4] Changed DungeonRoomSensor to not spawn on the client side --- CHANGELOG.md | 8 +++ DungeonGenerator.uplugin | 15 ++-- .../Private/DungeonGenerateBase.cpp | 71 ++++++++++--------- .../Public/DungeonGenerateBase.h | 4 +- 4 files changed, 51 insertions(+), 47 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3063c48..72fe67f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Change Log - Procedural 3D Dungeon Generator Plug-in +## 20251004-1.7.8 (61) +### Changes +* Changed DungeonRoomSensor to not spawn on the client side +* Fixed several bugs +### 変更点 +* DungeonRoomSensorをクライアント側でスポーンしないように変更 +* いくつかの不具合を修正 + ## 20250903-1.7.7 (60) ### Changes * Add DungeonRoomSensorDatabase diff --git a/DungeonGenerator.uplugin b/DungeonGenerator.uplugin index 8a76e38..b42f9d9 100644 --- a/DungeonGenerator.uplugin +++ b/DungeonGenerator.uplugin @@ -1,7 +1,7 @@ { "FileVersion": 3, - "Version": 60, - "VersionName": "1.7.7", + "Version": 61, + "VersionName": "1.7.8", "FriendlyName": "Dungeon Generator", "Description": "Procedural 3d dungeon generator plugin. Easy generation of levels, mini-maps and missions.", "Category": "Procedural Systems", @@ -18,19 +18,12 @@ { "Name": "DungeonGenerator", "Type": "Runtime", - "LoadingPhase": "Default", - "PlatformAllowList": [ - "Win64", - "Android" - ] + "LoadingPhase": "Default" }, { "Name": "DungeonGeneratorEditor", "Type": "UncookedOnly", - "LoadingPhase": "Default", - "PlatformAllowList": [ - "Win64" - ] + "LoadingPhase": "Default" } ] } diff --git a/Source/DungeonGenerator/Private/DungeonGenerateBase.cpp b/Source/DungeonGenerator/Private/DungeonGenerateBase.cpp index ec87f5a..e77a93f 100644 --- a/Source/DungeonGenerator/Private/DungeonGenerateBase.cpp +++ b/Source/DungeonGenerator/Private/DungeonGenerateBase.cpp @@ -595,7 +595,7 @@ bool ADungeonGenerateBase::BeginDungeonGeneration(const UDungeonGenerateParamete // メッシュの生成 { RoomAndRoomSensorMap roomSensorCache; - CreateImplement_PrepareSpawnRoomSensor(roomSensorCache); + CreateImplement_PrepareSpawnRoomSensor(roomSensorCache, hasAuthority); CreateImplement_QueryAisleGeneration(hasAuthority); CreateImplement_AddTerrain(roomSensorCache, hasAuthority); /* @@ -1303,7 +1303,7 @@ void ADungeonGenerateBase::CreateImplement_AddPillarAndTorch(const CreateImpleme ADungeonRoomSensorBaseはリプリケートされない前提のアクターなので 必ず同期乱数(GetSynchronizedRandom)を使ってください。 */ -void ADungeonGenerateBase::CreateImplement_PrepareSpawnRoomSensor(RoomAndRoomSensorMap& roomSensorCache) const +void ADungeonGenerateBase::CreateImplement_PrepareSpawnRoomSensor(RoomAndRoomSensorMap& roomSensorCache, const bool hasAuthority) const { check(IsValid(mParameter)); @@ -1311,40 +1311,43 @@ void ADungeonGenerateBase::CreateImplement_PrepareSpawnRoomSensor(RoomAndRoomSen dungeon::Stopwatch stopwatch; #endif - // RoomSensorActorを生成 - mGenerator->ForEach([this, &roomSensorCache](const std::shared_ptr& room) - { - auto* roomSensorClass = mParameter->GetRoomSensorClass(); - if (const auto* roomSensorDatabase = mParameter->GetRoomSensorDatabase()) - { - // TODO: ダンジョンの深さを0~255に正規化する関数を検討してください - auto depthFromStart = static_cast(room->GetDepthFromStart()); - depthFromStart /= static_cast(mGenerator->GetDeepestDepthFromStart()); - const auto depthRatioFromStart = static_cast(depthFromStart * 255.f); - - roomSensorClass = roomSensorDatabase->Select( - room->GetIdentifier(), - depthRatioFromStart, - GetSynchronizedRandom() - ); - } - if (roomSensorClass) + // サーバーならRoomSensorActorを生成 + if (hasAuthority) + { + mGenerator->ForEach([this, &roomSensorCache](const std::shared_ptr& room) { - auto* roomSensorActor = SpawnRoomSensorActorDeferred( - roomSensorClass, - room->GetIdentifier(), - room->GetCenter() * mParameter->GetGridSize().To3D() + GetActorLocation(), - room->GetExtent() * mParameter->GetGridSize().To3D(), - static_cast(room->GetParts()), - static_cast(room->GetItem()), - room->GetBranchId(), - room->GetDepthFromStart(), - mGenerator->GetDeepestDepthFromStart() - ); - roomSensorCache[room.get()] = roomSensorActor; + auto* roomSensorClass = mParameter->GetRoomSensorClass(); + if (const auto* roomSensorDatabase = mParameter->GetRoomSensorDatabase()) + { + // TODO: ダンジョンの深さを0~255に正規化する関数を検討してください + auto depthFromStart = static_cast(room->GetDepthFromStart()); + depthFromStart /= static_cast(mGenerator->GetDeepestDepthFromStart()); + const auto depthRatioFromStart = static_cast(depthFromStart * 255.f); + + roomSensorClass = roomSensorDatabase->Select( + room->GetIdentifier(), + depthRatioFromStart, + GetSynchronizedRandom() + ); + } + if (roomSensorClass) + { + auto* roomSensorActor = SpawnRoomSensorActorDeferred( + roomSensorClass, + room->GetIdentifier(), + room->GetCenter() * mParameter->GetGridSize().To3D() + GetActorLocation(), + room->GetExtent() * mParameter->GetGridSize().To3D(), + static_cast(room->GetParts()), + static_cast(room->GetItem()), + room->GetBranchId(), + room->GetDepthFromStart(), + mGenerator->GetDeepestDepthFromStart() + ); + roomSensorCache[room.get()] = roomSensorActor; + } } - } - ); + ); + } #if defined(DEBUG_ENABLE_MEASURE_GENERATION_TIME) DUNGEON_GENERATOR_LOG(TEXT("Prepare spawn DungeonRoomSensor actors: %lf seconds"), stopwatch.Lap()); diff --git a/Source/DungeonGenerator/Public/DungeonGenerateBase.h b/Source/DungeonGenerator/Public/DungeonGenerateBase.h index a9b4441..9c21d6b 100644 --- a/Source/DungeonGenerator/Public/DungeonGenerateBase.h +++ b/Source/DungeonGenerator/Public/DungeonGenerateBase.h @@ -5,7 +5,7 @@ All Rights Reserved. */ #pragma once -#include "helper/DungeonRandom.h" +#include "Helper/DungeonRandom.h" #include "Mission/DungeonRoomItem.h" #include "Mission/DungeonRoomParts.h" #include "Mission/DungeonRoomProps.h" @@ -302,7 +302,7 @@ class DUNGEONGENERATOR_API ADungeonGenerateBase : public AActor void CreateImplement_AddPillarAndTorch(const CreateImplementParameter& cp, ADungeonRoomSensorBase* dungeonRoomSensorBase, const bool hasAuthority) const; // Room sensor - void CreateImplement_PrepareSpawnRoomSensor(RoomAndRoomSensorMap& roomSensorCache) const; + void CreateImplement_PrepareSpawnRoomSensor(RoomAndRoomSensorMap& roomSensorCache, const bool hasAuthority) const; static void CreateImplement_FinishSpawnRoomSensor(const RoomAndRoomSensorMap& roomSensorCache); // Navigation From c0c9466070b2b32991b9026b7a1e2dbfd98f7e34 Mon Sep 17 00:00:00 2001 From: Shun Moriya <23472415+shun126@users.noreply.github.com> Date: Thu, 25 Sep 2025 00:58:29 +0900 Subject: [PATCH 2/4] Added the ability to assist actors spawning into the aisle grid --- .../Private/DungeonGenerateActor.cpp | 1 + .../Private/DungeonGenerateBase.cpp | 65 +-- .../Private/Helper/DungeonAisleGridMap.cpp | 17 +- .../Parameter/DungeonGenerateParameter.cpp | 42 +- .../Public/DungeonBlueprint.h | 2 +- .../Public/DungeonGenerateBase.h | 18 +- .../Public/Helper/DungeonAisleGridMap.h | 29 +- .../Public/Helper/DungeonDirection.h | 16 + .../Public/Helper/DungeonRandom.h | 2 +- .../MainLevel/DungeonMainLevelScriptActor.h | 2 +- .../Public/MainLevel/DungeonPartition.h | 2 +- .../Parameter/DungeonGenerateParameter.h | 371 +++++++++++------- .../DungeonGenerateParameterFactory.h | 2 +- .../Parameter/DungeonMeshSetDatabaseFactory.h | 2 +- .../DungeonRoomSensorDatabaseFactory.h | 2 +- 15 files changed, 393 insertions(+), 180 deletions(-) diff --git a/Source/DungeonGenerator/Private/DungeonGenerateActor.cpp b/Source/DungeonGenerator/Private/DungeonGenerateActor.cpp index b479891..ff2a10a 100644 --- a/Source/DungeonGenerator/Private/DungeonGenerateActor.cpp +++ b/Source/DungeonGenerator/Private/DungeonGenerateActor.cpp @@ -16,6 +16,7 @@ ADungeonGenerateActorは配置可能(Placeable)、ADungeonGeneratedActorは配 #include "Core/Math/Vector.h" #include "Core/Voxelization/Grid.h" #include "Core/Voxelization/Voxel.h" +#include "Helper/DungeonAisleGridMap.h" #include "MainLevel/DungeonMainLevelScriptActor.h" #include "Parameter/DungeonGenerateParameter.h" #include diff --git a/Source/DungeonGenerator/Private/DungeonGenerateBase.cpp b/Source/DungeonGenerator/Private/DungeonGenerateBase.cpp index e77a93f..a66af4c 100644 --- a/Source/DungeonGenerator/Private/DungeonGenerateBase.cpp +++ b/Source/DungeonGenerator/Private/DungeonGenerateBase.cpp @@ -73,6 +73,7 @@ ADungeonGenerateActorは配置可能(Placeable)、ADungeonGeneratedActorは配 namespace { + const FString ActorsFolderPath = TEXT("Actors"); const FString DoorsFolderPath = TEXT("Actors/Doors"); const FString TorchesFolderPath = TEXT("Actors/Torches"); const FString SensorsFolderPath = TEXT("Actors/Sensors"); @@ -422,11 +423,12 @@ bool ADungeonGenerateBase::BeginDungeonGeneration(const UDungeonGenerateParamete dungeon::CreateDebugDirectory(); #endif - DUNGEON_GENERATOR_LOG(TEXT("version '%s', license '%s', uuid '%s', commit '%s'"), + DUNGEON_GENERATOR_LOG(TEXT("version '%s', license '%s', uuid '%s', commit '%s', HasAuthority '%s'"), TEXT(DUNGENERATOR_PLUGIN_VERSION_NAME), TEXT(JENKINS_LICENSE), TEXT(JENKINS_UUID), - TEXT(JENKINS_GIT_COMMIT) + TEXT(JENKINS_GIT_COMMIT), + hasAuthority ? TEXT("Yes") : TEXT("No") ); // CRC32の値を初期化 @@ -528,7 +530,7 @@ bool ADungeonGenerateBase::BeginDungeonGeneration(const UDungeonGenerateParamete mAisleGridMap = NewObject(this); // 生成終了イベントの登録 - dungeon::Finalizer finalizer([this]() + dungeon::Finalizer finalizer([this, hasAuthority]()->void { #if defined(DEBUG_ENABLE_MEASURE_GENERATION_TIME) dungeon::Stopwatch stopwatch; @@ -540,6 +542,21 @@ bool ADungeonGenerateBase::BeginDungeonGeneration(const UDungeonGenerateParamete EndGeneration(random, mAisleGridMap); OnEndGeneration.Broadcast(random, mAisleGridMap); + mParameter->OnEndGeneration(random, mAisleGridMap, [this, hasAuthority](const FSoftObjectPath& spawnPath, const FTransform& transform) + { + if (hasAuthority) + { + const FSoftObjectPath path(spawnPath.ToString() + "_C"); + const TSoftClassPtr softClassPointer(path); + auto* actorClass = softClassPointer.LoadSynchronous(); + + FActorSpawnParameters actorSpawnParameters; + actorSpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButDontSpawnIfColliding; + SpawnActorImpl(actorClass, ActorsFolderPath, transform, actorSpawnParameters); + } + } + ); + #if defined(DEBUG_ENABLE_MEASURE_GENERATION_TIME) DUNGEON_GENERATOR_LOG(TEXT("On end generation event: %lf seconds"), stopwatch.Lap()); #endif @@ -1311,25 +1328,25 @@ void ADungeonGenerateBase::CreateImplement_PrepareSpawnRoomSensor(RoomAndRoomSen dungeon::Stopwatch stopwatch; #endif - // サーバーならRoomSensorActorを生成 - if (hasAuthority) - { - mGenerator->ForEach([this, &roomSensorCache](const std::shared_ptr& room) + mGenerator->ForEach([this, &roomSensorCache, hasAuthority](const std::shared_ptr& room) + { + auto* roomSensorClass = mParameter->GetRoomSensorClass(); + if (const auto* roomSensorDatabase = mParameter->GetRoomSensorDatabase()) + { + // TODO: ダンジョンの深さを0~255に正規化する関数を検討してください + auto depthFromStart = static_cast(room->GetDepthFromStart()); + depthFromStart /= static_cast(mGenerator->GetDeepestDepthFromStart()); + const auto depthRatioFromStart = static_cast(depthFromStart * 255.f); + + roomSensorClass = roomSensorDatabase->Select( + room->GetIdentifier(), + depthRatioFromStart, + GetSynchronizedRandom() + ); + } + // サーバーならRoomSensorActorを生成 + if (hasAuthority) { - auto* roomSensorClass = mParameter->GetRoomSensorClass(); - if (const auto* roomSensorDatabase = mParameter->GetRoomSensorDatabase()) - { - // TODO: ダンジョンの深さを0~255に正規化する関数を検討してください - auto depthFromStart = static_cast(room->GetDepthFromStart()); - depthFromStart /= static_cast(mGenerator->GetDeepestDepthFromStart()); - const auto depthRatioFromStart = static_cast(depthFromStart * 255.f); - - roomSensorClass = roomSensorDatabase->Select( - room->GetIdentifier(), - depthRatioFromStart, - GetSynchronizedRandom() - ); - } if (roomSensorClass) { auto* roomSensorActor = SpawnRoomSensorActorDeferred( @@ -1346,8 +1363,8 @@ void ADungeonGenerateBase::CreateImplement_PrepareSpawnRoomSensor(RoomAndRoomSen roomSensorCache[room.get()] = roomSensorActor; } } - ); - } + } + ); #if defined(DEBUG_ENABLE_MEASURE_GENERATION_TIME) DUNGEON_GENERATOR_LOG(TEXT("Prepare spawn DungeonRoomSensor actors: %lf seconds"), stopwatch.Lap()); @@ -1639,7 +1656,7 @@ AStaticMeshActor* ADungeonGenerateBase::SpawnStaticMeshActor(UStaticMesh* static if (auto* staticMeshComponent = GetValid(actor->GetStaticMeshComponent())) { - if (const UWorld* world = actor->GetWorld()) + if (const auto* world = actor->GetWorld()) { if (world->HasBegunPlay() == true) actor->SetMobility(EComponentMobility::Movable); diff --git a/Source/DungeonGenerator/Private/Helper/DungeonAisleGridMap.cpp b/Source/DungeonGenerator/Private/Helper/DungeonAisleGridMap.cpp index 4248a94..a18588b 100644 --- a/Source/DungeonGenerator/Private/Helper/DungeonAisleGridMap.cpp +++ b/Source/DungeonGenerator/Private/Helper/DungeonAisleGridMap.cpp @@ -34,14 +34,17 @@ void UDungeonAisleGridMap::Register(const int32 identifier, const EDungeonDirect } } -void UDungeonAisleGridMapBlueprintFunctionLibrary::ForEach(const UDungeonAisleGridMap* aisleGridArray, const FDungeonAisleGridMapLoopSignature& OnLoop) +void UDungeonAisleGridMap::ForEach(const FDungeonAisleGridMapLoopSignature& OnLoop) const { - if (aisleGridArray) + for (const auto& aisleGrid : mAisleGridMap) { - for (const auto& aisleGrid : aisleGridArray->mAisleGridMap) - { - if (OnLoop.ExecuteIfBound(aisleGrid.second) == false) - break; - } + if (OnLoop.ExecuteIfBound(aisleGrid.second) == false) + break; } } + +void UDungeonAisleGridMapBlueprintFunctionLibrary::ForEach(const UDungeonAisleGridMap* aisleGridArray, const FDungeonAisleGridMapLoopSignature& OnLoop) +{ + if (aisleGridArray) + aisleGridArray->ForEach(OnLoop); +} diff --git a/Source/DungeonGenerator/Private/Parameter/DungeonGenerateParameter.cpp b/Source/DungeonGenerator/Private/Parameter/DungeonGenerateParameter.cpp index e3b319b..006823b 100644 --- a/Source/DungeonGenerator/Private/Parameter/DungeonGenerateParameter.cpp +++ b/Source/DungeonGenerator/Private/Parameter/DungeonGenerateParameter.cpp @@ -10,6 +10,8 @@ All Rights Reserved. #include "Core/Debug/Debug.h" #include "Core/Math/Random.h" #include "Core/Voxelization/Grid.h" +#include "Helper/DungeonAisleGridMap.h" +#include "Helper/DungeonRandom.h" #include #include @@ -17,6 +19,7 @@ All Rights Reserved. #if WITH_EDITOR #include #endif +#include UDungeonGenerateParameter::UDungeonGenerateParameter(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) @@ -485,4 +488,41 @@ void UDungeonGenerateParameter::EachAisleCatwalkParts(const std::function& function) const { FDungeonMeshSet::EachParts(PillarParts, function); -} \ No newline at end of file +} + +void UDungeonGenerateParameter::OnEndGeneration(UDungeonRandom* synchronizedRandom, const UDungeonAisleGridMap* aisleGridMap, const std::function& spawnActor) const +{ + if (synchronizedRandom == nullptr) + return; + if (aisleGridMap == nullptr) + return; + if (SpawnActorInAisle.IsEmpty()) + return; + aisleGridMap->Each([this, synchronizedRandom, spawnActor](const TArray& aisleGridArray) + { + // スポーン先グリッドを抽選します + std::unordered_set gridIndexes; + const int32 totalGrids = aisleGridArray.Num(); + const int32 count = totalGrids / 3; + for (int32 i = 0; i < count; ++i) + { + gridIndexes.emplace(synchronizedRandom->GetIntegerFrom(totalGrids)); + } + + const int32 totalActors = SpawnActorInAisle.Num(); + for (const auto gridIndex : gridIndexes) + { + // スポーンする姿勢を求める + const auto& aisleGrid = aisleGridArray[gridIndex]; + const FTransform transform( + dungeon::detail::ToRotator(aisleGrid.Direction), + aisleGrid.Location + FVector(0, 0, VerticalGridSize / 2.f) + ); + + // アクターをスポーンします + const int32 actorType = synchronizedRandom->GetIntegerFrom(totalActors); + spawnActor(SpawnActorInAisle[actorType], transform); + } + } + ); +} diff --git a/Source/DungeonGenerator/Public/DungeonBlueprint.h b/Source/DungeonGenerator/Public/DungeonBlueprint.h index 9ec0667..1b25a78 100644 --- a/Source/DungeonGenerator/Public/DungeonBlueprint.h +++ b/Source/DungeonGenerator/Public/DungeonBlueprint.h @@ -15,7 +15,7 @@ class ADungeonRoomSensorBase; BluePrint function library ダンジョン生成ブループリント関数 */ -UCLASS() +UCLASS(ClassGroup = "DungeonGenerator") class UDungeonBlueprint : public UBlueprintFunctionLibrary { GENERATED_BODY() diff --git a/Source/DungeonGenerator/Public/DungeonGenerateBase.h b/Source/DungeonGenerator/Public/DungeonGenerateBase.h index 9c21d6b..a4ca3bf 100644 --- a/Source/DungeonGenerator/Public/DungeonGenerateBase.h +++ b/Source/DungeonGenerator/Public/DungeonGenerateBase.h @@ -159,10 +159,10 @@ class DUNGEONGENERATOR_API ADungeonGenerateBase : public AActor // アクターのスポーンと破棄 public: /** - アクターをスポーンします。 - DungeonGeneratorというタグを追加します。 - スポーンしたアクターはDestroySpawnedActorsで破棄されます。 - */ + * アクターをスポーンします。 + * DungeonGeneratorというタグを追加します。 + * スポーンしたアクターはDestroySpawnedActorsで破棄されます。 + */ static AActor* SpawnActorImpl(UWorld* world, UClass* actorClass, const FString& folderPath, const FTransform& transform, const FActorSpawnParameters& actorSpawnParameters); /** @@ -237,14 +237,24 @@ class DUNGEONGENERATOR_API ADungeonGenerateBase : public AActor /** * Event called at the end of the Create function + * synchronizedRandom is a random number that is synchronized between clients. It must always be called the same number of times on server and client. + * aisleGridMap is a container for the generated aisle grid + * * Create関数終了時に呼び出されるイベントです + * synchronizedRandomは、クライアント間で同期する乱数です。かならずサーバーとクライアントで同じ回数を呼び出す必要があります + * aisleGridMapは、生成された通路グリッドのコンテナ */ UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "DungeonGenerator") void EndGeneration(UDungeonRandom* synchronizedRandom, const UDungeonAisleGridMap* aisleGridMap); /** * Event called at the end of the Create function + * synchronizedRandom is a random number that is synchronized between clients. It must always be called the same number of times on server and client. + * aisleGridMap is a container for the generated aisle grid + * * Create関数終了時に呼び出されるイベントです + * synchronizedRandomは、クライアント間で同期する乱数です。かならずサーバーとクライアントで同じ回数を呼び出す必要があります + * aisleGridMapは、生成された通路グリッドのコンテナ */ UPROPERTY(BlueprintAssignable, Category = "DungeonGenerator|Event") FDungeonGenerateBaseOnEndGenerateSignature OnEndGeneration; diff --git a/Source/DungeonGenerator/Public/Helper/DungeonAisleGridMap.h b/Source/DungeonGenerator/Public/Helper/DungeonAisleGridMap.h index 9972370..a4e20d1 100644 --- a/Source/DungeonGenerator/Public/Helper/DungeonAisleGridMap.h +++ b/Source/DungeonGenerator/Public/Helper/DungeonAisleGridMap.h @@ -8,6 +8,7 @@ All Rights Reserved. #include "Helper/DungeonDirection.h" #include #include +#include #include #include "DungeonAisleGridMap.generated.h" @@ -41,13 +42,20 @@ DECLARE_DYNAMIC_DELEGATE_OneParam(FDungeonAisleGridMapLoopSignature, const TArra * Record aisle grid for each aisle * 通路毎に通路グリッドを記録します */ -UCLASS() +UCLASS(ClassGroup = "DungeonGenerator") class DUNGEONGENERATOR_API UDungeonAisleGridMap : public UObject { GENERATED_BODY() public: + /** + * コンストラクタ + */ explicit UDungeonAisleGridMap(const FObjectInitializer& initializer); + + /** + * デストラクタ + */ virtual ~UDungeonAisleGridMap() override = default; /** @@ -56,6 +64,23 @@ class DUNGEONGENERATOR_API UDungeonAisleGridMap : public UObject */ void Register(const int32 identifier, const EDungeonDirection direction, const FVector& location); + /** + * Update aisle grid + * 通路グリッドを更新します + */ + UFUNCTION(BlueprintCallable, Category = "DungeonGenerator") + void ForEach(const FDungeonAisleGridMapLoopSignature& OnLoop) const; + + /** + * Update aisle grid + * 通路グリッドを更新します + */ + void Each(const std::function& aisleGridArray)>& func) const + { + for (const auto& aisleGrid : mAisleGridMap) + func(aisleGrid.second); + } + private: std::unordered_map> mAisleGridMap; @@ -66,7 +91,7 @@ class DUNGEONGENERATOR_API UDungeonAisleGridMap : public UObject * Class for BluePrint function to manipulate UDungeonAisleGridMap * UDungeonAisleGridMapを操作するBluePrint関数のクラス */ -UCLASS() +UCLASS(ClassGroup = "DungeonGenerator") class UDungeonAisleGridMapBlueprintFunctionLibrary : public UBlueprintFunctionLibrary { GENERATED_BODY() diff --git a/Source/DungeonGenerator/Public/Helper/DungeonDirection.h b/Source/DungeonGenerator/Public/Helper/DungeonDirection.h index 0365759..f1f3d44 100644 --- a/Source/DungeonGenerator/Public/Helper/DungeonDirection.h +++ b/Source/DungeonGenerator/Public/Helper/DungeonDirection.h @@ -24,3 +24,19 @@ enum class EDungeonDirection : uint8 South, West, }; + +namespace dungeon +{ + namespace detail + { + inline double ToDegree(const EDungeonDirection dungeonDirection) noexcept + { + return static_cast(dungeonDirection) * 90; + } + + inline FRotator ToRotator(const EDungeonDirection dungeonDirection) + { + return FRotator(0, ToDegree(dungeonDirection), 0); + } + } +} diff --git a/Source/DungeonGenerator/Public/Helper/DungeonRandom.h b/Source/DungeonGenerator/Public/Helper/DungeonRandom.h index 9acac88..412b189 100644 --- a/Source/DungeonGenerator/Public/Helper/DungeonRandom.h +++ b/Source/DungeonGenerator/Public/Helper/DungeonRandom.h @@ -110,7 +110,7 @@ class DUNGEONGENERATOR_API CDungeonRandom * Random numbers for dungeon generation available from BluePrint * BluePrintから利用可能なダンジョン生成用乱数 */ -UCLASS() +UCLASS(ClassGroup = "DungeonGenerator") class DUNGEONGENERATOR_API UDungeonRandom : public UObject { GENERATED_BODY() diff --git a/Source/DungeonGenerator/Public/MainLevel/DungeonMainLevelScriptActor.h b/Source/DungeonGenerator/Public/MainLevel/DungeonMainLevelScriptActor.h index 0b027ce..d36d834 100644 --- a/Source/DungeonGenerator/Public/MainLevel/DungeonMainLevelScriptActor.h +++ b/Source/DungeonGenerator/Public/MainLevel/DungeonMainLevelScriptActor.h @@ -27,7 +27,7 @@ registered in the partition. ダンジョンを指定の範囲のパーティションで区切り、パーティションに登録されたコンポーネントの アクティブ性を制御します。 */ -UCLASS() +UCLASS(ClassGroup = "DungeonGenerator") class DUNGEONGENERATOR_API ADungeonMainLevelScriptActor : public ALevelScriptActor { GENERATED_BODY() diff --git a/Source/DungeonGenerator/Public/MainLevel/DungeonPartition.h b/Source/DungeonGenerator/Public/MainLevel/DungeonPartition.h index 3e3a3a3..1cff24c 100644 --- a/Source/DungeonGenerator/Public/MainLevel/DungeonPartition.h +++ b/Source/DungeonGenerator/Public/MainLevel/DungeonPartition.h @@ -23,7 +23,7 @@ If the partition is away from the player, deactivate it. プレイヤー周辺のパーティションならDungeonComponentActivatorComponentをアクティブ化します。 プレイヤーから離れているパーティションなら非アクティブ化します。 */ -UCLASS() +UCLASS(ClassGroup = "DungeonGenerator") class DUNGEONGENERATOR_API UDungeonPartition : public UObject { GENERATED_BODY() diff --git a/Source/DungeonGenerator/Public/Parameter/DungeonGenerateParameter.h b/Source/DungeonGenerator/Public/Parameter/DungeonGenerateParameter.h index a7a2965..6aa1765 100644 --- a/Source/DungeonGenerator/Public/Parameter/DungeonGenerateParameter.h +++ b/Source/DungeonGenerator/Public/Parameter/DungeonGenerateParameter.h @@ -14,12 +14,14 @@ All Rights Reserved. #include "DungeonGenerateParameter.generated.h" // forward declaration +class UDungeonAisleGridMap; +class UDungeonRandom; class UDungeonRoomSensorDatabase; /** -Frequency of generation -生成頻度 -*/ + * Frequency of generation + * 生成頻度 + */ UENUM() enum class EFrequencyOfGeneration : uint8 { @@ -32,52 +34,130 @@ enum class EFrequencyOfGeneration : uint8 }; /** -Dungeon generation parameter -ダンジョン生成パラメータ -*/ + * Dungeon generation parameter + * ダンジョン生成パラメータ + */ UCLASS(ClassGroup = "DungeonGenerator") class DUNGEONGENERATOR_API UDungeonGenerateParameter : public UObject { GENERATED_BODY() public: + /** + * コンストラクタ + */ explicit UDungeonGenerateParameter(const FObjectInitializer& ObjectInitializer); + + /** + * デストラクタ + */ virtual ~UDungeonGenerateParameter() override = default; + /** + * ダンジョン生成に使用する乱数の種を取得します + */ int32 GetRandomSeed() const; + + /** + * ダンジョン生成に使用した乱数の種を取得します + */ int32 GetGeneratedRandomSeed() const; + /** + * 生成する部屋の候補数を取得します + */ int32 GetNumberOfCandidateRooms() const; + /** + * 部屋の幅を取得します + */ const FInt32Interval& GetRoomWidth() const noexcept; + + /** + * 部屋の奥行を取得します + */ const FInt32Interval& GetRoomDepth() const noexcept; + + /** + * 部屋の高さを取得します + */ const FInt32Interval& GetRoomHeight() const noexcept; + /** + * 部屋と部屋の水平方向の間隔(余白)を取得します + */ int32 GetHorizontalRoomMargin() const noexcept; + + /** + * 部屋と部屋の垂直方向の間隔(余白)を取得します + */ int32 GetVerticalRoomMargin() const noexcept; + /** + * グリッドのサイズを取得します + */ FDungeonGridSize GetGridSize() const; + /** + * 部屋と部屋を結合するか取得します + */ bool IsMergeRooms() const noexcept; + + /** + * ゲーム開始時にPlayerStartアクターを移動するか?取得します + */ bool IsMovePlayerStartToStartingPoint() const noexcept; - + + /** + * ミッショングラフを有効にするか取得します + */ bool IsUseMissionGraph() const noexcept; + + /** + * 通路の複雑度を取得します + */ uint8 GetAisleComplexity() const noexcept; + + /** + * 通路の複雑度が有効か?取得します + */ bool IsAisleComplexity() const noexcept; + /** + * 燭台アクターの生成頻度を取得します + */ EFrequencyOfGeneration GetFrequencyOfTorchlightGeneration() const noexcept; + /** + * DungeonRoomSensorのクラスを取得します + */ UClass* GetRoomSensorClass() const; + + /** + * DungeonRoomSensorのデータベースを取得します + */ UDungeonRoomSensorDatabase* GetRoomSensorDatabase() const; - // Converts from a grid coordinate system to a world coordinate system + /** + * Converts from a grid coordinate system to a world coordinate system + * + * グリッド座標系からワールド座標系への変換 + */ FVector ToWorld(const FIntVector& location) const; - - // Converts from a grid coordinate system to a world coordinate system + + /** + * Converts from a grid coordinate system to a world coordinate system + * + * グリッド座標系からワールド座標系への変換 + */ FVector ToWorld(const uint32_t x, const uint32_t y, const uint32_t z) const; - // Converts from a grid coordinate system to a world coordinate system + /** + * Converts from a grid coordinate system to a world coordinate system + * + * グリッド座標系からワールド座標系への変換 + */ FIntVector ToGrid(const FVector& location) const; /** @@ -94,19 +174,26 @@ class DUNGEONGENERATOR_API UDungeonGenerateParameter : public UObject UFUNCTION(BlueprintCallable, Category = "DungeonGenerator") void SetRandomParameter() noexcept; -public: #if WITH_EDITOR /** - Output parameters in JSON format - パラメータをJSON形式で出力します - */ + * Output parameters in JSON format + * + * パラメータをJSON形式で出力します + */ UFUNCTION(Category = "DungeonGenerator", meta = (CallInEditor = "true")) void Dump() const; #endif private: + /** + * ダンジョン生成に使用する乱数の種を設定します + */ void SetRandomSeed(const int32 generateRandomSeed); + + /** + * ダンジョン生成に使用した乱数の種を設定します + */ void SetGeneratedRandomSeed(const int32 generatedRandomSeed); #if WITH_EDITOR @@ -116,8 +203,6 @@ class DUNGEONGENERATOR_API UDungeonGenerateParameter : public UObject static const FDungeonMeshSet* SelectParts(const UDungeonMeshSetDatabase* dungeonMeshSetDatabase, const dungeon::Grid& grid, const std::shared_ptr& random); - const FDungeonMeshParts* SelectSlopeParts(const size_t gridIndex, const dungeon::Grid& grid, const std::shared_ptr& random) const; - const UDungeonMeshSetDatabase* GetDungeonRoomMeshPartsDatabase() const noexcept; const UDungeonMeshSetDatabase* GetDungeonAisleMeshPartsDatabase() const noexcept; static const FDungeonMeshPartsWithDirection* SelectFloorParts(const UDungeonMeshSetDatabase* dungeonMeshSetDatabase, const size_t gridIndex, const dungeon::Grid& grid, const std::shared_ptr& random); @@ -136,7 +221,7 @@ class DUNGEONGENERATOR_API UDungeonGenerateParameter : public UObject void EachRoofParts(const std::function& function) const; void EachSlopeParts(const std::function& function) const; void EachCatwalkParts(const std::function& function) const; -void EachPillarParts(const std::function& function) const; + void EachPillarParts(const std::function& function) const; void EachRoomFloorParts(const std::function& function) const; void EachRoomWallParts(const std::function& function) const; @@ -152,7 +237,15 @@ void EachPillarParts(const std::function& functi int32 GetGeneratedDungeonCRC32() const noexcept; void SetGeneratedDungeonCRC32(const int32 generatedDungeonCRC32) noexcept; - + + /** + * ダンジョン生成終了時に通知されるイベント + * @param synchronizedRandom クライアント・サーバー間で同期される乱数 + * @param aisleGridMap 通路のグリッドを記録したコンテナ + * @param spawnActor アクターをスポーンする関数 + */ + void OnEndGeneration(UDungeonRandom* synchronizedRandom, const UDungeonAisleGridMap* aisleGridMap, const std::function& spawnActor) const; + public: // overrides virtual void GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const override; @@ -160,134 +253,134 @@ void EachPillarParts(const std::function& functi protected: /** - Seed of random number (if 0, auto-generated) - - 乱数のシード(0なら自動生成) - */ + * Seed of random number (if 0, auto-generated) + * + * 乱数のシード(0なら自動生成) + */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "DungeonGenerator", meta = (ClampMin = "0")) int32 RandomSeed = 0; /** - Seed of random numbers used for the last generation - - 最後の生成に使用された乱数のシード - */ + * Seed of random numbers used for the last generation + * + * 最後の生成に使用された乱数のシード + */ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Replicated, Transient, Category = "DungeonGenerator") int32 GeneratedRandomSeed = 0; /** - CRC32 of the last dungeon generated - - 最後に生成されたダンジョンのCRC32 - */ + * CRC32 of the last dungeon generated + * + * 最後に生成されたダンジョンのCRC32 + */ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Replicated, Transient, Category = "DungeonGenerator") int32 GeneratedDungeonCRC32 = 0; /** - Room Width - - 部屋の幅 - */ + * Room Width + * + * 部屋の幅 + */ UPROPERTY(EditAnywhere, Category = "DungeonGenerator", meta = (UIMin = 1, ClampMin = 1)) FInt32Interval RoomWidth = { 3, 8 }; /** - Room depth - - 部屋の奥行き - */ + * Room depth + * + * 部屋の奥行き + */ UPROPERTY(EditAnywhere, Category = "DungeonGenerator", meta = (UIMin = 1, ClampMin = 1)) FInt32Interval RoomDepth = { 3, 8 }; /** - Room height - - 部屋の高さ - */ + * Room height + * + * 部屋の高さ + */ UPROPERTY(EditAnywhere, Category = "DungeonGenerator", meta = (UIMin = 1, ClampMin = 1)) FInt32Interval RoomHeight = { 2, 4 }; /** - Horizontal room-to-room margins - MergeRooms must be unchecked to enable Room Horizontal Margin - - 水平方向の部屋と部屋の空白 - Room Horizontal Marginを有効にするにはMergeRoomsのチェックを外す必要があります - */ + * Horizontal room-to-room margins + * MergeRooms must be unchecked to enable Room Horizontal Margin + * + * 水平方向の部屋と部屋の空白 + * Room Horizontal Marginを有効にするにはMergeRoomsのチェックを外す必要があります + */ UPROPERTY(EditAnywhere, Category = "DungeonGenerator", BlueprintReadWrite, meta = (ClampMin = "1", EditCondition = "!MergeRooms"), DisplayName = "Horizontal Room Margin") uint8 RoomMargin = 2; /** - Vertical room-to-room margins - MergeRooms must be unchecked to enable Room Vertical Margin - - 垂直方向の部屋と部屋の空白 - Room Vertical Marginを有効にするにはMergeRoomsのチェックを外す必要があります - */ + * Vertical room-to-room margins + * MergeRooms must be unchecked to enable Room Vertical Margin + * + * 垂直方向の部屋と部屋の空白 + * Room Vertical Marginを有効にするにはMergeRoomsのチェックを外す必要があります + */ UPROPERTY(EditAnywhere, Category = "DungeonGenerator", BlueprintReadWrite, meta = (ClampMin = "0", EditCondition = "!MergeRooms && !Flat "), DisplayName = "Vertical Room Margin") uint8 VerticalRoomMargin = 0; /** - Candidate number of rooms to be generated - This is the initial number of rooms to be generated, not the final number of rooms to be generated. - - 生成される部屋数の候補 - これは最終的な部屋の数ではなく最初に生成される部屋の数です。 - */ + * Candidate number of rooms to be generated + * This is the initial number of rooms to be generated, not the final number of rooms to be generated. + * + * 生成される部屋数の候補 + * これは最終的な部屋の数ではなく最初に生成される部屋の数です + */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "DungeonGenerator", meta = (ClampMin = "3", ClampMax = "100")) uint8 NumberOfCandidateRooms = 10; /** - Horizontal room-to-room coupling - - 有効にすると部屋と部屋を結合します - */ + * Horizontal room-to-room coupling + * + * 有効にすると部屋と部屋を結合します + */ UPROPERTY(EditAnywhere, Category = "DungeonGenerator", BlueprintReadWrite) bool MergeRooms = false; /** - Candidate Number of Generated Hierarchies This is used as a reference number of hierarchies for generation, - not as the final number of hierarchies. - - 生成される階層数の候補 - これは最終的な階層の数ではなく生成時の参考階層数として利用されます。 - */ + * Candidate Number of Generated Hierarchies This is used as a reference number of hierarchies for generation, + * not as the final number of hierarchies. + * + * 生成される階層数の候補 + * これは最終的な階層の数ではなく生成時の参考階層数として利用されます。 + */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "DungeonGenerator", meta = (ClampMin = "0", ClampMax = "5", EditCondition = "!Flat")) uint8 NumberOfCandidateFloors = 3; /** - Generates a flat dungeon - - 平面的なダンジョンを生成します - */ + * Generates a flat dungeon + * + * 平面的なダンジョンを生成します + */ UPROPERTY(EditAnywhere, Category = "DungeonGenerator", BlueprintReadWrite, meta = (EditCondition = "!MergeRooms")) bool Flat = false; /** - PlayerStart is automatically moved to the start room at the start - - 開始時にPlayerStartを自動的にスタート部屋に移動します - */ + * PlayerStart is automatically moved to the start room at the start + * + * 開始時にPlayerStartを自動的にスタート部屋に移動します + */ UPROPERTY(EditAnywhere, Category = "DungeonGenerator", BlueprintReadWrite) bool MovePlayerStartToStartingPoint = true; /** - Enable MissionGraph to generate missions with keys. - MergeRooms must be unchecked and AisleComplexity must be 0 for UseMissionGraph to be enabled. - - MissionGraphを有効にして、鍵を使ったミッション情報を生成します - UseMissionGraphを有効にするには、MergeRoomsのチェックを外しAisleComplexityを0にする必要があります - */ + * Enable MissionGraph to generate missions with keys. + * MergeRooms must be unchecked and AisleComplexity must be 0 for UseMissionGraph to be enabled. + * + * MissionGraphを有効にして、鍵を使ったミッション情報を生成します + * UseMissionGraphを有効にするには、MergeRoomsのチェックを外しAisleComplexityを0にする必要があります + */ UPROPERTY(EditAnywhere, Category = "DungeonGenerator", BlueprintReadWrite, meta = (EditCondition = "!MergeRooms")) bool UseMissionGraph = false; /** - Aisle complexity (0 being the minimum aisle) - MergeRooms and UseMissionGraph must be unchecked to enable AisleComplexity - - 通路の複雑さ(0が最低限の通路) - AisleComplexityを有効にするには、MergeRoomsとUseMissionGraphのチェックを外す必要があります - */ + * Aisle complexity (0 being the minimum aisle) + * MergeRooms and UseMissionGraph must be unchecked to enable AisleComplexity + * + * 通路の複雑さ(0が最低限の通路) + * AisleComplexityを有効にするには、MergeRoomsとUseMissionGraphのチェックを外す必要があります + */ UPROPERTY(EditAnywhere, Category = "DungeonGenerator", BlueprintReadOnly, meta = (ClampMin = "0", ClampMax = "10", EditCondition = "!MergeRooms && !UseMissionGraph")) uint8 AisleComplexity = 5; @@ -312,90 +405,90 @@ void EachPillarParts(const std::function& functi bool GenerateStructuralColumn = false; /** - Horizontal voxel size - - 水平方向のボクセルサイズ - */ + * Horizontal voxel size + * + * 水平方向のボクセルサイズ + */ UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "DungeonGenerator|GridSize", meta = (ClampMin = 1), DisplayName = "Horizontal Size") float GridSize = 400.f; /** - Vertical voxel size - - 垂直方向のボクセルサイズ - */ + * Vertical voxel size + * + * 垂直方向のボクセルサイズ + */ UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "DungeonGenerator|GridSize", meta = (ClampMin = 1), DisplayName = "Vertical Size") float VerticalGridSize = 400.f; /** - Room mesh parts database - - 部屋のメッシュパーツデータベース - */ + * Room mesh parts database + * + * 部屋のメッシュパーツデータベース + */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "DungeonGenerator|Parts") TObjectPtr DungeonRoomMeshPartsDatabase; /** - Aisle mesh parts database - - 通路のメッシュパーツデータベース - */ + * Aisle mesh parts database + * + * 通路のメッシュパーツデータベース + */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "DungeonGenerator|Parts") TObjectPtr DungeonAisleMeshPartsDatabase; /** - How to generate parts of pillar - - 柱のパーツを生成する方法 - */ + * How to generate parts of pillar + * + * 柱のパーツを生成する方法 + */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "DungeonGenerator|Parts|Pillar") EDungeonPartsSelectionMethod PillarPartsSelectionMethod = EDungeonPartsSelectionMethod::Random; /** - Pillar Parts - - 柱のメッシュパーツデータベース - */ + * Pillar Parts + * + * 柱のメッシュパーツデータベース + */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "DungeonGenerator|Parts|Pillar") TArray PillarParts; /** - How to generate parts for torch - - 燭台のパーツを生成する方法 - */ + * How to generate parts for torch + * + * 燭台のパーツを生成する方法 + */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "DungeonGenerator|Parts|Torch") EDungeonPartsSelectionMethod TorchPartsSelectionMethod = EDungeonPartsSelectionMethod::Random; /** - Frequency of torchlight generation - - 燭台の生成頻度 - */ + * Frequency of torchlight generation + * + * 燭台の生成頻度 + */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "DungeonGenerator|Parts|Torch") EFrequencyOfGeneration FrequencyOfTorchlightGeneration = EFrequencyOfGeneration::Rarely; /** - Torch (pillar lighting) parts - - 燭台のメッシュパーツデータベース - */ + * Torch (pillar lighting) parts + * + * 燭台のメッシュパーツデータベース + */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "DungeonGenerator|Parts|Torch") TArray TorchParts; /** - How to generate door parts - - ドアのパーツを生成する方法 - */ + * How to generate door parts + * + * ドアのパーツを生成する方法 + */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "DungeonGenerator|Parts|Door") EDungeonPartsSelectionMethod DoorPartsSelectionMethod = EDungeonPartsSelectionMethod::Random; /** - Door Parts - - ドアのメッシュパーツデータベース - */ + * Door Parts + * + * ドアのメッシュパーツデータベース + */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "DungeonGenerator|Parts|Door") TArray DoorParts; @@ -422,6 +515,14 @@ void EachPillarParts(const std::function& functi UPROPERTY(EditAnywhere, Category = "DungeonGenerator|RoomSensor", BlueprintReadWrite) TObjectPtr DungeonRoomSensorDatabase; + /** + * Actor spawning in an aisle + * + * 通路にスポーンするアクター + */ + UPROPERTY(EditAnywhere, Category = "DungeonGenerator|RoomSensor", meta = (AllowedClasses = "Blueprint")) + TArray SpawnActorInAisle; + /** * PluginVersion * diff --git a/Source/DungeonGeneratorEditor/Public/Parameter/DungeonGenerateParameterFactory.h b/Source/DungeonGeneratorEditor/Public/Parameter/DungeonGenerateParameterFactory.h index 4b0a9c3..4c7691d 100644 --- a/Source/DungeonGeneratorEditor/Public/Parameter/DungeonGenerateParameterFactory.h +++ b/Source/DungeonGeneratorEditor/Public/Parameter/DungeonGenerateParameterFactory.h @@ -9,7 +9,7 @@ All Rights Reserved. #include #include "DungeonGenerateParameterFactory.generated.h" -UCLASS() +UCLASS(ClassGroup = "DungeonGenerator") class DUNGEONGENERATOREDITOR_API UDungeonGenerateParameterFactory : public UFactory { GENERATED_BODY() diff --git a/Source/DungeonGeneratorEditor/Public/Parameter/DungeonMeshSetDatabaseFactory.h b/Source/DungeonGeneratorEditor/Public/Parameter/DungeonMeshSetDatabaseFactory.h index a5b83fd..e2600fc 100644 --- a/Source/DungeonGeneratorEditor/Public/Parameter/DungeonMeshSetDatabaseFactory.h +++ b/Source/DungeonGeneratorEditor/Public/Parameter/DungeonMeshSetDatabaseFactory.h @@ -12,7 +12,7 @@ All Rights Reserved. /* UDungeonMeshSetDatabaseを生成するファクトリークラス */ -UCLASS() +UCLASS(ClassGroup = "DungeonGenerator") class DUNGEONGENERATOREDITOR_API UDungeonMeshSetDatabaseFactory : public UFactory { GENERATED_BODY() diff --git a/Source/DungeonGeneratorEditor/Public/SubActor/DungeonRoomSensorDatabaseFactory.h b/Source/DungeonGeneratorEditor/Public/SubActor/DungeonRoomSensorDatabaseFactory.h index a13d873..90b626b 100644 --- a/Source/DungeonGeneratorEditor/Public/SubActor/DungeonRoomSensorDatabaseFactory.h +++ b/Source/DungeonGeneratorEditor/Public/SubActor/DungeonRoomSensorDatabaseFactory.h @@ -9,7 +9,7 @@ All Rights Reserved. #include #include "DungeonRoomSensorDatabaseFactory.generated.h" -UCLASS() +UCLASS(ClassGroup = "DungeonGenerator") class DUNGEONGENERATOREDITOR_API UDungeonRoomSensorDatabaseFactory : public UFactory { GENERATED_BODY() From ecbaa637f1fde91a98f751773286823581941fd9 Mon Sep 17 00:00:00 2001 From: Shun Moriya <23472415+shun126@users.noreply.github.com> Date: Sat, 27 Sep 2025 20:32:31 +0900 Subject: [PATCH 3/4] Added actor spawn to passageway in DungeonRoomSensor --- CHANGELOG.md | 2 + DungeonGenerator.uplugin | 4 +- .../Parameter/DungeonGenerateParameter.cpp | 38 ++---------------- .../SubActor/DungeonRoomSensorDatabase.cpp | 40 +++++++++++++++++++ .../Parameter/DungeonGenerateParameter.h | 8 ---- .../SubActor/DungeonRoomSensorDatabase.h | 27 +++++++++++-- 6 files changed, 71 insertions(+), 48 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 72fe67f..dcb5e6c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,11 @@ ## 20251004-1.7.8 (61) ### Changes +* Added the ability to assist actors spawning into the aisle grid * Changed DungeonRoomSensor to not spawn on the client side * Fixed several bugs ### 変更点 +* 通路グリッドへのアクターをスポーンを補助する機能を追加 * DungeonRoomSensorをクライアント側でスポーンしないように変更 * いくつかの不具合を修正 diff --git a/DungeonGenerator.uplugin b/DungeonGenerator.uplugin index b42f9d9..54d9275 100644 --- a/DungeonGenerator.uplugin +++ b/DungeonGenerator.uplugin @@ -6,10 +6,10 @@ "Description": "Procedural 3d dungeon generator plugin. Easy generation of levels, mini-maps and missions.", "Category": "Procedural Systems", "CreatedBy": "Narcis Software", - "CreatedByURL": "https://github.com/shun126/UE5-DungeonGeneratorDemo", + "CreatedByURL": "https://github.com/shun126/DungeonGenerator", "DocsURL": "https://github.com/shun126/UE5-DungeonGeneratorDemo/wiki", "MarketplaceURL": "com.epicgames.launcher://ue/marketplace/content/36a8b87d859f44439cfe1515975d7197", - "SupportURL": "https://github.com/shun126/UE5-DungeonGeneratorDemo/issues", + "SupportURL": "https://github.com/shun126/DungeonGenerator/discussions", "CanContainContent": true, "IsBetaVersion": true, "IsExperimentalVersion": false, diff --git a/Source/DungeonGenerator/Private/Parameter/DungeonGenerateParameter.cpp b/Source/DungeonGenerator/Private/Parameter/DungeonGenerateParameter.cpp index 006823b..1665adb 100644 --- a/Source/DungeonGenerator/Private/Parameter/DungeonGenerateParameter.cpp +++ b/Source/DungeonGenerator/Private/Parameter/DungeonGenerateParameter.cpp @@ -10,8 +10,7 @@ All Rights Reserved. #include "Core/Debug/Debug.h" #include "Core/Math/Random.h" #include "Core/Voxelization/Grid.h" -#include "Helper/DungeonAisleGridMap.h" -#include "Helper/DungeonRandom.h" +#include "SubActor/DungeonRoomSensorDatabase.h" #include #include @@ -492,37 +491,6 @@ void UDungeonGenerateParameter::EachPillarParts(const std::function& spawnActor) const { - if (synchronizedRandom == nullptr) - return; - if (aisleGridMap == nullptr) - return; - if (SpawnActorInAisle.IsEmpty()) - return; - aisleGridMap->Each([this, synchronizedRandom, spawnActor](const TArray& aisleGridArray) - { - // スポーン先グリッドを抽選します - std::unordered_set gridIndexes; - const int32 totalGrids = aisleGridArray.Num(); - const int32 count = totalGrids / 3; - for (int32 i = 0; i < count; ++i) - { - gridIndexes.emplace(synchronizedRandom->GetIntegerFrom(totalGrids)); - } - - const int32 totalActors = SpawnActorInAisle.Num(); - for (const auto gridIndex : gridIndexes) - { - // スポーンする姿勢を求める - const auto& aisleGrid = aisleGridArray[gridIndex]; - const FTransform transform( - dungeon::detail::ToRotator(aisleGrid.Direction), - aisleGrid.Location + FVector(0, 0, VerticalGridSize / 2.f) - ); - - // アクターをスポーンします - const int32 actorType = synchronizedRandom->GetIntegerFrom(totalActors); - spawnActor(SpawnActorInAisle[actorType], transform); - } - } - ); + if (DungeonRoomSensorDatabase) + DungeonRoomSensorDatabase->OnEndGeneration(synchronizedRandom, aisleGridMap, VerticalGridSize, spawnActor); } diff --git a/Source/DungeonGenerator/Private/SubActor/DungeonRoomSensorDatabase.cpp b/Source/DungeonGenerator/Private/SubActor/DungeonRoomSensorDatabase.cpp index f792b62..cc5bce5 100644 --- a/Source/DungeonGenerator/Private/SubActor/DungeonRoomSensorDatabase.cpp +++ b/Source/DungeonGenerator/Private/SubActor/DungeonRoomSensorDatabase.cpp @@ -7,8 +7,11 @@ All Rights Reserved. #include "SubActor/DungeonRoomSensorDatabase.h" #include "Core/Math/Random.h" #include "Core/Debug/Debug.h" +#include "Helper/DungeonAisleGridMap.h" +#include "Helper/DungeonRandom.h" #include "Parameter/DungeonMeshSetDatabase.h" #include +#include UDungeonRoomSensorDatabase::UDungeonRoomSensorDatabase(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) @@ -51,3 +54,40 @@ UClass* UDungeonRoomSensorDatabase::Select(const uint16_t identifier, const uint return nullptr; } } + +void UDungeonRoomSensorDatabase::OnEndGeneration(UDungeonRandom* synchronizedRandom, const UDungeonAisleGridMap* aisleGridMap, const float verticalGridSize, const std::function& spawnActor) const +{ + if (synchronizedRandom == nullptr) + return; + if (aisleGridMap == nullptr) + return; + if (SpawnActorInAisle.IsEmpty()) + return; + aisleGridMap->Each([this, synchronizedRandom, verticalGridSize, spawnActor](const TArray& aisleGridArray) + { + // スポーン先グリッドを抽選します + std::unordered_set gridIndexes; + const int32 totalGrids = aisleGridArray.Num(); + const int32 count = totalGrids / 3; + for (int32 i = 0; i < count; ++i) + { + gridIndexes.emplace(synchronizedRandom->GetIntegerFrom(totalGrids)); + } + + const int32 totalActors = SpawnActorInAisle.Num(); + for (const auto gridIndex : gridIndexes) + { + // スポーンする姿勢を求める + const auto& aisleGrid = aisleGridArray[gridIndex]; + const FTransform transform( + dungeon::detail::ToRotator(aisleGrid.Direction), + aisleGrid.Location + FVector(0, 0, verticalGridSize / 2.f) + ); + + // アクターをスポーンします + const int32 actorType = synchronizedRandom->GetIntegerFrom(totalActors); + spawnActor(SpawnActorInAisle[actorType], transform); + } + } + ); +} diff --git a/Source/DungeonGenerator/Public/Parameter/DungeonGenerateParameter.h b/Source/DungeonGenerator/Public/Parameter/DungeonGenerateParameter.h index 6aa1765..2d2f757 100644 --- a/Source/DungeonGenerator/Public/Parameter/DungeonGenerateParameter.h +++ b/Source/DungeonGenerator/Public/Parameter/DungeonGenerateParameter.h @@ -515,14 +515,6 @@ class DUNGEONGENERATOR_API UDungeonGenerateParameter : public UObject UPROPERTY(EditAnywhere, Category = "DungeonGenerator|RoomSensor", BlueprintReadWrite) TObjectPtr DungeonRoomSensorDatabase; - /** - * Actor spawning in an aisle - * - * 通路にスポーンするアクター - */ - UPROPERTY(EditAnywhere, Category = "DungeonGenerator|RoomSensor", meta = (AllowedClasses = "Blueprint")) - TArray SpawnActorInAisle; - /** * PluginVersion * diff --git a/Source/DungeonGenerator/Public/SubActor/DungeonRoomSensorDatabase.h b/Source/DungeonGenerator/Public/SubActor/DungeonRoomSensorDatabase.h index f33e07a..3554030 100644 --- a/Source/DungeonGenerator/Public/SubActor/DungeonRoomSensorDatabase.h +++ b/Source/DungeonGenerator/Public/SubActor/DungeonRoomSensorDatabase.h @@ -6,9 +6,13 @@ All Rights Reserved. #pragma once #include "Parameter/DungeonMeshSetSelectionMethod.h" +#include #include #include "DungeonRoomSensorDatabase.generated.h" +class UDungeonAisleGridMap; +class UDungeonRandom; + namespace dungeon { class Random; @@ -50,19 +54,36 @@ class DUNGEONGENERATOR_API UDungeonRoomSensorDatabase : public UObject */ UClass* Select(const uint16_t identifier, const uint8_t depthRatioFromStart, const std::shared_ptr& random) const; + /** + * ダンジョン生成終了時に通知されるイベント + * @param synchronizedRandom クライアント・サーバー間で同期される乱数 + * @param aisleGridMap 通路のグリッドを記録したコンテナ + * @param verticalGridSize グリッドの垂直方向の大きさ + * @param spawnActor アクターをスポーンする関数 + */ + void OnEndGeneration(UDungeonRandom* synchronizedRandom, const UDungeonAisleGridMap* aisleGridMap, const float verticalGridSize, const std::function& spawnActor) const; + protected: /** * Room Sensor Generation Rules * ルームセンサーの生成ルール */ - UPROPERTY(EditAnywhere, Category = "DungeonGenerator") - EDungeonMeshSetSelectionMethod SelectionMethod = EDungeonMeshSetSelectionMethod::Identifier; + UPROPERTY(EditAnywhere, Category = "DungeonGenerator|RoomSensor") + EDungeonMeshSetSelectionMethod SelectionMethod = EDungeonMeshSetSelectionMethod::DepthFromStart; /** * Register the RoomSensor to be placed. * * 配置するRoomSensorを登録して下さい。 */ - UPROPERTY(EditAnywhere, Category = "DungeonGenerator", meta = (AllowedClasses = "DungeonRoomSensorBase")) + UPROPERTY(EditAnywhere, Category = "DungeonGenerator|RoomSensor", meta = (AllowedClasses = "DungeonRoomSensorBase")) TArray> DungeonRoomSensorClass; + + /** + * Actor spawning in an aisle + * + * 通路にスポーンするアクター + */ + UPROPERTY(EditAnywhere, Category = "DungeonGenerator|Aisle", meta = (AllowedClasses = "Blueprint")) + TArray SpawnActorInAisle; }; From f81985627c7503d5107bf3191539e939cd786d9b Mon Sep 17 00:00:00 2001 From: Shun Moriya <23472415+shun126@users.noreply.github.com> Date: Wed, 1 Oct 2025 03:05:47 +0900 Subject: [PATCH 4/4] Multiplayer support for shutters --- Content/Actors/BP_SampleDungeonDoor.uasset | Bin 87287 -> 129002 bytes .../Actors/BP_SampleDungeonRoomSensor.uasset | Bin 77252 -> 16189 bytes Content/Maps/Demonstration.umap | Bin 53010 -> 52184 bytes Content/Parameters/DGP_Sample.uasset | Bin 5167 -> 5142 bytes Content/Parameters/DRSD_Sample.uasset | Bin 0 -> 1937 bytes 5 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 Content/Parameters/DRSD_Sample.uasset diff --git a/Content/Actors/BP_SampleDungeonDoor.uasset b/Content/Actors/BP_SampleDungeonDoor.uasset index 1e8bc0dfdbd293af45f25082f5a380049e59fbaa..7ed36c525411f9098ef818bde2b585336769662d 100644 GIT binary patch literal 129002 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 XXXa^dU8QU_al diff --git a/Content/Actors/BP_SampleDungeonRoomSensor.uasset b/Content/Actors/BP_SampleDungeonRoomSensor.uasset index 96db68722652415872d7f5936d140175f6b855a8..b60b2acd2f9dbf8ceab30571a649aa316010fed3 100644 GIT binary patch delta 5329 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 diff --git a/Content/Maps/Demonstration.umap b/Content/Maps/Demonstration.umap index 59bc59d99d722db451dceb70d6600d0a6c6dac46..0c7d71fa95e8ec4144e3e436ffae1dc70977f57c 100644 GIT binary patch delta 11228 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 a$p%7uHirsIGco?2TqtbG_;d1V;T8Zvy@P@P delta 467 zcmbQHv0h_>0b|TWLwhD>&dIxl)omDnfSHqlfeA=o=4N0Jg7PQxfMggLwgYJpJ`Ti6 z^8J_cZ}5Ar?c`c1;Q9OO#H%@qzk%Yvg&}HTOeA^Q-AUyP6bB0$&WcNGwMvX=Te`1kL!rt7obWfs4j6R4WfPn#gVuS zmQW5b$Qa_-Aeh NVOhq1lP3wc007Fgo09+l diff --git a/Content/Parameters/DRSD_Sample.uasset b/Content/Parameters/DRSD_Sample.uasset new file mode 100644 index 0000000000000000000000000000000000000000..c9cb95562c1bff8b4c79c6f81981a9565d09c2e3 GIT binary patch literal 1937 zcmb7FX=oEs5T0tQwXIjQTBZIFp_aOv5hbAj$GdI)gRgzPL#0n$XN7Ccb&F7UWCDO4r6Z6Mqg)bKa*@kS zm1IXNlUahRTvi-`wosrW#1hFkM=HQ<9NRG>1uZTFn2*vK@VOd%jqXOT(;xISxSN~n zJwC5j5d48=x4%I^3P2^2aZ^xM1b{Er*7tEvfu5jzf#V|%TTj2OBLsCiae2qK=s1U zQ_xM2WtMK0r6iZtG_>@;jLkxAexEzxr8nuAMxZuHN`$zmNU}f96a}t-8mPd8!5T^A zFf{)5 zRWqhLWsP)DG7o3NZx>;lPd0eVT(Rrz|gX!l@sP=mf&0TjN4BpYbl$#pKJIW9e&6Z`<7FI>n>{NuAVYnS^H?o1*dB+>GZxE z_6{(Wg|T>H==j?elaR5RtBjN|xbO0@VpJI45tNnP<EZz=Qyf0P?wmX(j(BJ z2|uu^$)A9YnFVc?FkKh$9eI>x!k>8GkT*l8<>i$dHWJiHgnaR=JaaF9<4xAXjfnRX z_hYCvL3KGz*89VO_Np+UeD!TmYc*H&oF02zWBt? zr_Va!ggAdLqujz9#Oq=Y)h2?xbL|bNGg~6JXX?hTRtiT^SKu%YYW#b$Nu=T>(1oSJ zJfUfzHNmS3pz_y129sne&62QW*kD_PNg|bXPHPHkB;wzGVFUPcJ@MuIzPhEi9??gx Uq$n2beC}CSc=v|gY3PXm8}a>>IRF3v literal 0 HcmV?d00001