Skip to content

Commit f317cc3

Browse files
author
Unity Technologies
committed
com.unity.netcode@0.5.0-preview.5
## [0.5.0] - 2020-10-01 ### New features * Added RpcSystem.DynamicAssemblyList which can be used to delay the checksums for RPCs and ghost components when the set of assemblies are different on the client and server. * Added to RPC and Command the possiblity to send Entity reference from both client and server. ### Changes * Change the system ordering to be compatible with latest physics. `NetworkTimeSystem` has moved to `ClientInitializationSystemGroup`. The SimulationSystemGroup runs `GhostSpawnSystemGroup` (client), `GhostReceiveSystemGroup` and `GhostSimulationSystemGroup` before `FixedStepSimulationSystemGroup` where physics is running. `RpcCommandRequestSystemGroup`, `RpcSystem` and `GhostSendSystem` (server) is running at the end of the frame, after all simulation code. Other systems has been moved into one of the groups. * Created a new `GhostInputSystemGroup` where systems adding inputs to the input buffer should run. ### Fixes ### Upgrade guide * The systems adding input to the `ICommandData` buffer needs to be moved to `GhostInputSystemGroup` ## [0.4.0] - 2020-09-10 ### New features * Code gen support for ICommandData, serialization for command data can now be generated instead of hand-written. You can opt out of code generation by adding `[NetCodeDisableCommandCodeGen]`. * `NetCodeConversionSettings` has a new Client And Server mode, which makes it possible to build a single standalong build supporting both client and server. * There is a new static method to generate predicted spawn version of a prefab, `GhostCollectionSystem.CreatePredictedSpawnPrefab`. ### Changes * When not using code-gen for rpcs or commands the systems for registering them (the ones extending `RpcCommandRequestSystem<TActionSerializer, TActionRequest>`, `CommandSendSystem<TCommandDataSerializer, TCommandData>` and `CommandReceiveSystem<TCommandDataSerializer, TCommandData>`) need some more code to setup the jobs. * The `ICommandData` interface no longer takes an additional generic type. * Added a `CommandSendSystemGroup` and a `CommandReceiveSystemGroup` which can be used for dependencies when generating code for `ICommandData`. * Moved the GameObjects used for authoring to a separate assembly. * Fixed tickrate on the client is no longer supported. This also means that the render interpolation has been removed. * Using multiple rendering clients in the editor is no longer supported, thin clients are still supported. * The `GhostPrefabCollectionComponent` now only contains a single prefab list, and the `GhostPrefabBuffer` for it is attached to the same entity. ### Deprecated * Deprecated `ConvertToClientServerEntity`, please use the sub-scene conversion workflow instead. ### Fixes * Fixed a compile error in the generated code for components containing multiple ghosted Entity references. * Fixed a bug where predicted spawn ghosts were not destroyed on mis-prediction. * Fixed a bug where data for child entities on predicted ghosts could be corrupted. ### Upgrade guide * The predicted spawn code must switch to using the new `GhostCollectionSystem.CreatePredictedSpawnPrefab` utility method since there is only a single prefab on the client and it requires some patching before it can be used. * When using the `GhostPrefabCollectionComponent` to find a prefab to find a ghost prefab on the server you must change the code to read the `GhostPrefabBuffer` from the same entity as `GhostPrefabCollectionComponent`. * If you are using fixed tickrate mode on the client you need to remove the creation of the `FixedClientTickRate` singleton and remove the `CurrentSimulatedPosition` and `CurrentSimulatedRotation` if using them. * If you are using "Num Clients" in the PlayMode tools you need to move to using "Num Thin Clients" instead. * RPCs not using code-gen needs to add more code to the `RpcCommandRequestSystem`. The new implementation should look like this: ```c# class MyRequestRpcCommandRequestSystem : RpcCommandRequestSystem<MyRequestSerializer, MyRequest> { [BurstCompile] protected struct SendRpc : IJobEntityBatch { public SendRpcData data; public void Execute(ArchetypeChunk chunk, int orderIndex) { data.Execute(chunk, orderIndex); } } protected override void OnUpdate() { var sendJob = new SendRpc{data = InitJobData()}; ScheduleJobData(sendJob); } } ``` * The `Tick` property in `ICommandData` now requires both a getter and a setter. * ICommandData structs no longer need serialization or implementaions of `CommandSendSystem` and `CommandReceiveSystem` if you are using code-gen, and the interface changed from `ICommandData<T>` to `ICommandData`. * When manually writing serialization code for `ICommandData` you need to move the serialization code to a struct implementing `ICommandDataSerialize<T>`, and the `CommandSendSystem` and `CommandReceiveSystem` implementations need code to schedule the jobs like this: ```c# public class MyCommandSendCommandSystem : CommandSendSystem<MyCommandSerializer, MyCommand> { [BurstCompile] struct SendJob : IJobEntityBatch { public SendJobData data; public void Execute(ArchetypeChunk chunk, int orderIndex) { data.Execute(chunk, orderIndex); } } protected override void OnUpdate() { var sendJob = new SendJob{data = InitJobData()}; ScheduleJobData(sendJob); } } public class MyCommandReceiveCommandSystem : CommandReceiveSystem<MyCommandSerializer, MyCommand> { [BurstCompile] struct ReceiveJob : IJobEntityBatch { public ReceiveJobData data; public void Execute(ArchetypeChunk chunk, int orderIndex) { data.Execute(chunk, orderIndex); } } protected override void OnUpdate() { var recvJob = new ReceiveJob{data = InitJobData()}; ScheduleJobData(recvJob); } } ```
1 parent 8c45138 commit f317cc3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+863
-525
lines changed

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
# Change log
22

3+
## [0.5.0] - 2020-10-01
4+
### New features
5+
* Added RpcSystem.DynamicAssemblyList which can be used to delay the checksums for RPCs and ghost components when the set of assemblies are different on the client and server.
6+
* Added to RPC and Command the possiblity to send Entity reference from both client and server.
7+
8+
### Changes
9+
* Change the system ordering to be compatible with latest physics. `NetworkTimeSystem` has moved to `ClientInitializationSystemGroup`. The SimulationSystemGroup runs `GhostSpawnSystemGroup` (client), `GhostReceiveSystemGroup` and `GhostSimulationSystemGroup` before `FixedStepSimulationSystemGroup` where physics is running. `RpcCommandRequestSystemGroup`, `RpcSystem` and `GhostSendSystem` (server) is running at the end of the frame, after all simulation code. Other systems has been moved into one of the groups.
10+
* Created a new `GhostInputSystemGroup` where systems adding inputs to the input buffer should run.
11+
12+
### Fixes
13+
### Upgrade guide
14+
* The systems adding input to the `ICommandData` buffer needs to be moved to `GhostInputSystemGroup`
15+
316
## [0.4.0] - 2020-09-10
417
### New features
518
* Code gen support for ICommandData, serialization for command data can now be generated instead of hand-written. You can opt out of code generation by adding `[NetCodeDisableCommandCodeGen]`.

Editor/CodeGenTemplates/DefaultTypes/GhostSnapshotValueEntity.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,38 @@ public void Deserialize(uint tick, ref GhostSnapshotData baseline, ref DataStrea
7777
}
7878
#endregion
7979
}
80+
81+
public void SerializeCommand(ref DataStreamWriter writer, in IComponentData data, in RpcSerializerState state, NetworkCompressionModel compressionModel)
82+
{
83+
#region __COMMAND_WRITE__
84+
if (state.GhostFromEntity.HasComponent(data.__COMMAND_FIELD_NAME__))
85+
{
86+
var ghostComponent = state.GhostFromEntity[data.__COMMAND_FIELD_NAME__];
87+
writer.WriteInt(ghostComponent.ghostId);
88+
writer.WriteUInt(ghostComponent.spawnTick);
89+
}
90+
else
91+
{
92+
writer.WriteInt(0);
93+
writer.WriteUInt(0);
94+
}
95+
#endregion
96+
}
97+
98+
public void DeserializeCommand(ref DataStreamReader reader, ref IComponentData data, in RpcDeserializerState state, NetworkCompressionModel compressionModel)
99+
{
100+
#region __COMMAND_READ__
101+
var ghostId = reader.ReadInt();
102+
var spawnTick = reader.ReadUInt();
103+
data.__COMMAND_FIELD_NAME__ = Entity.Null;
104+
if (ghostId != 0)
105+
{
106+
if (state.ghostMap.TryGetValue(new SpawnedGhost{ghostId = ghostId, spawnTick = spawnTick}, out var ghostEnt))
107+
data.__COMMAND_FIELD_NAME__ = ghostEnt;
108+
}
109+
#endregion
110+
}
111+
80112
public void CalculateChangeMask(ref Snapshot snapshot, ref Snapshot baseline, uint changeMask)
81113
{
82114
#region __GHOST_CALCULATE_CHANGE_MASK_ZERO__

Editor/CodeGenTemplates/GhostComponentSerializer.cs

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -16,39 +16,47 @@ namespace __GHOST_NAMESPACE__
1616
[BurstCompile]
1717
public struct __GHOST_NAME__GhostComponentSerializer
1818
{
19-
static __GHOST_NAME__GhostComponentSerializer()
19+
static GhostComponentSerializer.State GetState()
2020
{
21-
State = new GhostComponentSerializer.State
21+
// This needs to be lazy initialized because otherwise there is a depenency on the static initialization order which breaks il2cpp builds due to TYpeManager not being initialized yet
22+
if (!s_StateInitialized)
2223
{
23-
GhostFieldsHash = __GHOST_FIELD_HASH__,
24-
ExcludeFromComponentCollectionHash = __GHOST_COMPONENT_EXCLUDE_FROM_COLLECTION_HASH__,
25-
ComponentType = ComponentType.ReadWrite<__GHOST_COMPONENT_TYPE__>(),
26-
ComponentSize = UnsafeUtility.SizeOf<__GHOST_COMPONENT_TYPE__>(),
27-
SnapshotSize = UnsafeUtility.SizeOf<Snapshot>(),
28-
ChangeMaskBits = ChangeMaskBits,
29-
SendMask = __GHOST_SEND_MASK__,
30-
SendForChildEntities = __GHOST_SEND_CHILD_ENTITY__,
31-
CopyToSnapshot =
32-
new PortableFunctionPointer<GhostComponentSerializer.CopyToFromSnapshotDelegate>(CopyToSnapshot),
33-
CopyFromSnapshot =
34-
new PortableFunctionPointer<GhostComponentSerializer.CopyToFromSnapshotDelegate>(CopyFromSnapshot),
35-
RestoreFromBackup =
36-
new PortableFunctionPointer<GhostComponentSerializer.RestoreFromBackupDelegate>(RestoreFromBackup),
37-
PredictDelta = new PortableFunctionPointer<GhostComponentSerializer.PredictDeltaDelegate>(PredictDelta),
38-
CalculateChangeMask =
39-
new PortableFunctionPointer<GhostComponentSerializer.CalculateChangeMaskDelegate>(
40-
CalculateChangeMask),
41-
Serialize = new PortableFunctionPointer<GhostComponentSerializer.SerializeDelegate>(Serialize),
42-
Deserialize = new PortableFunctionPointer<GhostComponentSerializer.DeserializeDelegate>(Deserialize),
24+
s_State = new GhostComponentSerializer.State
25+
{
26+
GhostFieldsHash = __GHOST_FIELD_HASH__,
27+
ExcludeFromComponentCollectionHash = __GHOST_COMPONENT_EXCLUDE_FROM_COLLECTION_HASH__,
28+
ComponentType = ComponentType.ReadWrite<__GHOST_COMPONENT_TYPE__>(),
29+
ComponentSize = UnsafeUtility.SizeOf<__GHOST_COMPONENT_TYPE__>(),
30+
SnapshotSize = UnsafeUtility.SizeOf<Snapshot>(),
31+
ChangeMaskBits = ChangeMaskBits,
32+
SendMask = __GHOST_SEND_MASK__,
33+
SendForChildEntities = __GHOST_SEND_CHILD_ENTITY__,
34+
CopyToSnapshot =
35+
new PortableFunctionPointer<GhostComponentSerializer.CopyToFromSnapshotDelegate>(CopyToSnapshot),
36+
CopyFromSnapshot =
37+
new PortableFunctionPointer<GhostComponentSerializer.CopyToFromSnapshotDelegate>(CopyFromSnapshot),
38+
RestoreFromBackup =
39+
new PortableFunctionPointer<GhostComponentSerializer.RestoreFromBackupDelegate>(RestoreFromBackup),
40+
PredictDelta = new PortableFunctionPointer<GhostComponentSerializer.PredictDeltaDelegate>(PredictDelta),
41+
CalculateChangeMask =
42+
new PortableFunctionPointer<GhostComponentSerializer.CalculateChangeMaskDelegate>(
43+
CalculateChangeMask),
44+
Serialize = new PortableFunctionPointer<GhostComponentSerializer.SerializeDelegate>(Serialize),
45+
Deserialize = new PortableFunctionPointer<GhostComponentSerializer.DeserializeDelegate>(Deserialize),
46+
#if UNITY_EDITOR || DEVELOPMENT_BUILD
47+
ReportPredictionErrors = new PortableFunctionPointer<GhostComponentSerializer.ReportPredictionErrorsDelegate>(ReportPredictionErrors),
48+
#endif
49+
};
4350
#if UNITY_EDITOR || DEVELOPMENT_BUILD
44-
ReportPredictionErrors = new PortableFunctionPointer<GhostComponentSerializer.ReportPredictionErrorsDelegate>(ReportPredictionErrors),
51+
s_State.NumPredictionErrorNames = GetPredictionErrorNames(ref s_State.PredictionErrorNames);
4552
#endif
46-
};
47-
#if UNITY_EDITOR || DEVELOPMENT_BUILD
48-
State.NumPredictionErrorNames = GetPredictionErrorNames(ref State.PredictionErrorNames);
49-
#endif
53+
s_StateInitialized = true;
54+
}
55+
return s_State;
5056
}
51-
public static readonly GhostComponentSerializer.State State;
57+
private static bool s_StateInitialized;
58+
private static GhostComponentSerializer.State s_State;
59+
public static GhostComponentSerializer.State State => GetState();
5260
public struct Snapshot
5361
{
5462
#region __GHOST_FIELD__

Editor/CodeGenTemplates/RpcCommandSerializer.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@ namespace __COMMAND_NAMESPACE__
1212
[BurstCompile]
1313
public struct __COMMAND_NAME__Serializer : IComponentData, IRpcCommandSerializer<__COMMAND_COMPONENT_TYPE__>
1414
{
15-
public void Serialize(ref DataStreamWriter writer, in __COMMAND_COMPONENT_TYPE__ data)
15+
public void Serialize(ref DataStreamWriter writer, in RpcSerializerState state, in __COMMAND_COMPONENT_TYPE__ data)
1616
{
1717
#region __COMMAND_WRITE__
1818
#endregion
1919
}
2020

21-
public void Deserialize(ref DataStreamReader reader, ref __COMMAND_COMPONENT_TYPE__ data)
21+
public void Deserialize(ref DataStreamReader reader, in RpcDeserializerState state, ref __COMMAND_COMPONENT_TYPE__ data)
2222
{
2323
#region __COMMAND_READ__
2424
#endregion

Editor/CodeGenerator/CodeGenDefaultTypes.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ private static TypeRegistry.CodeGenType[] GetDefaultTypes()
299299
template = new TypeTemplate
300300
{
301301
TemplatePath = $"{TypeRegistry.k_TemplateRootPath}/GhostSnapshotValueEntity.cs",
302-
SupportCommand = false
302+
SupportCommand = true
303303
}
304304
},
305305
new TypeRegistry.CodeGenType

Editor/GhostCompiler/GhostCompilerService.cs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ internal class GhostCompilerService : ScriptableObject
191191
internal bool ignoreAssemblyCSharpNextCompilation;
192192
private int _templateChangeCount;
193193
internal int _regenerateChangeCount;
194+
internal bool _regenerateAll;
194195

195196

196197
public UnityAssemblyDefinition[] CodegenTemplatesAssemblies => _codegenTemplatesAssemblies;
@@ -230,9 +231,6 @@ public void InitializeOnLoad()
230231
FirstTimeInitialization();
231232
initialized = true;
232233
}
233-
234-
RetrieveTemplatesFoldersAndRegisterWatcher();
235-
LoadCustomGhostSnapshotValueTypes();
236234
}
237235

238236
private void LoadCustomGhostSnapshotValueTypes()
@@ -266,25 +264,27 @@ private void LoadCustomGhostSnapshotValueTypes()
266264
}
267265
}
268266

269-
private void TriggerRegenerateAll()
270-
{
271-
RegenerateAll();
272-
}
273267
private void FirstTimeInitialization()
274268
{
275269
//If autocompilation is set to true, it is necessary to force the project to regenerate any changes and/or generated files the first
276270
//time we open the project, in order to keep up-to-date the temp folder with the current project files
277271
if (_settings.autoRecompile)
278272
{
279-
EditorApplication.delayCall += TriggerRegenerateAll;
273+
GhostCompilerServiceUtils.DebugLog($"Initial load, force recompilation of everything");
274+
_regenerateAll = true;
280275
}
281276
}
282277

283278
internal void DomainReload()
284279
{
285280
GhostCompilerServiceUtils.DebugLog("All assemblies has been loaded. Collecting components...");
286281

287-
if (_settings.autoRecompile)
282+
if (_regenerateAll)
283+
{
284+
_regenerateAll = false;
285+
RegenerateAll();
286+
}
287+
else if (_settings.autoRecompile)
288288
{
289289
RegenerateAllChanges();
290290
}
@@ -374,6 +374,11 @@ private void OnCompilationFinished(object context)
374374

375375
private void OnUpdate()
376376
{
377+
if (_codegenTemplatesAssemblies.Length == 0)
378+
{
379+
RetrieveTemplatesFoldersAndRegisterWatcher();
380+
LoadCustomGhostSnapshotValueTypes();
381+
}
377382
if (foldersToDelete.Count != 0)
378383
{
379384
foreach(var f in foldersToDelete)

Runtime/Authoring/Hybrid/GhostAuthoringComponent.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
namespace Unity.NetCode
99
{
10+
[DisallowMultipleComponent]
1011
public class GhostAuthoringComponent : MonoBehaviour
1112
{
1213
#if UNITY_EDITOR

Runtime/ClientServerWorld/ClientServerBootstrap.cs

Lines changed: 5 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,6 @@ public static World CreateClientWorld(World defaultWorld, string name, World wor
7979
var initializationGroup = world.GetOrCreateSystem<ClientInitializationSystemGroup>();
8080
var simulationGroup = world.GetOrCreateSystem<ClientSimulationSystemGroup>();
8181
var presentationGroup = world.GetOrCreateSystem<ClientPresentationSystemGroup>();
82-
//Disable groups legacy sorting behavior
83-
initializationGroup.UseLegacySortOrder = false;
84-
simulationGroup.UseLegacySortOrder = false;
85-
presentationGroup.UseLegacySortOrder = false;
8682

8783
//Pre-create also all the necessary tick systems in the DefaultWorld
8884
var initializationTickSystem = defaultWorld.GetOrCreateSystem<TickClientInitializationSystem>();
@@ -95,17 +91,6 @@ public static World CreateClientWorld(World defaultWorld, string name, World wor
9591
s_State.ClientPresentationSystems.Count +
9692
s_State.ClientChildSystems.Count + 3);
9793

98-
// By using the two-phase creation, we can't rely anymore on the fact that the World.GetOrCreateSystem always return
99-
// a system whose OnCreate method as been invoked. It depend on the system initialization order.
100-
// This break almost all the systems who were relying on that logic and it might require some new changes
101-
// on the Entities framework or (better) a rethink and decoupling of the systems.
102-
// In general, OnCreate is reliable ONLY for caching other system instances.
103-
// ** After trying different solutions I decided to explicitly add the most critical systems that are required to
104-
// pre-created before the simulation group **
105-
allSystems.Add(typeof(RpcSystem)); //Needed by RpcCommandSystem
106-
//NetworkReceiveSystem must be manually created but is not automatically updated by any group. Instead,
107-
//the ClientSimulationSystem tick it manually before the fixed-update / main update loop
108-
allSystems.Add(typeof(NetworkReceiveSystemGroup));
10994
allSystems.AddRange(s_State.ClientInitializationSystems);
11095
allSystems.AddRange(s_State.ClientSimulationSystems);
11196
allSystems.AddRange(s_State.ClientPresentationSystems);
@@ -122,7 +107,6 @@ public static World CreateClientWorld(World defaultWorld, string name, World wor
122107
initializationGroup.AddSystemToUpdateList(system);
123108
}
124109

125-
simulationGroup.AddSystemToUpdateList(world.GetExistingSystem(typeof(RpcSystem)));
126110
foreach (var systemType in s_State.ClientSimulationSystems)
127111
{
128112
var system = world.GetExistingSystem(systemType);
@@ -140,7 +124,7 @@ public static World CreateClientWorld(World defaultWorld, string name, World wor
140124
group.AddSystemToUpdateList(system);
141125
}
142126
initializationGroup.SortSystems();
143-
simulationGroup.SortSystemsAndNetworkSystemGroup();
127+
simulationGroup.SortSystems();
144128
presentationGroup.SortSystems();
145129

146130
//Bind main world group to tick systems (DefaultWorld tick the client world)
@@ -162,9 +146,6 @@ public static World CreateServerWorld(World defaultWorld, string name, World wor
162146
var world = worldToUse!=null ? worldToUse : new World(name);
163147
var initializationGroup = world.GetOrCreateSystem<ServerInitializationSystemGroup>();
164148
var simulationGroup = world.GetOrCreateSystem<ServerSimulationSystemGroup>();
165-
//Disable groups legacy sorting behavior
166-
initializationGroup.UseLegacySortOrder = false;
167-
simulationGroup.UseLegacySortOrder = false;
168149

169150
//Pre-create also all the necessary tick systems in the DefaultWorld
170151
var initializationTickSystem = defaultWorld.GetOrCreateSystem<TickServerInitializationSystem>();
@@ -176,15 +157,6 @@ public static World CreateServerWorld(World defaultWorld, string name, World wor
176157
s_State.ServerChildSystems.Count + 2);
177158

178159
allSystems.AddRange(s_State.ServerInitializationSystems);
179-
// By using the two-phase creation, we can't rely anymore on the fact that the World.GetOrCreateSystem always return
180-
// a system whose OnCreate method as been invoked. It depend on the system initialization order.
181-
// This break almost all the systems who were relying on that logic and it might require some new changes
182-
// on the Entities framework or (better) a rethink and decoupling of the systems.
183-
// In general, OnCreate is reliable ONLY for caching other system instances.
184-
// ** After trying different solutions I decided to explicitly add the most critical systems that are required to
185-
// pre-created before the simulation group **
186-
allSystems.Add(typeof(RpcSystem));
187-
allSystems.Add(typeof(NetworkReceiveSystemGroup));
188160
allSystems.AddRange(s_State.ServerSimulationSystems);
189161
foreach (var systemParentType in s_State.ServerChildSystems)
190162
{
@@ -199,10 +171,6 @@ public static World CreateServerWorld(World defaultWorld, string name, World wor
199171
initializationGroup.AddSystemToUpdateList(system);
200172
}
201173

202-
simulationGroup.AddSystemToUpdateList(world.GetExistingSystem(typeof(RpcSystem)));
203-
//For the server, the NetworkReceiveSystemGroup is part of the SimulationGroup and it is automatically updated as
204-
//usual.
205-
simulationGroup.AddSystemToUpdateList(world.GetExistingSystem(typeof(NetworkReceiveSystemGroup)));
206174
foreach (var systemType in s_State.ServerSimulationSystems)
207175
{
208176
var system = world.GetExistingSystem(systemType);
@@ -312,10 +280,12 @@ protected internal static void GenerateSystemLists(IReadOnlyList<Type> systems)
312280
{
313281
var targetWorld = GetSystemAttribute<UpdateInWorld>(type);
314282
if ((targetWorld != null && targetWorld.World == UpdateInWorld.TargetWorld.Default) ||
283+
#if !UNITY_DOTSRUNTIME
284+
type == typeof(ConvertToEntitySystem) ||
285+
#endif
315286
type == typeof(InitializationSystemGroup) ||
316287
type == typeof(SimulationSystemGroup) ||
317-
type == typeof(PresentationSystemGroup) ||
318-
type == typeof(ConvertToEntitySystem))
288+
type == typeof(PresentationSystemGroup))
319289
{
320290
DefaultWorldSystems.Add(type);
321291
ExplicitDefaultWorldSystems.Add(type);

0 commit comments

Comments
 (0)