forked from Unity-Technologies/EntityComponentSystemSamples
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLoadLevelSystem.cs
More file actions
99 lines (87 loc) · 3.95 KB
/
Copy pathLoadLevelSystem.cs
File metadata and controls
99 lines (87 loc) · 3.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
using Unity.Burst;
using Unity.Entities;
using Unity.Jobs;
using Unity.Collections;
using Unity.NetCode;
using Unity.Mathematics;
namespace Asteroids.Server
{
public struct LevelRequestedTag : IComponentData
{
}
[BurstCompile]
[WorldSystemFilter(WorldSystemFilterFlags.ServerSimulation)]
[UpdateBefore(typeof(RpcSystem))]
public partial struct LoadLevelSystem : ISystem
{
private EntityQuery m_LevelGroup;
private PortableFunctionPointer<GhostImportance.ScaleImportanceDelegate> m_ScaleFunctionPointer;
public void OnCreate(ref SystemState state)
{
var builder = new EntityQueryBuilder(Allocator.Temp).WithAllRW<LevelComponent>();
m_LevelGroup = state.GetEntityQuery(builder);
state.RequireForUpdate<ServerSettings>();
m_ScaleFunctionPointer = GhostDistanceImportance.ScaleFunctionPointer;
}
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
var settings = SystemAPI.GetSingleton<ServerSettings>();
if (!SystemAPI.HasSingleton<GhostImportance>())
{
// Try to store a bit less than full chunks to avoid fragmenting the data too much
var maxAsteroidsPerTile = 25;
var minTileSize = 256;
float asteroidsPerPx = (float)settings.levelData.numAsteroids / (float)(settings.levelData.levelWidth*settings.levelData.levelHeight);
// We want to make sure that asteroidsPerPx * tileSize * tileSize = maxAsteroidsPerTile
int tileSize = math.max(minTileSize, (int)math.ceil(math.sqrt((float)maxAsteroidsPerTile / asteroidsPerPx)));
var gridSingleton = state.EntityManager.CreateSingleton(new GhostDistanceData
{
TileSize = new int3(tileSize, tileSize, 256),
TileCenter = new int3(0, 0, 128),
TileBorderWidth = new float3(1f, 1f, 1f),
});
state.EntityManager.AddComponentData(gridSingleton, new GhostImportance
{
ScaleImportanceFunction = m_ScaleFunctionPointer,
GhostConnectionComponentType = ComponentType.ReadOnly<GhostConnectionPosition>(),
GhostImportanceDataType = ComponentType.ReadOnly<GhostDistanceData>(),
GhostImportancePerChunkDataType = ComponentType.ReadOnly<GhostDistancePartitionShared>(),
});
}
if (m_LevelGroup.IsEmptyIgnoreFilter)
{
var newLevel = state.EntityManager.CreateEntity();
state.EntityManager.AddComponentData(newLevel, settings.levelData);
return;
}
var level = m_LevelGroup.ToComponentDataListAsync<LevelComponent>(state.WorldUpdateAllocator,
out var levelHandle);
var levelJob = new LoadLevelJob
{
ecb = SystemAPI.GetSingleton<EndSimulationEntityCommandBufferSystem.Singleton>()
.CreateCommandBuffer(state.WorldUnmanaged),
level = level,
};
state.Dependency = JobHandle.CombineDependencies(state.Dependency, levelHandle);
levelJob.Schedule();
}
[BurstCompile]
[WithNone(typeof(LevelRequestedTag))]
internal partial struct LoadLevelJob : IJobEntity
{
public EntityCommandBuffer ecb;
[ReadOnly] public NativeList<LevelComponent> level;
public void Execute(Entity entity, in NetworkId networkId)
{
ecb.AddComponent(entity, new LevelRequestedTag());
var req = ecb.CreateEntity();
ecb.AddComponent(req, new LevelLoadRequest
{
levelData = level[0],
});
ecb.AddComponent(req, new SendRpcCommandRequest {TargetConnection = entity});
}
}
}
}