forked from Unity-Technologies/EntityComponentSystemSamples
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCustomBuildPhysicsWorld.cs
More file actions
128 lines (120 loc) · 7.33 KB
/
Copy pathCustomBuildPhysicsWorld.cs
File metadata and controls
128 lines (120 loc) · 7.33 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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
using Unity.Burst;
using Unity.Entities;
using Unity.Physics;
using Unity.Physics.Systems;
namespace Unity.NetCode
{
/// <summary>
/// A system which builds the physics world based on the entity world. The world will contain a
/// rigid body for every entity which has a rigid body component, and a joint for every entity
/// which has a joint component.
/// </summary>
[WorldSystemFilter(WorldSystemFilterFlags.ClientSimulation)]
[BurstCompile]
[UpdateInGroup(typeof(PhysicsBuildWorldGroup))]
[CreateAfter(typeof(BuildPhysicsWorld))]
public partial struct CustomBuildPhysicsWorld : ISystem
{
private SystemHandle buildPhysicSystemHandle;
private int currentPhysicStep;
[BurstCompile]
public void OnCreate(ref SystemState state)
{
buildPhysicSystemHandle = state.WorldUnmanaged.GetExistingUnmanagedSystem<BuildPhysicsWorld>();
//It is necesary to create temp PhysicsWorldData here for sake of setting up the correct dependencies.
//The PhysicsWorldData itself is then retrieved from the BuildPhysicsWorld all the time.
var physicsData = new PhysicsWorldData(ref state, new PhysicsWorldIndex());
physicsData.Dispose();
state.EntityManager.AddComponentData(state.SystemHandle, new BuildPhysicsWorldSettings());
//The sytem always start disabled and will be enabled/disabled based on the PhysicsCustomLoop component
//settings by the ConfigureBuildPhysicsWorld.
state.Enabled = false;
}
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
//First we need to need to complete any pending dependencies before building or updating the
//physics world. In particular the BuildPhysicsWorldData may have some physics jobs that need to be
//completed but for which the dependency cannot be tracked automatically. They are tracked by the internal
// InputDepdency handled and it is possible to wait for them here using the exposed CompleteInputDependency method.
ref var buildPhysicsData = ref state.EntityManager.GetComponentDataRW<BuildPhysicsWorldData>(buildPhysicSystemHandle).ValueRW;
buildPhysicsData.CompleteInputDependency();
float timeStep = SystemAPI.Time.DeltaTime;
if (!SystemAPI.TryGetSingleton(out PhysicsStep stepComponent))
stepComponent = PhysicsStep.Default;
//The BuildPhysicsWorldSettings govern how the build system construct the physics world. In particular,
//either a full rebuild or an "incremental" one, that just update the current brodphase by enlargin the AABB
//by using the last calculated physics step PhysicsVelocity and gravity.
//Notice that in case of prediction, the PhysicsVelocity may be actually a replicated value from the server
//and not the last predicted value, being used as both input-output.
var settings = state.EntityManager.GetComponentData<BuildPhysicsWorldSettings>(state.SystemHandle);
// In case we just want to update the broadphase and motion data we check if any new
// physics object has been created or destroyed (either, static, dynamic or joint) and we force a full rebuild
// in that case.
if (settings.UpdateBroadphaseAndMotion == 1)
{
var dynamicObject = buildPhysicsData.PhysicsData.DynamicEntityGroup.CalculateEntityCount();
//+1 to account for the default static body object
var staticObject = buildPhysicsData.PhysicsData.StaticEntityGroup.CalculateEntityCount() + 1;
var joints = buildPhysicsData.PhysicsData.JointEntityGroup.CalculateEntityCount();
//If entity count changed we forcibly rebuild (and we log this)
if (buildPhysicsData.PhysicsData.PhysicsWorld.NumDynamicBodies != dynamicObject ||
buildPhysicsData.PhysicsData.PhysicsWorld.NumStaticBodies != staticObject ||
buildPhysicsData.PhysicsData.PhysicsWorld.NumJoints != joints)
{
settings.UpdateBroadphaseAndMotion = 0;
}
}
// The following code either does a full rebuild (BuildPhysicsWorld)
// or does an partial update of the Motion and Broaphase.
// The update of the motions and the broaphase are not executed
// by the same method (i.e ScheduleUpdateBroadphase) because this way there is a little bit more
// flexibility for checking if and what we actually need to update. Technically, only simulated physics entities can have LocalTransform,
// and PhysicsVelocity expoerted, meaning that "kinematic-like" motion data in general does not change, and
// can be potentially not need an update.
//Immediate mode could be a good choice to use when the number of physics entities is small.
//In this sammple, this is executed on the main thread but it is possible to also execute that
//in a job.
if (settings.UseImmediateMode != 0)
{
state.CompleteDependency();
if (settings.UpdateBroadphaseAndMotion == 0)
{
PhysicsWorldBuilder.BuildPhysicsWorldImmediate(ref state, ref buildPhysicsData.PhysicsData,
timeStep, stepComponent.Gravity, state.LastSystemVersion);
}
else
{
buildPhysicsData.PhysicsData.Update(ref state);
PhysicsWorldBuilder.UpdateMotionDataImmediate(ref state, ref buildPhysicsData.PhysicsData);
//This method internally check if necessary to update also the static tree
PhysicsWorldBuilder.UpdateBroadphaseImmediate(ref buildPhysicsData.PhysicsData, timeStep, stepComponent.Gravity,
state.LastSystemVersion);
}
}
else
{
//Full rebuild of the physics world.
if (settings.UpdateBroadphaseAndMotion == 0)
{
state.Dependency = PhysicsWorldBuilder.SchedulePhysicsWorldBuild(ref state, ref buildPhysicsData.PhysicsData,
state.Dependency, timeStep, stepComponent.MultiThreaded > 0, stepComponent.Gravity, state.LastSystemVersion);
}
else
{
buildPhysicsData.PhysicsData.Update(ref state);
state.Dependency = PhysicsWorldBuilder.ScheduleUpdateMotionData(ref state, ref buildPhysicsData.PhysicsData, state.Dependency);
//This method internally check if necessary to update also the static tree
state.Dependency = PhysicsWorldBuilder.ScheduleUpdateBroadphase(
ref buildPhysicsData.PhysicsData, timeStep, stepComponent.Gravity, state.LastSystemVersion,
state.Dependency, stepComponent.MultiThreaded > 0);
}
}
SystemAPI.SetSingleton(new PhysicsWorldSingleton
{
PhysicsWorld = buildPhysicsData.PhysicsData.PhysicsWorld,
PhysicsWorldIndex = buildPhysicsData.WorldFilter
});
}
}
}