main path force floor wip
This commit is contained in:
parent
c59fd63cb5
commit
6a07721867
@ -166,9 +166,15 @@ MonoBehaviour:
|
|||||||
branchFrequency: 0.3
|
branchFrequency: 0.3
|
||||||
branchLengthMin: 2
|
branchLengthMin: 2
|
||||||
branchLengthMax: 4
|
branchLengthMax: 4
|
||||||
useCustomStartEnd: 1
|
startEndPairs:
|
||||||
customStartPoint: {x: 1, y: 1}
|
- start: {fileID: 919478494}
|
||||||
customEndPoint: {x: 13, y: 13}
|
end: {fileID: 350389820}
|
||||||
|
- start: {fileID: 350389820}
|
||||||
|
end: {fileID: 919478494}
|
||||||
|
- start: {fileID: 501085820}
|
||||||
|
end: {fileID: 1753478022}
|
||||||
|
- start: {fileID: 1753478022}
|
||||||
|
end: {fileID: 501085820}
|
||||||
enforceMainPath: 1
|
enforceMainPath: 1
|
||||||
--- !u!4 &202619012
|
--- !u!4 &202619012
|
||||||
Transform:
|
Transform:
|
||||||
@ -195,7 +201,7 @@ GameObject:
|
|||||||
m_Component:
|
m_Component:
|
||||||
- component: {fileID: 350389820}
|
- component: {fileID: 350389820}
|
||||||
m_Layer: 0
|
m_Layer: 0
|
||||||
m_Name: PlayerSpawn (2)
|
m_Name: top right
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
m_Icon: {fileID: 0}
|
m_Icon: {fileID: 0}
|
||||||
m_NavMeshLayer: 0
|
m_NavMeshLayer: 0
|
||||||
@ -209,7 +215,7 @@ Transform:
|
|||||||
m_PrefabAsset: {fileID: 0}
|
m_PrefabAsset: {fileID: 0}
|
||||||
m_GameObject: {fileID: 350389819}
|
m_GameObject: {fileID: 350389819}
|
||||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
m_LocalPosition: {x: 54, y: 0, z: 54}
|
m_LocalPosition: {x: 13, y: 0, z: 13}
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
m_ConstrainProportionsScale: 0
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children: []
|
m_Children: []
|
||||||
@ -226,7 +232,7 @@ GameObject:
|
|||||||
m_Component:
|
m_Component:
|
||||||
- component: {fileID: 501085820}
|
- component: {fileID: 501085820}
|
||||||
m_Layer: 0
|
m_Layer: 0
|
||||||
m_Name: PlayerSpawn (1)
|
m_Name: top left
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
m_Icon: {fileID: 0}
|
m_Icon: {fileID: 0}
|
||||||
m_NavMeshLayer: 0
|
m_NavMeshLayer: 0
|
||||||
@ -240,7 +246,7 @@ Transform:
|
|||||||
m_PrefabAsset: {fileID: 0}
|
m_PrefabAsset: {fileID: 0}
|
||||||
m_GameObject: {fileID: 501085819}
|
m_GameObject: {fileID: 501085819}
|
||||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
m_LocalPosition: {x: 2, y: 0, z: 54}
|
m_LocalPosition: {x: 1, y: 0, z: 13}
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
m_ConstrainProportionsScale: 0
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children: []
|
m_Children: []
|
||||||
@ -421,7 +427,7 @@ GameObject:
|
|||||||
m_Component:
|
m_Component:
|
||||||
- component: {fileID: 919478494}
|
- component: {fileID: 919478494}
|
||||||
m_Layer: 0
|
m_Layer: 0
|
||||||
m_Name: PlayerSpawn
|
m_Name: bot left
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
m_Icon: {fileID: 0}
|
m_Icon: {fileID: 0}
|
||||||
m_NavMeshLayer: 0
|
m_NavMeshLayer: 0
|
||||||
@ -435,7 +441,7 @@ Transform:
|
|||||||
m_PrefabAsset: {fileID: 0}
|
m_PrefabAsset: {fileID: 0}
|
||||||
m_GameObject: {fileID: 919478493}
|
m_GameObject: {fileID: 919478493}
|
||||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
m_LocalPosition: {x: 2, y: 0, z: 2}
|
m_LocalPosition: {x: 1, y: 0, z: 1}
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
m_ConstrainProportionsScale: 0
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children: []
|
m_Children: []
|
||||||
@ -786,7 +792,7 @@ GameObject:
|
|||||||
m_Component:
|
m_Component:
|
||||||
- component: {fileID: 1753478022}
|
- component: {fileID: 1753478022}
|
||||||
m_Layer: 0
|
m_Layer: 0
|
||||||
m_Name: PlayerSpawn (3)
|
m_Name: bot right
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
m_Icon: {fileID: 0}
|
m_Icon: {fileID: 0}
|
||||||
m_NavMeshLayer: 0
|
m_NavMeshLayer: 0
|
||||||
@ -800,7 +806,7 @@ Transform:
|
|||||||
m_PrefabAsset: {fileID: 0}
|
m_PrefabAsset: {fileID: 0}
|
||||||
m_GameObject: {fileID: 1753478021}
|
m_GameObject: {fileID: 1753478021}
|
||||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
m_LocalPosition: {x: 54, y: 0, z: 2}
|
m_LocalPosition: {x: 13, y: 0, z: 1}
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
m_ConstrainProportionsScale: 0
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children: []
|
m_Children: []
|
||||||
@ -843,31 +849,31 @@ MonoBehaviour:
|
|||||||
- {fileID: 7255329216686614878, guid: 7dbefec577d5e284fbddd5a29842cc2c, type: 3}
|
- {fileID: 7255329216686614878, guid: 7dbefec577d5e284fbddd5a29842cc2c, type: 3}
|
||||||
- {fileID: 2704001218989138493, guid: 2c83cfd89cb8a284caca24f2ca9d0ba3, type: 3}
|
- {fileID: 2704001218989138493, guid: 2c83cfd89cb8a284caca24f2ca9d0ba3, type: 3}
|
||||||
- {fileID: 2704001218989138493, guid: bd98fb12d63b7bc49ae0f03c2245b435, type: 3}
|
- {fileID: 2704001218989138493, guid: bd98fb12d63b7bc49ae0f03c2245b435, type: 3}
|
||||||
- {fileID: 2704001218989138493, guid: 6a774c110d5aeb1408324d380adb8955, type: 3}
|
|
||||||
- {fileID: 2704001218989138493, guid: 3162a96ef13239b41ba3d21ca801cdc4, type: 3}
|
|
||||||
- {fileID: 2704001218989138493, guid: d9e49365637f4444a99840103c5d5a44, type: 3}
|
- {fileID: 2704001218989138493, guid: d9e49365637f4444a99840103c5d5a44, type: 3}
|
||||||
- {fileID: 2704001218989138493, guid: 80ed2fe86d7677d498f807270b37b1f7, type: 3}
|
- {fileID: 2704001218989138493, guid: 80ed2fe86d7677d498f807270b37b1f7, type: 3}
|
||||||
- {fileID: 2704001218989138493, guid: d32ae7acb5c9b0f489ce40dc2e15c772, type: 3}
|
- {fileID: 2704001218989138493, guid: 6a774c110d5aeb1408324d380adb8955, type: 3}
|
||||||
- {fileID: 7919088255103129344, guid: cc3828d7e55dcf04b85290093563dff2, type: 3}
|
- {fileID: 2704001218989138493, guid: 3162a96ef13239b41ba3d21ca801cdc4, type: 3}
|
||||||
- {fileID: 7919088255103129344, guid: 2b7862a7ca7290d4c922cecdd20528bb, type: 3}
|
|
||||||
- {fileID: 7919088255103129344, guid: 31934c838854a3c4baa7ad791fd520d3, type: 3}
|
|
||||||
- {fileID: 7919088255103129344, guid: 1e236b387bdb75c4ab929f783d7e3f24, type: 3}
|
|
||||||
- {fileID: 7919088255103129344, guid: 2653cb9ee3eaab74ca647ba7532e1608, type: 3}
|
|
||||||
- {fileID: 7919088255103129344, guid: 31dfb5210a9d64b41bb417620dd68533, type: 3}
|
|
||||||
- {fileID: 7919088255103129344, guid: 2bbd6e86a833c8a4e9ee47a195ec46c1, type: 3}
|
|
||||||
- {fileID: 7919088255103129344, guid: e2e591d216fb2734aba113997efa3797, type: 3}
|
|
||||||
- {fileID: 7919088255103129344, guid: 1ff71b2adbd7a854cb82ddfd95f25afb, type: 3}
|
|
||||||
- {fileID: 2704001218989138493, guid: 10dc33d8ada12f84ebd7234446f34c45, type: 3}
|
|
||||||
- {fileID: 7255329216686614878, guid: a809dc39cad8b27429e59a86867fd6d6, type: 3}
|
- {fileID: 7255329216686614878, guid: a809dc39cad8b27429e59a86867fd6d6, type: 3}
|
||||||
- {fileID: 7919088255103129344, guid: 503e9bc31e02ce046bda52996a26fe22, type: 3}
|
|
||||||
- {fileID: 7919088255103129344, guid: a057db1023afbb44993f4161fe103b41, type: 3}
|
|
||||||
- {fileID: 7919088255103129344, guid: 963551cb04192a84088ddaaa3500f559, type: 3}
|
|
||||||
- {fileID: 7919088255103129344, guid: 09343d8e8bc60e445bae34f6881ffe59, type: 3}
|
|
||||||
- {fileID: 7919088255103129344, guid: 9a95e856383ff334b8850ad578cb6d65, type: 3}
|
|
||||||
- {fileID: 7919088255103129344, guid: 55a0e845f95f1974f880c446a4af8303, type: 3}
|
|
||||||
- {fileID: 2704001218989138493, guid: 989f0d6e8bde6834ebbd740844aeba0e, type: 3}
|
|
||||||
- {fileID: 7919088255103129344, guid: a00c0b36ee4586144a9ec800f0d38830, type: 3}
|
- {fileID: 7919088255103129344, guid: a00c0b36ee4586144a9ec800f0d38830, type: 3}
|
||||||
|
- {fileID: 2704001218989138493, guid: 989f0d6e8bde6834ebbd740844aeba0e, type: 3}
|
||||||
|
- {fileID: 7919088255103129344, guid: 55a0e845f95f1974f880c446a4af8303, type: 3}
|
||||||
|
- {fileID: 7919088255103129344, guid: 9a95e856383ff334b8850ad578cb6d65, type: 3}
|
||||||
|
- {fileID: 7919088255103129344, guid: 09343d8e8bc60e445bae34f6881ffe59, type: 3}
|
||||||
|
- {fileID: 7919088255103129344, guid: 963551cb04192a84088ddaaa3500f559, type: 3}
|
||||||
|
- {fileID: 7919088255103129344, guid: a057db1023afbb44993f4161fe103b41, type: 3}
|
||||||
|
- {fileID: 7919088255103129344, guid: 503e9bc31e02ce046bda52996a26fe22, type: 3}
|
||||||
|
- {fileID: 2704001218989138493, guid: 10dc33d8ada12f84ebd7234446f34c45, type: 3}
|
||||||
|
- {fileID: 7919088255103129344, guid: 2653cb9ee3eaab74ca647ba7532e1608, type: 3}
|
||||||
|
- {fileID: 7919088255103129344, guid: e2e591d216fb2734aba113997efa3797, type: 3}
|
||||||
|
- {fileID: 7919088255103129344, guid: 2bbd6e86a833c8a4e9ee47a195ec46c1, type: 3}
|
||||||
|
- {fileID: 7919088255103129344, guid: 31dfb5210a9d64b41bb417620dd68533, type: 3}
|
||||||
- {fileID: 2704001218989138493, guid: 2fce0180ccd18534faacb5e22db086b9, type: 3}
|
- {fileID: 2704001218989138493, guid: 2fce0180ccd18534faacb5e22db086b9, type: 3}
|
||||||
|
- {fileID: 7919088255103129344, guid: 1e236b387bdb75c4ab929f783d7e3f24, type: 3}
|
||||||
|
- {fileID: 7919088255103129344, guid: 31934c838854a3c4baa7ad791fd520d3, type: 3}
|
||||||
|
- {fileID: 7919088255103129344, guid: 2b7862a7ca7290d4c922cecdd20528bb, type: 3}
|
||||||
|
- {fileID: 7919088255103129344, guid: cc3828d7e55dcf04b85290093563dff2, type: 3}
|
||||||
|
- {fileID: 2704001218989138493, guid: d32ae7acb5c9b0f489ce40dc2e15c772, type: 3}
|
||||||
|
- {fileID: 7919088255103129344, guid: 1ff71b2adbd7a854cb82ddfd95f25afb, type: 3}
|
||||||
- {fileID: 7919088255103129344, guid: f818560f421c6f348b9d516c62c52d09, type: 3}
|
- {fileID: 7919088255103129344, guid: f818560f421c6f348b9d516c62c52d09, type: 3}
|
||||||
--- !u!4 &2078654584
|
--- !u!4 &2078654584
|
||||||
Transform:
|
Transform:
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
[System.Serializable]
|
||||||
|
public class TupleTransform
|
||||||
|
{
|
||||||
|
public Transform start;
|
||||||
|
public Transform end;
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: fb1682e3348aa144885053fa0b89077e
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -30,11 +30,9 @@ public class WFCGenerator : MonoBehaviour
|
|||||||
[SerializeField] private float branchFrequency = 0.3f;
|
[SerializeField] private float branchFrequency = 0.3f;
|
||||||
[SerializeField] private int branchLengthMin = 2;
|
[SerializeField] private int branchLengthMin = 2;
|
||||||
[SerializeField] private int branchLengthMax = 4;
|
[SerializeField] private int branchLengthMax = 4;
|
||||||
[Space]
|
|
||||||
[SerializeField] private bool useCustomStartEnd = false;
|
|
||||||
[SerializeField] private Vector2Int customStartPoint = new Vector2Int(1, 1);
|
|
||||||
[SerializeField] private Vector2Int customEndPoint = new Vector2Int(13, 13);
|
|
||||||
|
|
||||||
|
[Space]
|
||||||
|
[SerializeField] private List<TupleTransform> startEndPairs = new List<TupleTransform>();
|
||||||
// Possible spawn points and exit points
|
// Possible spawn points and exit points
|
||||||
private Vector2Int startPoint;
|
private Vector2Int startPoint;
|
||||||
private Vector2Int endPoint;
|
private Vector2Int endPoint;
|
||||||
@ -47,182 +45,172 @@ public class WFCGenerator : MonoBehaviour
|
|||||||
private List<Vector2Int> mainPath = new List<Vector2Int>();
|
private List<Vector2Int> mainPath = new List<Vector2Int>();
|
||||||
private HashSet<Vector2Int> guaranteedConnections = new HashSet<Vector2Int>();
|
private HashSet<Vector2Int> guaranteedConnections = new HashSet<Vector2Int>();
|
||||||
|
|
||||||
|
bool mainPathReady = false;
|
||||||
|
bool gridReady = false;
|
||||||
|
|
||||||
private void Start()
|
private void Start()
|
||||||
{
|
{
|
||||||
chunkCompatibilityMatrix.BuildCompatibilityMatrix();
|
chunkCompatibilityMatrix.BuildCompatibilityMatrix();
|
||||||
|
|
||||||
if (randomizeSeed)
|
if (randomizeSeed)
|
||||||
seed = UnityEngine.Random.Range(0, 1000000);
|
seed = UnityEngine.Random.Range(0, 1000000);
|
||||||
|
|
||||||
UnityEngine.Random.InitState(seed);
|
UnityEngine.Random.InitState(seed);
|
||||||
|
|
||||||
if (enforceMainPath)
|
// Generate path first
|
||||||
{
|
GenerateMainPath();
|
||||||
GenerateMainPath();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Then initialize grid with path consideration
|
||||||
|
//InitializeGrid();
|
||||||
|
|
||||||
InitializeGrid(chunkCompatibilityMatrix.prefabs);
|
// Finally start the WFC process
|
||||||
GenerateMap();
|
//await WaitSignal();
|
||||||
|
|
||||||
|
//StartCoroutine(RunWFC());
|
||||||
}
|
}
|
||||||
|
private async Task WaitSignal()
|
||||||
private void GenerateMainPath()
|
|
||||||
{
|
{
|
||||||
DetermineStartAndEndPoints();
|
while (!(mainPathReady && gridReady))
|
||||||
|
{
|
||||||
|
await Task.Delay(delayAwait);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private async void GenerateMainPath()
|
||||||
|
{
|
||||||
|
int startEndIndex = UnityEngine.Random.Range(0, startEndPairs.Count);
|
||||||
|
startPoint = new Vector2Int((int)startEndPairs[startEndIndex].start.position.x, (int)startEndPairs[startEndIndex].start.position.z);
|
||||||
|
endPoint = new Vector2Int((int)startEndPairs[startEndIndex].end.position.x, (int)startEndPairs[startEndIndex].end.position.z);
|
||||||
|
|
||||||
// Start from bottom-left
|
|
||||||
Vector2Int current = startPoint;
|
Vector2Int current = startPoint;
|
||||||
mainPath.Add(current);
|
mainPath.Add(current);
|
||||||
guaranteedConnections.Add(current);
|
|
||||||
guaranteedConnections.Add(endPoint);
|
|
||||||
|
|
||||||
while (current != endPoint)
|
while (current != endPoint)
|
||||||
{
|
{
|
||||||
Vector2Int next = GetNextPathPoint(current, endPoint);
|
Vector2Int next = GetNextPathPoint(current);
|
||||||
|
|
||||||
if (!IsOutOfBounds(next) && !mainPath.Contains(next))
|
if (!IsOutOfBounds(next) && !mainPath.Contains(next))
|
||||||
{
|
{
|
||||||
current = next;
|
current = next;
|
||||||
mainPath.Add(current);
|
mainPath.Add(current);
|
||||||
guaranteedConnections.Add(current);
|
|
||||||
|
|
||||||
// Add some branching paths
|
if (UnityEngine.Random.value < 0.3f)
|
||||||
if (UnityEngine.Random.value < branchFrequency)
|
|
||||||
{
|
{
|
||||||
AddBranchPath(current);
|
AddBranchPath(current);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
await Task.Delay(delayAwait);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mainPathReady = true;
|
||||||
|
|
||||||
|
InitializeGrid();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Vector2Int GetNextPathPoint(Vector2Int current)
|
||||||
|
{
|
||||||
|
Vector2Int direction = endPoint - current;
|
||||||
|
List<Vector2Int> possibleMoves = new List<Vector2Int>();
|
||||||
|
|
||||||
|
// Always consider all four primary directions
|
||||||
|
var primaryDirections = new List<Vector2Int>
|
||||||
|
{
|
||||||
|
Vector2Int.up,
|
||||||
|
Vector2Int.right,
|
||||||
|
Vector2Int.down,
|
||||||
|
Vector2Int.left
|
||||||
|
};
|
||||||
|
|
||||||
|
// Sort directions by their effectiveness in reaching the target
|
||||||
|
primaryDirections.Sort((a, b) =>
|
||||||
|
{
|
||||||
|
float scoreA = Vector2Int.Distance(current + a, endPoint);
|
||||||
|
float scoreB = Vector2Int.Distance(current + b, endPoint);
|
||||||
|
return scoreA.CompareTo(scoreB);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add sorted directions to possible moves if they're valid
|
||||||
|
foreach (var dir in primaryDirections)
|
||||||
|
{
|
||||||
|
Vector2Int nextPos = current + dir;
|
||||||
|
if (IsValidPathPosition(nextPos))
|
||||||
|
{
|
||||||
|
possibleMoves.Add(nextPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no primary moves are available, try diagonal moves
|
||||||
|
if (possibleMoves.Count == 0)
|
||||||
|
{
|
||||||
|
var diagonalDirections = new List<Vector2Int>
|
||||||
|
{
|
||||||
|
new Vector2Int(1, 1),
|
||||||
|
new Vector2Int(1, -1),
|
||||||
|
new Vector2Int(-1, 1),
|
||||||
|
new Vector2Int(-1, -1)
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var dir in diagonalDirections)
|
||||||
|
{
|
||||||
|
Vector2Int nextPos = current + dir;
|
||||||
|
if (IsValidPathPosition(nextPos))
|
||||||
|
{
|
||||||
|
possibleMoves.Add(nextPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have valid moves, prefer the one that gets us closest to the target
|
||||||
|
if (possibleMoves.Count > 0)
|
||||||
|
{
|
||||||
|
// Sort by distance to target and add some randomness
|
||||||
|
possibleMoves.Sort((a, b) =>
|
||||||
|
{
|
||||||
|
float scoreA = Vector2Int.Distance(a, endPoint) + UnityEngine.Random.Range(0f, 0.5f);
|
||||||
|
float scoreB = Vector2Int.Distance(b, endPoint) + UnityEngine.Random.Range(0f, 0.5f);
|
||||||
|
return scoreA.CompareTo(scoreB);
|
||||||
|
});
|
||||||
|
|
||||||
|
return possibleMoves[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return current; // Only return current position if absolutely no moves are available
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsValidPathPosition(Vector2Int pos)
|
||||||
|
{
|
||||||
|
return !IsOutOfBounds(pos) &&
|
||||||
|
!mainPath.Contains(pos) &&
|
||||||
|
pos.x > 0 && pos.x < gridWidth - 1 &&
|
||||||
|
pos.y > 0 && pos.y < gridHeight - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddBranchPath(Vector2Int start)
|
private void AddBranchPath(Vector2Int start)
|
||||||
{
|
{
|
||||||
Vector2Int current = start;
|
Vector2Int current = start;
|
||||||
int branchLength = UnityEngine.Random.Range(branchLengthMin, branchLengthMax);
|
int maxLength = 3;
|
||||||
|
|
||||||
for (int i = 0; i < branchLength; i++)
|
for (int i = 0; i < maxLength; i++)
|
||||||
{
|
{
|
||||||
Vector2Int next;
|
Vector2Int direction = UnityEngine.Random.value < 0.5f ?
|
||||||
if (UnityEngine.Random.value < 0.5f)
|
new Vector2Int(UnityEngine.Random.value < 0.5f ? 1 : -1, 0) :
|
||||||
next = current + Vector2Int.right * (UnityEngine.Random.value < 0.5f ? 1 : -1);
|
new Vector2Int(0, 1);
|
||||||
else
|
|
||||||
next = current + Vector2Int.up;
|
|
||||||
|
|
||||||
if (!IsOutOfBounds(next) && !mainPath.Contains(next) &&
|
Vector2Int next = current + direction;
|
||||||
|
|
||||||
|
if (!IsOutOfBounds(next) &&
|
||||||
|
!mainPath.Contains(next) &&
|
||||||
next.x > 0 && next.x < gridWidth - 1 &&
|
next.x > 0 && next.x < gridWidth - 1 &&
|
||||||
next.y > 0 && next.y < gridHeight - 1)
|
next.y > 0 && next.y < gridHeight - 1)
|
||||||
{
|
{
|
||||||
current = next;
|
current = next;
|
||||||
guaranteedConnections.Add(current);
|
mainPath.Add(current);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
|
||||||
private void DetermineStartAndEndPoints()
|
|
||||||
{
|
|
||||||
if (useCustomStartEnd)
|
|
||||||
{
|
|
||||||
startPoint = customStartPoint;
|
|
||||||
endPoint = customEndPoint;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Generate multiple possible spawn points in the bottom third
|
|
||||||
for (int x = 1; x < gridWidth - 1; x++)
|
|
||||||
{
|
|
||||||
for (int y = 1; y < gridHeight / 3; y++)
|
|
||||||
{
|
|
||||||
possibleSpawnPoints.Add(new Vector2Int(x, y));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate multiple possible exit points in the top third
|
|
||||||
for (int x = 1; x < gridWidth - 1; x++)
|
|
||||||
{
|
|
||||||
for (int y = (gridHeight * 2) / 3; y < gridHeight - 1; y++)
|
|
||||||
{
|
|
||||||
possibleExitPoints.Add(new Vector2Int(x, y));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pick random points from the possible locations
|
|
||||||
startPoint = possibleSpawnPoints[UnityEngine.Random.Range(0, possibleSpawnPoints.Count)];
|
|
||||||
endPoint = possibleExitPoints[UnityEngine.Random.Range(0, possibleExitPoints.Count)];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool IsBorderPosition(Vector2Int pos)
|
|
||||||
{
|
|
||||||
return pos.x == 0 || pos.x == gridWidth - 1 ||
|
|
||||||
pos.y == 0 || pos.y == gridHeight - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Vector2Int GetNextPathPoint(Vector2Int current, Vector2Int target)
|
|
||||||
{
|
|
||||||
// Calculate direction to target
|
|
||||||
Vector2Int direction = target - current;
|
|
||||||
float distance = direction.magnitude;
|
|
||||||
|
|
||||||
// List of possible next points
|
|
||||||
List<Vector2Int> possibleMoves = new List<Vector2Int>();
|
|
||||||
|
|
||||||
// Always try to move closer to the target when possible
|
|
||||||
if (Mathf.Abs(direction.x) > Mathf.Abs(direction.y))
|
|
||||||
{
|
|
||||||
// Prioritize horizontal movement
|
|
||||||
if (direction.x > 0)
|
|
||||||
possibleMoves.Add(current + Vector2Int.right);
|
|
||||||
else
|
|
||||||
possibleMoves.Add(current + Vector2Int.left);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Prioritize vertical movement
|
|
||||||
if (direction.y > 0)
|
|
||||||
possibleMoves.Add(current + Vector2Int.up);
|
|
||||||
else
|
|
||||||
possibleMoves.Add(current + Vector2Int.down);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add some randomness to prevent straight lines
|
|
||||||
if (UnityEngine.Random.value < 0.4f)
|
|
||||||
{
|
|
||||||
if (current.x > 1)
|
|
||||||
possibleMoves.Add(current + Vector2Int.left);
|
|
||||||
if (current.x < gridWidth - 2)
|
|
||||||
possibleMoves.Add(current + Vector2Int.right);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter out invalid moves
|
|
||||||
possibleMoves.RemoveAll(move =>
|
|
||||||
IsOutOfBounds(move) ||
|
|
||||||
mainPath.Contains(move) ||
|
|
||||||
IsBorderPosition(move)
|
|
||||||
);
|
|
||||||
|
|
||||||
// If no valid moves, try moving directly towards target
|
|
||||||
if (possibleMoves.Count == 0)
|
|
||||||
{
|
|
||||||
Vector2Int directMove = current + new Vector2Int(
|
|
||||||
Mathf.Clamp(direction.x, -1, 1),
|
|
||||||
Mathf.Clamp(direction.y, -1, 1)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!IsOutOfBounds(directMove) &&
|
|
||||||
!mainPath.Contains(directMove) &&
|
|
||||||
!IsBorderPosition(directMove))
|
|
||||||
{
|
|
||||||
return directMove;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return random valid move, or current position if no valid moves
|
|
||||||
return possibleMoves.Count > 0 ?
|
|
||||||
possibleMoves[UnityEngine.Random.Range(0, possibleMoves.Count)] :
|
|
||||||
current;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Add this to help with spawning
|
// Add this to help with spawning
|
||||||
public Vector2Int GetRandomSpawnPoint()
|
public Vector2Int GetRandomSpawnPoint()
|
||||||
{
|
{
|
||||||
@ -278,26 +266,66 @@ public class WFCGenerator : MonoBehaviour
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitializeGrid(List<GameObject> allPrefabs)
|
private async void InitializeGrid()
|
||||||
{
|
{
|
||||||
grid = new WaveCell[gridWidth, gridHeight];
|
grid = new WaveCell[gridWidth, gridHeight];
|
||||||
|
var allPrefabs = chunkCompatibilityMatrix.prefabs;
|
||||||
|
|
||||||
|
// First pass: Initialize all cells
|
||||||
for (int x = 0; x < gridWidth; x++)
|
for (int x = 0; x < gridWidth; x++)
|
||||||
{
|
{
|
||||||
for (int y = 0; y < gridHeight; y++)
|
for (int y = 0; y < gridHeight; y++)
|
||||||
{
|
{
|
||||||
// Start with all prefabs as possibilities
|
Vector2Int pos = new Vector2Int(x, y);
|
||||||
List<GameObject> possiblePrefabs = new List<GameObject>(allPrefabs);
|
|
||||||
|
|
||||||
// If using closed borders, restrict edge cells to prefabs with closed sockets
|
if (mainPath.Contains(pos))
|
||||||
if (closedBorders)
|
|
||||||
{
|
{
|
||||||
possiblePrefabs = FilterPrefabsForBorders(x, y, possiblePrefabs);
|
// Filter for floor-based prefabs
|
||||||
|
var pathPrefabs = allPrefabs.Where(prefab =>
|
||||||
|
{
|
||||||
|
var conn = prefab.GetComponent<ChunkConnectionData>();
|
||||||
|
return !conn.IsBorderPrefab() && HasFloorConnection(conn);
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
|
grid[x, y] = new WaveCell(pathPrefabs, pos);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
List<GameObject> possiblePrefabs = new List<GameObject>(allPrefabs);
|
||||||
|
if (closedBorders)
|
||||||
|
{
|
||||||
|
possiblePrefabs = FilterPrefabsForBorders(x, y, possiblePrefabs);
|
||||||
|
}
|
||||||
|
grid[x, y] = new WaveCell(possiblePrefabs, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start with all prefabs as possibilities
|
await Task.Delay(delayAwait);
|
||||||
grid[x, y] = new WaveCell(new List<GameObject>(possiblePrefabs), new Vector2Int(x, y));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Second pass: Collapse path cells
|
||||||
|
foreach (var pathPos in mainPath)
|
||||||
|
{
|
||||||
|
var cell = grid[pathPos.x, pathPos.y];
|
||||||
|
cell.IsCollapsed = true;
|
||||||
|
cell.PossiblePrefabs = new List<GameObject> {
|
||||||
|
GetWeightedRandomPrefab(cell.PossiblePrefabs)
|
||||||
|
};
|
||||||
|
InstantiateCollapsedCell(cell);
|
||||||
|
await Task.Delay(delayAwait);
|
||||||
|
}
|
||||||
|
|
||||||
|
gridReady = true;
|
||||||
|
|
||||||
|
StartCoroutine(RunWFC());
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool HasFloorConnection(ChunkConnectionData conn)
|
||||||
|
{
|
||||||
|
return conn.NorthConnection == ConnectionSocket.floor &&
|
||||||
|
conn.SouthConnection == ConnectionSocket.floor &&
|
||||||
|
conn.EastConnection == ConnectionSocket.floor &&
|
||||||
|
conn.WestConnection == ConnectionSocket.floor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* void OnDrawGizmos()
|
/* void OnDrawGizmos()
|
||||||
@ -327,7 +355,7 @@ public class WFCGenerator : MonoBehaviour
|
|||||||
|
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Restrict edge cells to prefabs with walls or closed connections
|
// Restrict edge cells to prefabs with walls or closed connections
|
||||||
List<GameObject> FilterPrefabsForBorders(int x, int y, List<GameObject> possiblePrefabs)
|
List<GameObject> FilterPrefabsForBorders(int x, int y, List<GameObject> possiblePrefabs)
|
||||||
@ -428,35 +456,35 @@ public class WFCGenerator : MonoBehaviour
|
|||||||
PropagateConstraints(cellPos);
|
PropagateConstraints(cellPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* // Find the cell with the smallest number of possible prefabs
|
/* // Find the cell with the smallest number of possible prefabs
|
||||||
Vector2Int FindMinEntropyCell()
|
Vector2Int FindMinEntropyCell()
|
||||||
{
|
{
|
||||||
int minEntropy = int.MaxValue;
|
int minEntropy = int.MaxValue;
|
||||||
List<Vector2Int> candidates = new List<Vector2Int>();
|
List<Vector2Int> candidates = new List<Vector2Int>();
|
||||||
|
|
||||||
for (int x = 0; x < gridWidth; x++)
|
for (int x = 0; x < gridWidth; x++)
|
||||||
{
|
{
|
||||||
for (int y = 0; y < gridHeight; y++)
|
for (int y = 0; y < gridHeight; y++)
|
||||||
{
|
{
|
||||||
WaveCell cell = grid[x, y];
|
WaveCell cell = grid[x, y];
|
||||||
if (cell.IsCollapsed) continue;
|
if (cell.IsCollapsed) continue;
|
||||||
|
|
||||||
if (cell.Entropy < minEntropy)
|
if (cell.Entropy < minEntropy)
|
||||||
{
|
{
|
||||||
minEntropy = cell.Entropy;
|
minEntropy = cell.Entropy;
|
||||||
candidates.Clear();
|
candidates.Clear();
|
||||||
candidates.Add(new Vector2Int(x, y));
|
candidates.Add(new Vector2Int(x, y));
|
||||||
}
|
}
|
||||||
else if (cell.Entropy == minEntropy)
|
else if (cell.Entropy == minEntropy)
|
||||||
{
|
{
|
||||||
candidates.Add(new Vector2Int(x, y));
|
candidates.Add(new Vector2Int(x, y));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pick a random candidate to avoid directional bias
|
// Pick a random candidate to avoid directional bias
|
||||||
return candidates[UnityEngine.Random.Range(0, candidates.Count)];
|
return candidates[UnityEngine.Random.Range(0, candidates.Count)];
|
||||||
}*/
|
}*/
|
||||||
Vector2Int FindMinEntropyCell()
|
Vector2Int FindMinEntropyCell()
|
||||||
{
|
{
|
||||||
int minEntropy = int.MaxValue;
|
int minEntropy = int.MaxValue;
|
||||||
@ -520,31 +548,40 @@ public class WFCGenerator : MonoBehaviour
|
|||||||
|
|
||||||
async void CollapseCell(Vector2Int cellPos)
|
async void CollapseCell(Vector2Int cellPos)
|
||||||
{
|
{
|
||||||
await Task.Delay(delayAwait); // Simulating async work
|
await Task.Delay(delayAwait);
|
||||||
|
|
||||||
WaveCell cell = grid[cellPos.x, cellPos.y];
|
WaveCell cell = grid[cellPos.x, cellPos.y];
|
||||||
if (cell.IsCollapsed || cell.Entropy == 0) return;
|
if (cell.IsCollapsed || cell.Entropy == 0) return;
|
||||||
|
|
||||||
GameObject chosenPrefab = GetWeightedRandomPrefab(cell.PossiblePrefabs);
|
if (mainPath.Contains(cellPos))
|
||||||
//Debug.Log("cell.PossiblePrefabs.count" + cell.PossiblePrefabs.Count);
|
|
||||||
//GameObject chosenPrefab = cell.PossiblePrefabs.Find(p => p.name.Contains("Floor"));
|
|
||||||
|
|
||||||
if (chosenPrefab == null)
|
|
||||||
{
|
{
|
||||||
Debug.LogError("No valid floor prefab found!");
|
cell.PossiblePrefabs = cell.PossiblePrefabs.Where(prefab =>
|
||||||
|
{
|
||||||
|
var conn = prefab.GetComponent<ChunkConnectionData>();
|
||||||
|
return !conn.IsBorderPrefab() &&
|
||||||
|
conn.NorthConnection == ConnectionSocket.floor &&
|
||||||
|
conn.SouthConnection == ConnectionSocket.floor &&
|
||||||
|
conn.EastConnection == ConnectionSocket.floor &&
|
||||||
|
conn.WestConnection == ConnectionSocket.floor;
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
|
if (cell.PossiblePrefabs.Count == 0)
|
||||||
|
{
|
||||||
|
Debug.LogError($"No valid floor prefabs available for path at {cellPos}!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Debug.Log("Collapsed cell: " + cellPos.x + ", " + cellPos.y + " = " + chosenPrefab.name);
|
|
||||||
|
|
||||||
// Collapse the cell to this prefab
|
GameObject chosenPrefab = GetWeightedRandomPrefab(cell.PossiblePrefabs);
|
||||||
|
|
||||||
cell.PossiblePrefabs = new List<GameObject> { chosenPrefab };
|
cell.PossiblePrefabs = new List<GameObject> { chosenPrefab };
|
||||||
cell.IsCollapsed = true;
|
cell.IsCollapsed = true;
|
||||||
|
|
||||||
InstantiateCollapsedCell(cell);
|
InstantiateCollapsedCell(cell);
|
||||||
|
|
||||||
await Task.Delay(delayAwait); // Simulating async work
|
await Task.Delay(delayAwait);
|
||||||
|
|
||||||
// Propagate constraints to neighbors
|
|
||||||
PropagateConstraints(cellPos);
|
PropagateConstraints(cellPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -583,7 +620,7 @@ public class WFCGenerator : MonoBehaviour
|
|||||||
return possiblePrefabs[0];
|
return possiblePrefabs[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
async void PropagateConstraints(Vector2Int startCellPos)
|
async void PropagateConstraints(Vector2Int startCellPos)
|
||||||
{
|
{
|
||||||
Queue<Vector2Int> cellsToProcess = new Queue<Vector2Int>();
|
Queue<Vector2Int> cellsToProcess = new Queue<Vector2Int>();
|
||||||
cellsToProcess.Enqueue(startCellPos);
|
cellsToProcess.Enqueue(startCellPos);
|
||||||
@ -593,6 +630,20 @@ public class WFCGenerator : MonoBehaviour
|
|||||||
Vector2Int cellPos = cellsToProcess.Dequeue();
|
Vector2Int cellPos = cellsToProcess.Dequeue();
|
||||||
WaveCell cell = grid[cellPos.x, cellPos.y];
|
WaveCell cell = grid[cellPos.x, cellPos.y];
|
||||||
|
|
||||||
|
if (mainPath.Contains(cellPos))
|
||||||
|
{
|
||||||
|
// Ensure we maintain floor connections for path tiles
|
||||||
|
cell.PossiblePrefabs = cell.PossiblePrefabs.Where(prefab =>
|
||||||
|
{
|
||||||
|
var conn = prefab.GetComponent<ChunkConnectionData>();
|
||||||
|
return !conn.IsBorderPrefab() &&
|
||||||
|
conn.NorthConnection == ConnectionSocket.floor &&
|
||||||
|
conn.SouthConnection == ConnectionSocket.floor &&
|
||||||
|
conn.EastConnection == ConnectionSocket.floor &&
|
||||||
|
conn.WestConnection == ConnectionSocket.floor;
|
||||||
|
}).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
foreach (Direction dir in Enum.GetValues(typeof(Direction)))
|
foreach (Direction dir in Enum.GetValues(typeof(Direction)))
|
||||||
{
|
{
|
||||||
Vector2Int neighborPos = GetNeighborPosition(cellPos, dir);
|
Vector2Int neighborPos = GetNeighborPosition(cellPos, dir);
|
||||||
@ -608,7 +659,7 @@ public class WFCGenerator : MonoBehaviour
|
|||||||
|
|
||||||
for (int i = 0; i < validPrefabs.Count; i++)
|
for (int i = 0; i < validPrefabs.Count; i++)
|
||||||
{
|
{
|
||||||
Debug.Log("Cell: " + cell.GridPosition + " has possible neighbors " + dir + " = " + validPrefabs[i].name);
|
//Debug.Log("Cell: " + cell.GridPosition + " has possible neighbors " + dir + " = " + validPrefabs[i].name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for contradictions here!
|
// Check for contradictions here!
|
||||||
@ -627,7 +678,7 @@ public class WFCGenerator : MonoBehaviour
|
|||||||
cellsToProcess.Enqueue(neighborPos);
|
cellsToProcess.Enqueue(neighborPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await Task.Delay(delayAwait); // Simulating async work
|
await Task.Delay(delayAwait); // Simulating async work
|
||||||
@ -768,7 +819,7 @@ public class WFCGenerator : MonoBehaviour
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
IEnumerator RunWFC()
|
private IEnumerator RunWFC()
|
||||||
{
|
{
|
||||||
while (!AllCellsCollapsed())
|
while (!AllCellsCollapsed())
|
||||||
{
|
{
|
||||||
@ -776,8 +827,6 @@ public class WFCGenerator : MonoBehaviour
|
|||||||
CollapseCell(cellPos);
|
CollapseCell(cellPos);
|
||||||
yield return new WaitForSeconds(delayCoroutine);
|
yield return new WaitForSeconds(delayCoroutine);
|
||||||
}
|
}
|
||||||
//if (AllCellsCollapsed())
|
|
||||||
// InstantiatePrefabs();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AllCellsCollapsed()
|
bool AllCellsCollapsed()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user