Skip to content

Commit

Permalink
NotEnoughDoors diagnostic check
Browse files Browse the repository at this point in the history
  • Loading branch information
OndrejNepozitek committed Dec 15, 2023
1 parent 6013c60 commit 1755e55
Show file tree
Hide file tree
Showing 7 changed files with 341 additions and 0 deletions.
101 changes: 101 additions & 0 deletions Runtime/Grid2D/Common/Diagnostics/Checks/NotEnoughDoors.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Edgar.GraphBasedGenerator.Grid2D;
using UnityEngine;

namespace Edgar.Unity.Diagnostics
{
public class NotEnoughDoors
{
public Result Run(LevelDescriptionBase levelDescription)
{
var roomTemplates = new List<RoomTemplateGrid2D>();
var levelDescriptionGrid2D = levelDescription.GetLevelDescription();
foreach (var room in levelDescription.GetGraph().Vertices)
{
var roomDescription = levelDescriptionGrid2D.GetRoomDescription(room);
if (!roomDescription.IsCorridor)
{
roomTemplates.AddRange(roomDescription.RoomTemplates);
}
}
roomTemplates = roomTemplates.Distinct().ToList();

var result = new Result
{
Summary = ""
};

var summaries = new List<string>()
{
DoorsOnAllSides(roomTemplates, result),
};

var summariesWithoutNulls = summaries.Where(x => x != null).ToList();
if (summariesWithoutNulls.Count == 0)
{
return result;
}

var sb = new StringBuilder();
sb.AppendLine("For the performance of the generator, it is important to add many door positions to individual room templates.");
sb.AppendLine("It is even more critical if you want to generate levels with cycles.");
sb.AppendLine("A good starting point is to use the Simple door mode that provides many door positions.");
sb.AppendLine("");
sb.AppendLine("We detected potential issues related to doors below:");
sb.AppendLine("");

result.IsPotentialProblem = true;

result.Summary = sb.ToString();
result.Summary += string.Join("\n", summariesWithoutNulls);

return result;
}

private string DoorsOnAllSides(List<RoomTemplateGrid2D> roomTemplates, Result result)
{
var hasAllDirectionsDoors = false;
foreach (var roomTemplate in roomTemplates)
{
var doors = roomTemplate.Doors.GetDoors(roomTemplate.Outline);
var distinctDirections = doors
.Select(x => x.Line.GetDirection())
.Distinct()
.Count();

if (distinctDirections >= 4)
{
hasAllDirectionsDoors = true;
break;
}
}

if (hasAllDirectionsDoors)
{
return null;
}

result.MissingDoorsOnAllSides = true;

var sb = new StringBuilder();
sb.AppendLine("There are no room templates that have doors on all 4 sides.");
sb.AppendLine("Such room templates are useful for the generator because they are often very versatile and can be used for rooms with many neighbors.");
sb.AppendLine("They are also very useful if you want to have cycles in your level graph.");

return sb.ToString();
}

public class Result : IDiagnosticResult
{
public string Name => "Not enough doors";

public string Summary { get; set; }

public bool IsPotentialProblem { get; set; }

public bool MissingDoorsOnAllSides { get; set; }
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Runtime/Grid2D/Common/Diagnostics/Diagnostics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public static List<IDiagnosticResult> Run(LevelDescriptionGrid2D levelDescriptio
results.Add(new WrongPositionGameObjects().Run(levelDescription));
results.Add(new OddCycles().Run(levelDescription));
results.Add(new CorridorTypes().Run(levelDescription));
results.Add(new NotEnoughDoors().Run(levelDescription));

return results;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &-7877986336414098987
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 8f692f83df7c1b5468af64edd22287dc, type: 3}
m_Name:
m_EditorClassIdentifier:
From: {fileID: -3829538508782324871}
To: {fileID: 3289652443752732884}
--- !u!114 &-7307270355954133241
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 8f692f83df7c1b5468af64edd22287dc, type: 3}
m_Name:
m_EditorClassIdentifier:
From: {fileID: -3649007993993380384}
To: {fileID: 3289652443752732884}
--- !u!114 &-3829538508782324871
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 8074dc491ddc34f4e83332d9eae76980, type: 3}
m_Name:
m_EditorClassIdentifier:
Position: {x: 240, y: 208}
Name: Room
IndividualRoomTemplates: []
RoomTemplateSets: []
--- !u!114 &-3649007993993380384
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 8074dc491ddc34f4e83332d9eae76980, type: 3}
m_Name:
m_EditorClassIdentifier:
Position: {x: 352, y: 144}
Name: Room
IndividualRoomTemplates: []
RoomTemplateSets: []
--- !u!114 &-3110113770019691134
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 8074dc491ddc34f4e83332d9eae76980, type: 3}
m_Name:
m_EditorClassIdentifier:
Position: {x: 464, y: 208}
Name: Room
IndividualRoomTemplates: []
RoomTemplateSets: []
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: b8400baee4cafd34091c865089a167b2, type: 3}
m_Name: NotEnoughDoorsNoFourSides
m_EditorClassIdentifier:
Connections:
- {fileID: -7307270355954133241}
- {fileID: -7877986336414098987}
- {fileID: 792699257021706418}
CorridorIndividualRoomTemplates: []
CorridorRoomTemplateSets: []
DefaultIndividualRoomTemplates:
- {fileID: 3020086594291796898, guid: 0e63bd7168493a94e9ffd4b0566f2965, type: 3}
DefaultRoomTemplateSets: []
Rooms:
- {fileID: -3829538508782324871}
- {fileID: 3289652443752732884}
- {fileID: -3110113770019691134}
- {fileID: -3649007993993380384}
EditorData:
PanOffset: {x: 0, y: 0}
Zoom: 1
RoomType: Edgar.Unity.Room
ConnectionType: Edgar.Unity.Connection
--- !u!114 &792699257021706418
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 8f692f83df7c1b5468af64edd22287dc, type: 3}
m_Name:
m_EditorClassIdentifier:
From: {fileID: 3289652443752732884}
To: {fileID: -3110113770019691134}
--- !u!114 &3289652443752732884
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 8074dc491ddc34f4e83332d9eae76980, type: 3}
m_Name:
m_EditorClassIdentifier:
Position: {x: 352, y: 208}
Name: Room
IndividualRoomTemplates: []
RoomTemplateSets: []

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

76 changes: 76 additions & 0 deletions Tests/Runtime/Scenes/TimeoutDiagnostics/TimeoutDiagnostic.unity
Original file line number Diff line number Diff line change
Expand Up @@ -729,6 +729,82 @@ Transform:
m_Father: {fileID: 0}
m_RootOrder: 3
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &931995039
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 931995041}
- component: {fileID: 931995040}
m_Layer: 0
m_Name: NotEnoughDoorsNoFourSides
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &931995040
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 931995039}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 11725bdbb93631241b38951f78cae60c, type: 3}
m_Name:
m_EditorClassIdentifier:
version: 3
EnableDiagnostics: 0
FixedLevelGraphConfig:
LevelGraph: {fileID: 11400000, guid: a94d731b80196b34bae9d1eaba013383, type: 2}
UseCorridors: 0
GeneratorConfig:
RootGameObject: {fileID: 0}
Timeout: 1
RepeatModeOverride: 0
MinimumRoomDistance: 1
RoomTemplatePrefabMode: 0
PostProcessConfig:
InitializeSharedTilemaps: 1
TilemapLayersStructure: 0
TilemapLayersHandler: {fileID: 0}
TilemapLayersExample: {fileID: 0}
TilemapMaterial: {fileID: 0}
CopyTilesToSharedTilemaps: 1
CenterGrid: 1
DisableRoomTemplatesRenderers: 1
DisableRoomTemplatesColliders: 1
CustomPostProcessTasks: []
OtherConfig:
UseRandomSeed: 1
RandomGeneratorSeed: 0
GenerateOnStart: 1
AdvancedConfig:
ThrowExceptionsImmediately: 0
UseRandomSeed: 0
RandomGeneratorSeed: 0
GenerateOnStart: 0
ThrowExceptionsImmediately: 0
DisableCustomPostProcessing: 0
--- !u!4 &931995041
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 931995039}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 12
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1020620959
GameObject:
m_ObjectHideFlags: 0
Expand Down
13 changes: 13 additions & 0 deletions Tests/Runtime/TimeoutDiagnosticTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,19 @@ public void CorridorTypesHorizontal()
Assert.That(result.CorridorTypes, Is.EquivalentTo(new List<CorridorTypes.CorridorType>() { CorridorTypes.CorridorType.Horizontal }));
Assert.That(result.IsPotentialProblem, Is.True);
}

[Test]
public void NotEnoughDoorsNoFourSides()
{
var dungeonGeneratorGameObject = GameObject.Find("NotEnoughDoorsNoFourSides");
var dungeonGenerator = dungeonGeneratorGameObject.GetComponent<DungeonGeneratorGrid2D>();

var exception = Assert.Throws<TimeoutException>(() => dungeonGenerator.Generate());
var result = GetResult<NotEnoughDoors.Result>(exception);

Assert.That(result.MissingDoorsOnAllSides, Is.True);
Assert.That(result.IsPotentialProblem, Is.True);
}

private TResult GetResult<TResult>(TimeoutException exception, bool allowOnlySingle = true) where TResult : class
{
Expand Down

0 comments on commit 1755e55

Please sign in to comment.