Skip to content

Commit

Permalink
Fix player movement collision detection
Browse files Browse the repository at this point in the history
  • Loading branch information
jeickhoff committed Jun 1, 2023
1 parent ab0914d commit c5f19cf
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 63 deletions.
6 changes: 3 additions & 3 deletions Assets/Scenes/SampleScene/SampleSubScene.unity
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,10 @@ MonoBehaviour:
type: 3}
seed: 43
initialAreas:
x: 1
x: 2
y: 1
z: 1
maxChunkSpawnsPerTick: 10
z: 2
maxChunkSpawnsPerTick: 1
blocksPerChunkSide: 4
YBounds:
x: 0
Expand Down
92 changes: 56 additions & 36 deletions Assets/Scripts/Player/PlayerMovementSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -170,39 +170,43 @@ static bool HasPhysicsWorldBeenInitialized(PhysicsWorldSingleton physicsWorldSin

private PlayerUtilities.PlayerSupportState CheckPlayerSupported(RigidTransform transform)
{
float offset = 0.0f;
// Need to check each corner under player for support
NativeHashSet<int3> set = new NativeHashSet<int3>(4, Allocator.Temp);
set.Add(new int3((int)math.floor(transform.pos.x +offset), (int)math.floor(transform.pos.y),
(int)math.floor(transform.pos.z+offset)));
set.Add(new int3((int)math.ceil(transform.pos.x -offset), (int)math.floor(transform.pos.y),
(int)math.floor(transform.pos.z+offset)));
set.Add(new int3((int)math.floor(transform.pos.x +offset), (int)math.floor(transform.pos.y),
(int)math.ceil(transform.pos.z-offset)));
set.Add(new int3((int)math.ceil(transform.pos.x -offset), (int)math.floor(transform.pos.y),
(int)math.ceil(transform.pos.z-offset)));

// Check corners under player
float offset = 0.5f;
NativeHashSet<float3> set = new NativeHashSet<float3>(4, Allocator.Temp);
set.Add(new float3(
transform.pos.x + offset,
transform.pos.y-1.1f,
transform.pos.z + offset));
set.Add(new float3(
transform.pos.x + offset,
transform.pos.y-1.1f,
transform.pos.z - offset));
set.Add(new float3(
transform.pos.x - offset,
transform.pos.y-1.1f,
transform.pos.z - offset));
set.Add(new float3(
transform.pos.x - offset,
transform.pos.y-1.1f,
transform.pos.z + offset));

foreach (var pos in set)
{
//Debug.DrawLine(transform.pos, new float3(pos), Color.cyan);
//Debug.Log($"Checking pos {pos}");
if (IsBlockAtPosition(pos))
{
Debug.DrawLine(transform.pos, new float3(pos), Color.cyan);
return PlayerUtilities.PlayerSupportState.Supported;
}
}


return PlayerUtilities.PlayerSupportState.Unsupported;
}

private bool IsBlockAtPosition(int3 pos)
private bool IsBlockAtPosition(float3 pos)
{
if (GetTerrainAreaByPosition(pos, out Entity containingArea, out int3 containingAreaLocation))
{
var terrainBuffer = _bufferLookup[containingArea];
int localx = pos.x - containingAreaLocation.x-1;
int localy = pos.y - containingAreaLocation.y-1;
int localz = pos.z - containingAreaLocation.z-1;
int localx = (int)math.floor(pos.x) - containingAreaLocation.x;
int localy = (int)math.floor(pos.y) - containingAreaLocation.y;
int localz = (int)math.floor(pos.z) - containingAreaLocation.z;
//Debug.Log($"Found block at {pos}, corresponding to chunk {containingAreaLocation} with local index {localx}, {localy}, {localz}");
int index = localx + localy * blocksPerChunkSide + localz * blocksPerChunkSide * blocksPerChunkSide;
int4 block = terrainBuffer[index].Value;
if (block.w != -1)
Expand Down Expand Up @@ -231,7 +235,7 @@ private bool IsBlockAtPosition(int3 pos)
return false;
}

private bool GetTerrainAreaByPosition(int3 pos, out Entity containingArea, out int3 containingAreaLocation)
private bool GetTerrainAreaByPosition(float3 pos, out Entity containingArea, out int3 containingAreaLocation)
{
for (int i = 0; i < terrainAreas.Length; i++ )
{
Expand All @@ -246,7 +250,7 @@ private bool GetTerrainAreaByPosition(int3 pos, out Entity containingArea, out i
return true;
}
}
containingArea = new Entity();
containingArea = Entity.Null;
containingAreaLocation = new int3(-1);
return false;
}
Expand All @@ -256,22 +260,38 @@ private void MovePlayerCheckCollisions(PlayerUtilities.PlayerStepInput stepInput
{
float deltaTime = stepInput.DeltaTime;
float3 newPosition = transform.pos + deltaTime * linearVelocity;


float3 newVelocity = linearVelocity;
float3 norm = math.normalize(linearVelocity);

/* Need to check four corners of the mesh for obstacles
NativeHashSet<int3> set = new NativeHashSet<int3>(2, Allocator.Temp);
float offset = 0.5f;
NativeHashSet<float3> set = new NativeHashSet<float3>(4, Allocator.Temp);
set.Add(new float3(
newPosition.x + offset,
newPosition.y-1.0f,
newPosition.z + offset));
set.Add(new float3(
newPosition.x + offset,
newPosition.y-1.0f,
newPosition.z - offset));
set.Add(new float3(
newPosition.x - offset,
newPosition.y-1.0f,
newPosition.z - offset));
set.Add(new float3(
newPosition.x - offset,
newPosition.y-1.0f,
newPosition.z + offset));

set.Add((int3)(transform.pos + norm + new float3(0.5f,0.0f,0.0f)));
foreach (var pos in set)
if (IsBlockAtPosition(pos))
{
linearVelocity = new float3(0,0,0);
return;
}

int3 pos = (int3)(transform.pos + new float3(0.1f,0.1f,0.0f) + norm);
Debug.DrawLine(transform.pos, (float3) pos, Color.magenta);
if (IsBlockAtPosition(pos))
{
//Debug.DrawLine(transform.pos, (float3) pos, Color.magenta);
//transform.pos = newPosition;
//linearVelocity = new float3(0);
}*/

transform.pos = newPosition;
linearVelocity = newVelocity;

Expand Down
62 changes: 43 additions & 19 deletions Assets/Scripts/Terrain/TerrainGenerationSystem.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
using Unity.Entities;
using System.Collections.Generic;
using Unity.Entities;
using Unity.Jobs;
using Unity.Mathematics;
using Unity.NetCode;
using Unity.Transforms;
using Unity.Burst;
using Unity.Collections;
using Unity.Logging.Internal.Debug;
using UnityEngine;

[WorldSystemFilter(WorldSystemFilterFlags.ServerSimulation)]
[UpdateInGroup(typeof(PredictedSimulationSystemGroup))]
Expand Down Expand Up @@ -36,39 +40,60 @@ public void OnUpdate(ref SystemState state)
{
return;
}

NativeArray<int3> chunksToSpawn = chunksToSpawnBuffer.ToNativeArray(Allocator.TempJob);
if (chunksToSpawnBuffer.Length > terrainSpawner.maxChunkSpawnsPerTick)
{
chunksToSpawnBuffer.RemoveRange(0, terrainSpawner.maxChunkSpawnsPerTick);
}
else
{
chunksToSpawnBuffer.Clear();
}

//NativeArray<int3> chunksToSpawn = chunksToSpawnBuffer.ToNativeArray(Allocator.TempJob);
NativeArray<int3> chunksToSpawn = chunksToSpawnBuffer.AsNativeArray();
// Sort the chunks to spawn so ones closer to 0,0 are first
SortJob<int3, Int3Comparer> sortJob = chunksToSpawn.SortJob(new Int3Comparer{});
JobHandle sortHandle = sortJob.Schedule();

// Spawn the terrain area entities
state.EntityManager.Instantiate(terrainSpawner.TerrainArea,
chunksToSpawn.Length > terrainSpawner.maxChunkSpawnsPerTick ? terrainSpawner.maxChunkSpawnsPerTick : chunksToSpawn.Length,
Allocator.Temp);
// Then populate them on worker threads
new PopulateTerrainAreas
JobHandle populateHandle = new PopulateTerrainAreas
{
initialAreas = terrainSpawner.initialAreas,
chunksToSpawn = chunksToSpawn,
//ecb = parallelEcb,
noiseSeed = terrainSpawner.seed,
blocksPerChunkSide = terrainSpawner.blocksPerChunkSide,
YBounds = terrainSpawner.YBounds,
}.ScheduleParallel();
}.ScheduleParallel(sortHandle);
populateHandle.Complete();

// Remove spawned areas from the toSpawn buffer
if (chunksToSpawnBuffer.Length > terrainSpawner.maxChunkSpawnsPerTick)
{
chunksToSpawnBuffer.RemoveRange(0, terrainSpawner.maxChunkSpawnsPerTick);
}
else
{
chunksToSpawnBuffer.Clear();
}
}
}


public struct Int3Comparer : IComparer<int3>
{
public int Compare(int3 a, int3 b)
{
int lSum = math.abs(a.x) + math.abs(a.y) + math.abs(a.z);
int rSum = math.abs(b.x) + math.abs(b.y) + math.abs(b.z);
if (lSum > rSum)
return 1;
if (lSum < rSum)
return -1;
return 0;
}
}

[WithAll(typeof(NewSpawn))]
[BurstCompile]
partial struct PopulateTerrainAreas : IJobEntity
{
[DeallocateOnJobCompletion] public NativeArray<int3> chunksToSpawn;
public NativeArray<int3> chunksToSpawn;

public int3 initialAreas;
public int blocksPerChunkSide;
Expand All @@ -78,11 +103,10 @@ partial struct PopulateTerrainAreas : IJobEntity

public void Execute(Entity entity, [EntityIndexInQuery] int index, ref DynamicBuffer<TerrainBlocks> terrainBlocksBuffer, ref LocalTransform localTransform, ref TerrainArea terrainArea)
{

int3 chunk = chunksToSpawn[index];
int areaX = chunk.x * blocksPerChunkSide - (int)(0.5f*initialAreas.x*blocksPerChunkSide);
int areaY = chunk.y * blocksPerChunkSide - (int)(0.5f*initialAreas.y*blocksPerChunkSide);
int areaZ = chunk.z * blocksPerChunkSide - (int)(0.5f*initialAreas.z*blocksPerChunkSide);
int areaX = chunk.x * blocksPerChunkSide;// - (int)(0.5f*initialAreas.x*blocksPerChunkSide);
int areaY = chunk.y * blocksPerChunkSide;// - (int)(0.5f*initialAreas.y*blocksPerChunkSide);
int areaZ = chunk.z * blocksPerChunkSide;// - (int)(0.5f*initialAreas.z*blocksPerChunkSide);
// Physically place the area even though its invisible, useful for checking where to bother rendering
localTransform.Position = new float3(areaX, areaY, areaZ);
terrainArea.location = new int3(areaX, areaY, areaZ);
Expand Down
10 changes: 5 additions & 5 deletions Assets/Scripts/Terrain/TerrainSpawnerAuthoring.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,15 @@ public override void Bake(TerrainSpawnerAuthoring authoring)
component.maxChunkSpawnsPerTick = authoring.maxChunkSpawnsPerTick;
component.seed = authoring.seed;
component.initialAreas = authoring.initialAreas;

// Add to the TerrainSpawner entity a buffer of int3s, fill it with initial values
var toSpawnBuffer = AddBuffer<TerrainAreasToSpawn>(entity);
DynamicBuffer<int3> intBuffer = toSpawnBuffer.Reinterpret<int3>();
for (int x = 0; x < authoring.initialAreas.x; x++)
for (int y = 0; y < authoring.initialAreas.y; y++)
for (int z = 0; z < authoring.initialAreas.z; z++)
for (int x = -(int)math.floor(authoring.initialAreas.x / 2.0f); x < math.ceil(authoring.initialAreas.x / 2.0f); x++)
for (int y = -(int)math.floor(authoring.initialAreas.y / 2.0f); y < math.ceil(authoring.initialAreas.y / 2.0f); y++)
for (int z = -(int)math.floor(authoring.initialAreas.z / 2.0f); z < math.ceil(authoring.initialAreas.z / 2.0f); z++)
intBuffer.Add(new int3(x, y, z));

AddComponent(entity, component);

}
Expand Down

0 comments on commit c5f19cf

Please sign in to comment.