-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
Copy pathPlayerSpawnerSystem.cs
96 lines (87 loc) · 4.51 KB
/
PlayerSpawnerSystem.cs
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
using Tutorials.Kickball.Execute;
using Tutorials.Kickball.Step1;
using Unity.Burst;
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
namespace Tutorials.Kickball.Step2
{
[UpdateAfter(typeof(ObstacleSpawnerSystem))]
[UpdateBefore(typeof(TransformSystemGroup))]
public partial struct PlayerSpawnerSystem : ISystem
{
[BurstCompile]
public void OnCreate(ref SystemState state)
{
state.RequireForUpdate<PlayerSpawner>();
state.RequireForUpdate<Config>();
}
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
// We only want to spawn players in one frame. Disabling the system stops it from updating again after this one time.
state.Enabled = false;
var config = SystemAPI.GetSingleton<Config>();
#if true
// higher-level API
// This "foreach query" is transformed by source-gen into code resembling the #else below.
// For every entity having a LocalTransform and Obstacle component, a read-only reference to
// the LocalTransform is assigned to 'obstacleTransform'.
foreach (var obstacleTransform in
SystemAPI.Query<RefRO<LocalTransform>>().
WithAll<Obstacle>())
{
// Create a player entity from the prefab.
var player = state.EntityManager.Instantiate(config.PlayerPrefab);
// Set the new player's transform (a position offset from the obstacle).
state.EntityManager.SetComponentData(player, new LocalTransform
{
Position = new float3
{
x = obstacleTransform.ValueRO.Position.x + config.PlayerOffset,
y = 1,
z = obstacleTransform.ValueRO.Position.z + config.PlayerOffset
},
Scale = 1, // If we didn't set Scale and Rotation, they would default to zero (which is bad!)
Rotation = quaternion.identity
});
}
#else
// lower-level API
// Get a query that matches all entities which have both a LocalTransform and Obstacle component.
var query = SystemAPI.QueryBuilder().WithAll<LocalTransform, Obstacle>().Build();
// Type handles are needed to access component data arrays from chunks.
var localTransformTypeHandle = SystemAPI.GetComponentTypeHandle<LocalTransform>(true);
// Perform the query: returns all the chunks with entities matching the query.
var chunks = query.ToArchetypeChunkArray(Allocator.Temp);
foreach (var chunk in chunks)
{
// Use the LocalTransform type handle to get the LocalTransform component data array from the chunk.
// Be clear that this is not a copy! This is the actual component array stored in the chunk, so
// modifying its contents directly modifies the LocalTransform values of the entities.
// Because the array belongs to the chunk, you need not (and should not) dispose it.
var localTransforms = chunk.GetNativeArray(ref localTransformTypeHandle);
// Iterate through every entity in the chunk.
for (int i = 0; i < chunk.Count; i++)
{
// Directly read the component value from the component data array.
var obstacleTransform = localTransforms[i];
// Same player instantiation code as above.
var player = state.EntityManager.Instantiate(config.PlayerPrefab);
state.EntityManager.SetComponentData(player, new LocalTransform
{
Position = new float3
{
x = obstacleTransform.Position.x + config.PlayerOffset,
y = 1,
z = obstacleTransform.Position.z + config.PlayerOffset
},
Scale = 1,
Rotation = quaternion.identity
});
}
}
#endif
}
}
}