Merge pull request #1 from Xevion/optimization

Major Optimizations
This commit is contained in:
2020-11-24 22:08:02 -06:00
committed by GitHub
23 changed files with 883 additions and 249 deletions

1
Paths/.gitignore vendored
View File

@@ -0,0 +1 @@
/Assets/TextMesh Pro/**

View File

@@ -1,33 +0,0 @@
fileFormatVersion: 2
guid: d2139aa590f628641baaa96cfa467569
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 1
settings:
DefaultValueInitialized: true
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -43,7 +43,7 @@ RenderSettings:
--- !u!157 &3
LightmapSettings:
m_ObjectHideFlags: 0
serializedVersion: 11
serializedVersion: 12
m_GIWorkflowMode: 1
m_GISettings:
serializedVersion: 2
@@ -94,10 +94,11 @@ LightmapSettings:
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
m_PVRFilteringAtrousPositionSigmaIndirect: 2
m_PVRFilteringAtrousPositionSigmaAO: 1
m_ShowResolutionOverlay: 1
m_ExportTrainingData: 0
m_TrainingDataDestination: TrainingData
m_LightProbeSampleCountMultiplier: 4
m_LightingDataAsset: {fileID: 0}
m_UseShadowmask: 1
m_LightingSettings: {fileID: 628914115}
--- !u!196 &4
NavMeshSettings:
serializedVersion: 2
@@ -117,6 +118,8 @@ NavMeshSettings:
manualTileSize: 0
tileSize: 256
accuratePlacement: 0
maxJobWorkers: 0
preserveTilesOutsideBounds: 0
debug:
m_Flags: 0
m_NavMeshData: {fileID: 0}
@@ -203,6 +206,67 @@ Transform:
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!850595691 &628914115
LightingSettings:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Settings.lighting
serializedVersion: 2
m_GIWorkflowMode: 1
m_EnableBakedLightmaps: 0
m_EnableRealtimeLightmaps: 0
m_RealtimeEnvironmentLighting: 1
m_BounceScale: 1
m_AlbedoBoost: 1
m_IndirectOutputScale: 1
m_UsingShadowmask: 1
m_BakeBackend: 0
m_LightmapMaxSize: 1024
m_BakeResolution: 40
m_Padding: 2
m_TextureCompression: 1
m_AO: 0
m_AOMaxDistance: 1
m_CompAOExponent: 1
m_CompAOExponentDirect: 0
m_ExtractAO: 0
m_MixedBakeMode: 2
m_LightmapsBakeMode: 1
m_FilterMode: 1
m_LightmapParameters: {fileID: 0}
m_ExportTrainingData: 0
m_TrainingDataDestination: TrainingData
m_RealtimeResolution: 2
m_ForceWhiteAlbedo: 0
m_ForceUpdates: 0
m_FinalGather: 0
m_FinalGatherRayCount: 256
m_FinalGatherFiltering: 1
m_PVRCulling: 1
m_PVRSampling: 1
m_PVRDirectSampleCount: 32
m_PVRSampleCount: 500
m_PVREnvironmentSampleCount: 500
m_PVREnvironmentReferencePointCount: 2048
m_LightProbeSampleCountMultiplier: 4
m_PVRBounces: 2
m_PVRRussianRouletteStartBounce: 2
m_PVREnvironmentMIS: 0
m_PVRFilteringMode: 2
m_PVRDenoiserTypeDirect: 0
m_PVRDenoiserTypeIndirect: 0
m_PVRDenoiserTypeAO: 0
m_PVRFilterTypeDirect: 0
m_PVRFilterTypeIndirect: 0
m_PVRFilterTypeAO: 0
m_PVRFilteringGaussRadiusDirect: 1
m_PVRFilteringGaussRadiusIndirect: 5
m_PVRFilteringGaussRadiusAO: 2
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
m_PVRFilteringAtrousPositionSigmaIndirect: 2
m_PVRFilteringAtrousPositionSigmaAO: 1
--- !u!1 &1373243071
GameObject:
m_ObjectHideFlags: 0
@@ -250,8 +314,8 @@ MonoBehaviour:
gridObject: {fileID: 2092623184}
gridController: {fileID: 2092623185}
debugText: {fileID: 1436240699}
speed: 1000
clampIncrement: 1
speed: 2500
clampIncrement: 2
--- !u!1 &1436240698
GameObject:
m_ObjectHideFlags: 0
@@ -262,8 +326,6 @@ GameObject:
m_Component:
- component: {fileID: 1436240703}
- component: {fileID: 1436240702}
- component: {fileID: 1436240701}
- component: {fileID: 1436240700}
- component: {fileID: 1436240699}
m_Layer: 0
m_Name: DebugText
@@ -287,11 +349,11 @@ MonoBehaviour:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
m_text:
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
@@ -313,13 +375,12 @@ MonoBehaviour:
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: 0
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_outlineColor:
serializedVersion: 2
rgba: 4278190080
m_fontSize: 5
m_fontSizeBase: 5
m_fontWeight: 400
@@ -327,7 +388,9 @@ MonoBehaviour:
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 0
m_textAlignment: 257
m_HorizontalAlignment: 1
m_VerticalAlignment: 256
m_textAlignment: 65535
m_characterSpacing: 0
m_wordSpacing: 0
m_lineSpacing: 0
@@ -337,10 +400,8 @@ MonoBehaviour:
m_enableWordWrapping: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_firstOverflowCharacterIndex: -1
m_linkedTextComponent: {fileID: 0}
m_isLinkedTextComponent: 0
m_isTextTruncated: 0
parentLinkedComponent: {fileID: 0}
m_enableKerning: 1
m_enableExtraPadding: 0
checkPaddingRequired: 0
@@ -348,58 +409,22 @@ MonoBehaviour:
m_parseCtrlCharacters: 1
m_isOrthographic: 0
m_isCullingEnabled: 0
m_ignoreRectMaskCulling: 0
m_ignoreCulling: 1
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 1
m_firstVisibleCharacter: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: -0.04661131, z: -0.07833099, w: -0.033168316}
m_textInfo:
textComponent: {fileID: 1436240699}
characterCount: 0
spriteCount: 0
spaceCount: 0
wordCount: 0
linkCount: 0
lineCount: 0
pageCount: 0
materialCount: 1
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_spriteAnimator: {fileID: 0}
m_hasFontAssetChanged: 0
m_renderer: {fileID: 1436240702}
m_subTextObjects:
- {fileID: 0}
- {fileID: 0}
- {fileID: 0}
- {fileID: 0}
- {fileID: 0}
- {fileID: 0}
- {fileID: 0}
- {fileID: 0}
m_maskType: 0
--- !u!222 &1436240700
CanvasRenderer:
m_ObjectHideFlags: 2
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1436240698}
m_CullTransparentMesh: 0
--- !u!33 &1436240701
MeshFilter:
m_ObjectHideFlags: 2
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1436240698}
m_Mesh: {fileID: 0}
_SortingLayerID: 0
_SortingOrder: 0
--- !u!23 &1436240702
MeshRenderer:
m_ObjectHideFlags: 0
@@ -414,6 +439,8 @@ MeshRenderer:
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
@@ -425,6 +452,7 @@ MeshRenderer:
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
@@ -437,6 +465,7 @@ MeshRenderer:
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!224 &1436240703
RectTransform:
m_ObjectHideFlags: 0
@@ -481,8 +510,9 @@ Light:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1951333406}
m_Enabled: 1
serializedVersion: 9
serializedVersion: 10
m_Type: 1
m_Shape: 0
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_Intensity: 1.49
m_Range: 10
@@ -579,8 +609,8 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
gridMaterial: {fileID: 2100000, guid: 780d53bea4df7b0418e9c8ed8afd6410, type: 2}
width: 130
height: 61
width: 10
height: 10
--- !u!23 &2092623186
MeshRenderer:
m_ObjectHideFlags: 0
@@ -595,6 +625,8 @@ MeshRenderer:
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
@@ -606,6 +638,7 @@ MeshRenderer:
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
@@ -618,6 +651,7 @@ MeshRenderer:
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!33 &2092623187
MeshFilter:
m_ObjectHideFlags: 0

View File

@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace Algorithms {
@@ -9,56 +8,66 @@ namespace Algorithms {
private Stack<Node> _path;
private List<Node> _openList;
private List<Node> _closedList;
private List<GridState> _states;
public ChangeController ChangeController { get; private set; }
public Vector2Int Start { get; private set; }
public Vector2Int End { get; private set; }
public AStar(NodeGrid nodeGrid) {
this._nodeGrid = nodeGrid;
_states = new List<GridState>();
ChangeController = new ChangeController(nodeGrid.RenderNodeTypes());
}
public Stack<Node> FindPath(Vector2Int start, Vector2Int end) {
this.Start = start;
this.End = end;
var startNode = new Node(start, true);
var endNode = new Node(end, true);
ChangeController.AddChange(new Change(start.x, start.y, GridNodeType.Start, GridNodeType.Empty));
ChangeController.AddChange(new Change(end.x, end.y, GridNodeType.End, GridNodeType.Empty));
Node startNode = _nodeGrid.Grid[start.x, start.y];
Node endNode = _nodeGrid.Grid[end.x, end.y];
_path = new Stack<Node>();
_openList = new List<Node>();
_closedList = new List<Node>();
RecordState();
Node current = startNode;
// add start node to Open List
startNode.State = NodeState.Open;
_openList.Add(startNode);
while (_openList.Count != 0 && !_closedList.Exists(x => x.Position == endNode.Position)) {
while (_openList.Count != 0) {
current = _openList[0];
_openList.Remove(current);
_openList.RemoveAt(0);
current.State = NodeState.Closed;
ChangeController.AddChange(new Change(
current.Position.x, current.Position.y,
GridNodeType.Expanded, GridNodeType.Seen));
_closedList.Add(current);
RecordState();
if (current.Position == endNode.Position)
break;
Node[] adjacentNodes = this._nodeGrid.GetAdjacentNodesArray(current);
if (true) {
for (int i = 0; i < adjacentNodes.Length; i++) {
Node n = adjacentNodes[i];
if (n == null) continue;
for (int i = 0; i < adjacentNodes.Length; i++) {
Node node = adjacentNodes[i];
if (node != null && node.State == NodeState.None && node.Walkable) {
// Setup node & calculate new costs
node.Parent = current;
node.DistanceToTarget = NodeGrid.Manhattan(node, endNode);
node.Cost = node.Weight + node.Parent.Cost;
if (!_closedList.Contains(n) && n.Walkable) {
if (!_openList.Contains(n)) {
n.Parent = current;
n.DistanceToTarget = NodeGrid.Manhattan(n, endNode);
n.Cost = n.Weight + n.Parent.Cost;
node.State = NodeState.Open;
ChangeController.AddChange(new Change(node.Position.x, node.Position.y, GridNodeType.Seen,
GridNodeType.Empty));
_openList.Add(n);
_openList = _openList.OrderBy(node => node.F).ToList();
}
}
// Insert the new node into the sorted open list in ascending order
int index = _openList.BinarySearch(node);
if (index < 0) index = ~index;
_openList.Insert(index, node);
}
}
}
@@ -68,34 +77,19 @@ namespace Algorithms {
return null;
}
// Fix start position being overriden
ChangeController.RemovePositions(start, 1);
// if all good, return path
Node temp = _closedList[_closedList.IndexOf(current)];
if (temp == null) return null;
do {
_path.Push(temp);
RecordState();
ChangeController.AddChange(new Change(temp.Position.x, temp.Position.y, GridNodeType.Path, GridNodeType.Expanded));
temp = temp.Parent;
} while (temp != startNode && temp != null);
} while (temp != null && !temp.Equals(startNode));
return _path;
}
/// <summary>
/// Records the current state of the pathfinding algorithm in the grid.
/// </summary>
public void RecordState() {
// TODO: Record pathfinding state information (stages, heuristic, statistical info)
this._states.Add(
new GridState(this._nodeGrid, this._openList, this._closedList, Start, End, _path)
);
}
/// <summary>
/// Returns the current list of grid states of the pathfinding algorithm.
/// </summary>
/// <returns>A list of GridState objects representing the pathfinding algorithm's progress</returns>
public List<GridState> GetStates() {
return this._states;
}
}
}

View File

@@ -1,20 +1,27 @@
using UnityEngine;
using System;
using UnityEngine;
namespace Algorithms {
public class Node {
public enum NodeState {
None, Open, Closed
}
public class Node : IComparable<Node> {
// Change this depending on what the desired size is for each element in the grid
public Node Parent;
public Vector2Int Position;
public readonly Vector2Int Position;
// A* Algorithm variables
public float DistanceToTarget;
public float Cost;
public float? DistanceToTarget;
public float? Cost;
public float Weight;
public NodeState State = NodeState.None;
public float F {
get {
if (DistanceToTarget != -1 && Cost != -1)
return DistanceToTarget + Cost;
if (DistanceToTarget.HasValue && Cost.HasValue)
return DistanceToTarget.Value + Cost.Value;
return -1;
}
}
@@ -24,14 +31,34 @@ namespace Algorithms {
public Node(Vector2Int pos, bool walkable, float weight = 1) {
Parent = null;
Position = pos;
DistanceToTarget = -1;
DistanceToTarget = null;
Cost = 1;
Weight = weight;
Walkable = walkable;
}
public override bool Equals(object obj) {
return obj is Node node && Position.Equals(node.Position);
}
public override int GetHashCode() {
return Position.GetHashCode();
}
public int CompareTo(Node other) {
int diff = (int) (this.F - other.F);
return diff;
// return diff != 0 ? diff : NodeGrid.SignedManhattan(Position, other.Position);
}
public override string ToString() {
return $"Node({Position.x}, {Position.y}, {Walkable})";
return string.Format(
"Node ({0:00}, {1:00}, {2}, {3})",
Position.x,
Position.y,
Walkable ? "Walkable" : "Not Walkable",
State == NodeState.None ? (Walkable ? "Openable" : "Wall") : State.ToString()
);
}
}
}

View File

@@ -55,7 +55,7 @@ namespace Algorithms {
int col = node.Position.x;
int row = node.Position.y;
return new Node[] {
return new [] {
row + 1 < Height ? Grid[col, row + 1] : null,
row - 1 >= 0 ? Grid[col, row - 1] : null,
col - 1 >= 0 ? Grid[col - 1, row] : null,
@@ -67,12 +67,16 @@ namespace Algorithms {
return Grid[position.x, position.y];
}
public static float Manhattan(Node a, Node b) {
return Math.Abs(a.Position.x - b.Position.x) + Math.Abs(a.Position.y - b.Position.y);
public static int Manhattan(Node a, Node b) {
return Manhattan(a.Position, b.Position);
}
public static float Manhattan(Vector2Int a, Vector2Int b) {
return Manhattan(new Node(a, false), new Node(b, false));
public static int SignedManhattan(Vector2Int a, Vector2Int b) {
return a.x - b.x + (a.y - b.y);
}
public static int Manhattan(Vector2Int a, Vector2Int b) {
return Math.Abs(a.x - b.x) + Math.Abs(a.y - b.y);
}
/// <summary>
@@ -134,5 +138,17 @@ namespace Algorithms {
Grid[(int) x, (int) y].Walkable = true;
}
}
public GridNodeType[,] RenderNodeTypes() {
GridNodeType[,] nodeTypeGrid = new GridNodeType[Grid.GetLength(0), Grid.GetLength(1)];
for (int x = 0; x < Grid.GetLength(0); x++) {
for (int y = 0; y < Grid.GetLength(1); y++) {
nodeTypeGrid[x, y] = Grid[x, y].Walkable ? GridNodeType.Empty : GridNodeType.Wall;
}
}
return nodeTypeGrid;
}
}
}

View File

@@ -0,0 +1,19 @@
public readonly struct Change {
public readonly int X;
public readonly int Y;
public readonly GridNodeType New;
public readonly GridNodeType Old;
public readonly float Time;
public Change(int x, int y, GridNodeType newType, GridNodeType oldType) {
this.X = x;
this.Y = y;
this.New = newType;
this.Old = oldType;
this.Time = UnityEngine.Time.realtimeSinceStartup;
}
public override string ToString() {
return $"Change({X}, {Y}, {Old} -> {New})";
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ce434b5fefcc4447bc8adc1ab11dd964
timeCreated: 1606250638

View File

@@ -0,0 +1,156 @@
using System;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// Helps manage Change value types by rendering forward/backward movements to a Enum array.
/// </summary>
public class ChangeController {
private readonly GridNodeType[,] _initial;
public GridNodeType[,] Current { get; private set; }
public bool[,] DirtyFlags { get; private set; }
public int Index { get; private set; }
private readonly List<Change> _changes;
public int Count => _changes.Count;
public Change CurrentChange => _changes[Index];
public double CurrentRuntime => _changes[Index].Time - _changes[0].Time;
public ChangeController(GridNodeType[,] initial) {
_initial = initial;
Current = initial;
Index = -1;
_changes = new List<Change>();
DirtyFlags = new bool[initial.GetLength(0), initial.GetLength(1)];
SetDirty();
}
/// <summary>
/// Sets the entire grid as dirty, essentially re-rendering all values in the shader.
/// </summary>
public void SetDirty() {
int width = DirtyFlags.GetLength(0);
int height = DirtyFlags.GetLength(1);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
DirtyFlags[x, y] = true;
}
}
}
/// <summary>
/// Sets only a specific position as dirty.
/// </summary>
/// <param name="position"></param>
public void SetDirty(Vector2Int position) {
DirtyFlags[position.x, position.y] = true;
}
/// <summary>
/// Resets the ChangeController back to the initial state.
/// </summary>
public void Reset() {
Current = _initial;
SetDirty();
}
/// <summary>
/// Adds a new change to the list.
/// </summary>
/// <param name="change">A valid Change value type.</param>
public void AddChange(Change change) {
_changes.Add(change);
}
/// <summary>
/// Move the ChangeController's current index forward by index.
/// Positive values only, wil only result in forward movement (if any).
/// </summary>
/// <param name="n">The number of times to move forward.</param>
public void Forward(int n = 1) {
if (n < 0)
throw new ArgumentOutOfRangeException(nameof(n));
for (int i = 0; i < n; i++) {
Change cur = _changes[++Index];
Current[cur.X, cur.Y] = cur.New;
SetDirty(new Vector2Int(cur.X, cur.Y));
}
}
/// <summary>
/// Move the ChangeController's current index backward by index.
/// Positive values only, will only result in backward movement (if any).
/// </summary>
/// <param name="n">The number of times to move backward.</param>
public void Reverse(int n = 1) {
if (n < 0)
throw new ArgumentOutOfRangeException(nameof(n));
if (n > 5 && Index - n == 0)
Reset(); // resetting by copying values instead of mutating might be easier.
else {
for (int i = 0; i < n; i++) {
Change cur = _changes[--Index];
Current[cur.X, cur.Y] = cur.Old;
SetDirty(new Vector2Int(cur.X, cur.Y));
}
}
}
/// <summary>
/// Move the ChangeController's current index by index, forward or backward.
/// Values can be positive or negative to determine movement. Best used for calculating movement via difference.
/// </summary>
/// <param name="n">The number of times to move. Sign determines direction.</param>
public void Move(int n) {
if (n > 0)
Forward(n);
else if (n < 0)
Reverse(-n);
}
/// <summary>
/// Move to this specific index in the ChangeController's states.
/// All changes will be applied to get here, either forward or reverse.
/// </summary>
/// <param name="index">The new index to move to.</param>
/// <exception cref="ArgumentOutOfRangeException">When the index is invalid.</exception>
public void MoveTo(int index) {
// check that index is valid at least
if (index >= _changes.Count || index < 0)
throw new ArgumentOutOfRangeException(nameof(index),
$"Cannot move to change index {index}. Only indexes from 0 to {_changes.Count - 1} are valid.");
// diff & move to
int diff = index - Index;
if (diff != 0)
// prefer resetting if index is 0 and it needs to move at least some.
if (index == 0 && diff > 5)
Reset();
else
Move(diff);
}
/// <summary>
/// Removes all Change values referencing a specific position.
/// Intended for fixing start and end positions.
/// Works in reverse, i.e. count = 1 removes the last position if any.
/// </summary>
/// <param name="position">The Vector2Int position to look for.</param>
/// <param name="count">Maximum number of Change values to remove. -1 for all.</param>
public void RemovePositions(Vector2Int position, int count = -1) {
if (count == 0)
return;
for (int i = _changes.Count - 1; i >= 0; i--)
if (_changes[i].X == position.x && _changes[i].Y == position.y) {
_changes.RemoveAt(i);
// Return if the count is now zero.
if (--count == 0)
return;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f90bfa4d7a4f45968a29175338225e65
timeCreated: 1606251343

View File

@@ -68,17 +68,39 @@ public class GridController : MonoBehaviour {
/// <summary>
/// Loads a GridState into the Grid Shader's StructuredBuffer
/// </summary>
/// <param name="gridState"></param>
public void LoadGridState(GridState gridState) {
/// <param name="state"></param>
public void LoadGridState(GridNodeType[,] state) {
// Loop over matrix and set values via cast Enum to int
for (int x = 0; x < gridState.Grid.GetLength(0); x++) {
for (int y = 0; y < gridState.Grid.GetLength(1); y++)
this.SetValue(x, y, (int) gridState.Grid[x, y]);
int gridWidth = state.GetLength(0);
int gridHeight = state.GetLength(1);
for (int x = 0; x < gridWidth; x++) {
for (int y = 0; y < gridHeight; y++)
SetValue(x, y, (int) state[x, y]);
}
UpdateShader(PropertyName.Values);
}
/// <summary>
/// A more performant method of loading GridState values into the shader.
/// </summary>
/// <param name="state"></param>
/// <param name="dirtyFlags"></param>
public void LoadDirtyGridState(GridNodeType[,] state, bool[,] dirtyFlags) {
int gridWidth = state.GetLength(0);
for (int x = 0; x < gridWidth; x++) {
int gridHeight = state.GetLength(1);
for (int y = 0; y < gridHeight; y++)
// only set value if the value has been marked as dirty
if (dirtyFlags[x, y]) {
SetValue(x, y, (int) state[x, y]);
dirtyFlags[x, y] = false;
}
}
UpdateShader(PropertyName.Values);
}
/// <summary>
/// Sets a value in the 1D array at a particular 2D coordinate
/// </summary>

View File

@@ -1,51 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using Algorithms;
using UnityEngine;
public class GridState {
public readonly GridNodeType[,] Grid;
public readonly float Time;
public GridState(NodeGrid grid, IReadOnlyList<Node> seen, IReadOnlyList<Node> expanded, Vector2Int start,
Vector2Int end, Stack<Node> path) {
this.Time = UnityEngine.Time.realtimeSinceStartup;
Grid = new GridNodeType[grid.Width, grid.Height];
// Add walls and empty tiles
for (int x = 0; x < grid.Width; x++) {
for (int y = 0; y < grid.Height; y++) {
Grid[x, y] = grid.Grid[x, y].Walkable ? GridNodeType.Empty : GridNodeType.Wall;
}
}
// Add 'seen' tiles
int length = seen.Count();
for (int i = 0; i < length; i++) {
Node seenNode = seen[i];
Grid[seenNode.Position.x, seenNode.Position.y] = GridNodeType.Seen;
}
// Add 'expanded' tiles
length = expanded.Count();
for (int i = 0; i < length; i++) {
Node expandedNode = expanded[i];
Grid[expandedNode.Position.x, expandedNode.Position.y] = GridNodeType.Expanded;
}
// Add 'path' tiles
if (path != null) {
Node[] pathArray = path.ToArray();
length = pathArray.Length;
for (int i = 0; i < length; i++) {
Node pathNode = pathArray[i];
Grid[pathNode.Position.x, pathNode.Position.y] = GridNodeType.Path;
}
}
// Set start and end tiles
Grid[start.x, start.y] = GridNodeType.Start;
Grid[end.x, end.y] = GridNodeType.End;
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 1a26aa7e514043e8911382088176258b
timeCreated: 1604887099

View File

@@ -14,12 +14,7 @@ public interface IPathfinding {
/// <returns>A List of NodeGridGrid objects representing the timeline of Pathfinding</returns>
Stack<Node> FindPath(Vector2Int start, Vector2Int end);
/// <summary>
/// Records the current state of the pathfinding algorithm. Internal usage only.
/// </summary>
void RecordState();
List<GridState> GetStates();
Vector2Int Start { get; }
Vector2Int End { get; }
ChangeController ChangeController { get; }
}

View File

@@ -4,16 +4,16 @@ using Algorithms;
using LevelGeneration;
using TMPro;
using UnityEngine;
using UnityEngine.Analytics;
/// <summary>
/// The primary controller of the entire application, managing state, events and sending commands
/// </summary>
public class Manager : MonoBehaviour {
private IPathfinding _algorithm;
private List<GridState> _states;
private ChangeController _state;
private int _curIndex;
private Stack<Node> _path;
private float _lastStart;
private float _runtime;
public Camera mainCamera;
@@ -29,7 +29,6 @@ public class Manager : MonoBehaviour {
}
public void Start() {
_states = new List<GridState>();
GeneratePath();
Resize();
}
@@ -39,66 +38,87 @@ public class Manager : MonoBehaviour {
// Gizmos.DrawWireCube(transform.position, new Vector3(size, size, size));
// }
/// <summary>
/// Returns the current time multiplier, based on the latest change in the path.
/// </summary>
/// <returns>A positive non-zero float representing how fast the current frame should be processed.</returns>
private float CurrentMultiplier() {
if (_state.Index == -1)
return 1;
switch (_state.CurrentChange.New) {
case GridNodeType.Path:
return 1/5f;
case GridNodeType.Empty:
break;
case GridNodeType.Wall:
break;
case GridNodeType.Start:
break;
case GridNodeType.End:
break;
case GridNodeType.Seen:
break;
case GridNodeType.Expanded:
break;
default:
throw new ArgumentOutOfRangeException();
}
return 1;
}
public void Update() {
var increment = Time.deltaTime * speed;
var increment = Time.deltaTime * speed * CurrentMultiplier();
if (clampIncrement > 0)
increment = Mathf.Clamp(increment, 0, _states.Count * Time.deltaTime / clampIncrement);
increment = Mathf.Clamp(increment, 0, _state.Count * Time.deltaTime / clampIncrement);
_runtime += increment;
if (CurrentIndex < _states.Count)
this.LoadNextState();
if (CurrentIndex < _state.Count)
LoadNextState();
else {
try {
_lastStart = Time.realtimeSinceStartup;
GeneratePath();
CurrentIndex = 0;
// _curIndex = path != null && path.Count > 30 ? 0 : _states.Count;
}
catch (ArgumentOutOfRangeException) {
}
GeneratePath();
CurrentIndex = 0;
}
}
private void GeneratePath() {
var nodeGrid = new NodeGrid(gridController.width, gridController.height);
_algorithm = new AStar(nodeGrid);
Vector2Int start = nodeGrid.RandomPosition();
// Vector2Int start = new Vector2Int(30, 30);
Vector2Int end = nodeGrid.RandomPosition();
nodeGrid.ApplyGenerator(new RandomPlacement(0.25f, true));
nodeGrid.ApplyGenerator(new RandomPlacement(0.3f, true, true));
nodeGrid.GetNode(start).Walkable = true;
nodeGrid.GetNode(end).Walkable = true;
_algorithm = new AStar(nodeGrid);
_path = _algorithm.FindPath(start, end);
_states = _algorithm.GetStates();
_state = _algorithm.ChangeController;
}
private void LoadNextState() {
GridState state = _states[CurrentIndex];
gridController.LoadGridState(state);
_state.MoveTo(CurrentIndex);
gridController.LoadDirtyGridState(_state.Current, _state.DirtyFlags);
float change = state.Time - _lastStart;
string pathCount = _path != null ? $"{_path.Count}" : "N/A";
debugText.text = $"{change * 1000.0:F1}ms\n" +
$"{this.CurrentIndex:000} / {this._states.Count:000}\n" +
debugText.text = $"{_state.CurrentRuntime * 1000.0:F1}ms\n" +
$"{this.CurrentIndex:000} / {_state.Count:000}\n" +
$"Path: {pathCount} tiles";
}
/// <summary>
/// Scales the GridController GameObject to fit within the Camera
/// </summary>
public void Resize() {
private void Resize() {
float ratioImage = (float) gridController.width / gridController.height;
float ratioScreen = mainCamera.aspect;
var orthographicSize = mainCamera.orthographicSize;
var image = new Vector2(gridController.width, gridController.height);
var screen = new Vector2(2 * orthographicSize * mainCamera.aspect, orthographicSize * 2);
gridObject.transform.localScale = ratioScreen > ratioImage
? new Vector3(image.x * screen.y / image.y, screen.y, 0.001f)
: new Vector3(screen.x, image.y * screen.x / image.x, 0.001f);

View File

@@ -1,13 +1,20 @@
{
"dependencies": {
"com.unity.ads": "2.0.8",
"com.unity.analytics": "3.3.2",
"com.unity.collab-proxy": "1.2.16",
"com.unity.package-manager-ui": "2.1.2",
"com.unity.purchasing": "2.0.6",
"com.unity.textmeshpro": "2.0.0",
"com.unity.timeline": "1.0.0",
"com.unity.2d.sprite": "1.0.0",
"com.unity.2d.tilemap": "1.0.0",
"com.unity.ads": "3.5.0",
"com.unity.analytics": "3.5.3",
"com.unity.collab-proxy": "1.3.9",
"com.unity.ide.rider": "1.2.1",
"com.unity.ide.visualstudio": "2.0.3",
"com.unity.ide.vscode": "1.2.3",
"com.unity.purchasing": "2.1.1",
"com.unity.test-framework": "1.1.18",
"com.unity.textmeshpro": "3.0.1",
"com.unity.timeline": "1.2.6",
"com.unity.ugui": "1.0.0",
"com.unity.modules.ai": "1.0.0",
"com.unity.modules.androidjni": "1.0.0",
"com.unity.modules.animation": "1.0.0",
"com.unity.modules.assetbundle": "1.0.0",
"com.unity.modules.audio": "1.0.0",

View File

@@ -0,0 +1,370 @@
{
"dependencies": {
"com.unity.2d.sprite": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.2d.tilemap": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.ads": {
"version": "3.5.0",
"depth": 0,
"source": "registry",
"dependencies": {
"com.unity.ugui": "1.0.0"
},
"url": "https://packages.unity.com"
},
"com.unity.analytics": {
"version": "3.5.3",
"depth": 0,
"source": "registry",
"dependencies": {
"com.unity.ugui": "1.0.0"
},
"url": "https://packages.unity.com"
},
"com.unity.collab-proxy": {
"version": "1.3.9",
"depth": 0,
"source": "registry",
"dependencies": {},
"url": "https://packages.unity.com"
},
"com.unity.ext.nunit": {
"version": "1.0.0",
"depth": 1,
"source": "registry",
"dependencies": {},
"url": "https://packages.unity.com"
},
"com.unity.ide.rider": {
"version": "1.2.1",
"depth": 0,
"source": "registry",
"dependencies": {
"com.unity.test-framework": "1.1.1"
},
"url": "https://packages.unity.com"
},
"com.unity.ide.visualstudio": {
"version": "2.0.3",
"depth": 0,
"source": "registry",
"dependencies": {},
"url": "https://packages.unity.com"
},
"com.unity.ide.vscode": {
"version": "1.2.3",
"depth": 0,
"source": "registry",
"dependencies": {},
"url": "https://packages.unity.com"
},
"com.unity.purchasing": {
"version": "2.1.1",
"depth": 0,
"source": "registry",
"dependencies": {
"com.unity.ugui": "1.0.0"
},
"url": "https://packages.unity.com"
},
"com.unity.test-framework": {
"version": "1.1.18",
"depth": 0,
"source": "registry",
"dependencies": {
"com.unity.ext.nunit": "1.0.0",
"com.unity.modules.imgui": "1.0.0",
"com.unity.modules.jsonserialize": "1.0.0"
},
"url": "https://packages.unity.com"
},
"com.unity.textmeshpro": {
"version": "3.0.1",
"depth": 0,
"source": "registry",
"dependencies": {
"com.unity.ugui": "1.0.0"
},
"url": "https://packages.unity.com"
},
"com.unity.timeline": {
"version": "1.2.6",
"depth": 0,
"source": "registry",
"dependencies": {},
"url": "https://packages.unity.com"
},
"com.unity.ugui": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.ui": "1.0.0",
"com.unity.modules.imgui": "1.0.0"
}
},
"com.unity.modules.ai": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.androidjni": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.animation": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.assetbundle": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.audio": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.cloth": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.physics": "1.0.0"
}
},
"com.unity.modules.director": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.audio": "1.0.0",
"com.unity.modules.animation": "1.0.0"
}
},
"com.unity.modules.imageconversion": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.imgui": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.jsonserialize": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.particlesystem": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.physics": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.physics2d": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.screencapture": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.imageconversion": "1.0.0"
}
},
"com.unity.modules.subsystems": {
"version": "1.0.0",
"depth": 1,
"source": "builtin",
"dependencies": {
"com.unity.modules.jsonserialize": "1.0.0"
}
},
"com.unity.modules.terrain": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.terrainphysics": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.physics": "1.0.0",
"com.unity.modules.terrain": "1.0.0"
}
},
"com.unity.modules.tilemap": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.physics2d": "1.0.0"
}
},
"com.unity.modules.ui": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.uielements": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.ui": "1.0.0",
"com.unity.modules.imgui": "1.0.0",
"com.unity.modules.jsonserialize": "1.0.0",
"com.unity.modules.uielementsnative": "1.0.0"
}
},
"com.unity.modules.uielementsnative": {
"version": "1.0.0",
"depth": 1,
"source": "builtin",
"dependencies": {
"com.unity.modules.ui": "1.0.0",
"com.unity.modules.imgui": "1.0.0",
"com.unity.modules.jsonserialize": "1.0.0"
}
},
"com.unity.modules.umbra": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.unityanalytics": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.unitywebrequest": "1.0.0",
"com.unity.modules.jsonserialize": "1.0.0"
}
},
"com.unity.modules.unitywebrequest": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.unitywebrequestassetbundle": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.assetbundle": "1.0.0",
"com.unity.modules.unitywebrequest": "1.0.0"
}
},
"com.unity.modules.unitywebrequestaudio": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.unitywebrequest": "1.0.0",
"com.unity.modules.audio": "1.0.0"
}
},
"com.unity.modules.unitywebrequesttexture": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.unitywebrequest": "1.0.0",
"com.unity.modules.imageconversion": "1.0.0"
}
},
"com.unity.modules.unitywebrequestwww": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.unitywebrequest": "1.0.0",
"com.unity.modules.unitywebrequestassetbundle": "1.0.0",
"com.unity.modules.unitywebrequestaudio": "1.0.0",
"com.unity.modules.audio": "1.0.0",
"com.unity.modules.assetbundle": "1.0.0",
"com.unity.modules.imageconversion": "1.0.0"
}
},
"com.unity.modules.vehicles": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.physics": "1.0.0"
}
},
"com.unity.modules.video": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.audio": "1.0.0",
"com.unity.modules.ui": "1.0.0",
"com.unity.modules.unitywebrequest": "1.0.0"
}
},
"com.unity.modules.vr": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.jsonserialize": "1.0.0",
"com.unity.modules.physics": "1.0.0",
"com.unity.modules.xr": "1.0.0"
}
},
"com.unity.modules.wind": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.xr": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.physics": "1.0.0",
"com.unity.modules.jsonserialize": "1.0.0",
"com.unity.modules.subsystems": "1.0.0"
}
}
}
}

View File

@@ -31,6 +31,9 @@ GraphicsSettings:
m_AlwaysIncludedShaders:
- {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0}
- {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0}
- {fileID: 16000, guid: 0000000000000000f000000000000000, type: 0}
- {fileID: 16001, guid: 0000000000000000f000000000000000, type: 0}
- {fileID: 17000, guid: 0000000000000000f000000000000000, type: 0}
m_PreloadedShaders: []
m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000,
type: 0}

View File

@@ -0,0 +1,43 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &1
MonoBehaviour:
m_ObjectHideFlags: 61
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: 13964, guid: 0000000000000000e000000000000000, type: 0}
m_Name:
m_EditorClassIdentifier:
m_EnablePreviewPackages: 0
m_EnablePackageDependencies: 0
m_AdvancedSettingsExpanded: 1
m_ScopedRegistriesSettingsExpanded: 1
oneTimeWarningShown: 0
m_Registries:
- m_Id: main
m_Name:
m_Url: https://packages.unity.com
m_Scopes: []
m_IsDefault: 1
m_Capabilities: 7
m_UserSelectedRegistryName:
m_UserAddingNewScopedRegistry: 0
m_RegistryInfoDraft:
m_ErrorMessage:
m_Original:
m_Id:
m_Name:
m_Url:
m_Scopes: []
m_IsDefault: 0
m_Capabilities: 0
m_Modified: 0
m_Name:
m_Url:
m_Scopes:
-
m_SelectedScopeIndex: 0

View File

@@ -1,2 +1,2 @@
m_EditorVersion: 2019.1.1f1
m_EditorVersionWithRevision: 2019.1.1f1 (fef62e97e63b)
m_EditorVersion: 2020.1.14f1
m_EditorVersionWithRevision: 2020.1.14f1 (d81f64f5201d)

View File

@@ -4,7 +4,7 @@
UnityConnectSettings:
m_ObjectHideFlags: 0
serializedVersion: 1
m_Enabled: 0
m_Enabled: 1
m_TestMode: 0
m_EventOldUrl: https://api.uca.cloud.unity3d.com/v1/events
m_EventUrl: https://cdp.cloud.unity3d.com/v1/events

View File

@@ -0,0 +1,8 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!890905787 &1
VersionControlSettings:
m_ObjectHideFlags: 0
m_Mode: Visible Meta Files
m_CollabEditorSettings:
inProgressEnabled: 1