Hi, just upgraded my learning project to 0.17 and have a single breaking change
I am getting this error: InvalidOperationException: The previously scheduled job EnemySystem:OnUpdate_LambdaJob0 reads from the Unity.Collections.NativeHashMap
InvalidOperationException: The previously scheduled job EnemySystem:OnUpdate_LambdaJob0 reads from the Unity.Collections.NativeHashMap2[Unity.Entities.Entity,System.Int32] OnUpdate_LambdaJob0.JobData.raycaster.pw.CollisionWorld.EntityBodyIndexMap. You must call JobHandle.Complete() on the job EnemySystem:OnUpdate_LambdaJob0, before you can write to the Unity.Collections.NativeHashMap
2[Unity.Entities.Entity,System.Int32] safely.
Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle.CheckWriteAndBumpSecondaryVersion (Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle handle) (at :0)
Unity.Collections.NativeHashMap2[TKey,TValue].CheckWrite () (at Library/PackageCache/com.unity.collections@0.15.0-preview.21/Unity.Collections/NativeHashMap.cs:554) Unity.Collections.NativeHashMap
2[TKey,TValue].Clear () (at Library/PackageCache/com.unity.collections@0.15.0-preview.21/Unity.Collections/NativeHashMap.cs:194)
Unity.Physics.CollisionWorld.Reset (System.Int32 numStaticBodies, System.Int32 numDynamicBodies) (at Library/PackageCache/com.unity.physics@0.6.0-preview.3/Unity.Physics/Collision/World/CollisionWorld.cs:53)
Unity.Physics.PhysicsWorld.Reset (System.Int32 numStaticBodies, System.Int32 numDynamicBodies, System.Int32 numJoints) (at Library/PackageCache/com.unity.physics@0.6.0-preview.3/Unity.Physics/Dynamics/World/PhysicsWorld.cs:41)
Unity.Physics.Systems.BuildPhysicsWorld.OnUpdate () (at Library/PackageCache/com.unity.physics@0.6.0-preview.3/Unity.Physics/ECS/Base/Systems/BuildPhysicsWorld.cs:122)
Unity.Entities.SystemBase.Update () (at Library/PackageCache/com.unity.entities@0.17.0-preview.41/Unity.Entities/SystemBase.cs:412)
Unity.Entities.ComponentSystemGroup.UpdateAllSystems () (at Library/PackageCache/com.unity.entities@0.17.0-preview.41/Unity.Entities/ComponentSystemGroup.cs:472)
UnityEngine.Debug:LogException(Exception)
Unity.Debug:LogException(Exception) (at Library/PackageCache/com.unity.entities@0.17.0-preview.41/Unity.Entities/Stubs/Unity/Debug.cs:19)
Unity.Entities.ComponentSystemGroup:UpdateAllSystems() (at Library/PackageCache/com.unity.entities@0.17.0-preview.41/Unity.Entities/ComponentSystemGroup.cs:477)
Unity.Entities.ComponentSystemGroup:OnUpdate() (at Library/PackageCache/com.unity.entities@0.17.0-preview.41/Unity.Entities/ComponentSystemGroup.cs:423)
Unity.Entities.ComponentSystem:Update() (at Library/PackageCache/com.unity.entities@0.17.0-preview.41/Unity.Entities/ComponentSystem.cs:114)
Unity.Entities.ComponentSystemGroup:UpdateAllSystems() (at Library/PackageCache/com.unity.entities@0.17.0-preview.41/Unity.Entities/ComponentSystemGroup.cs:472)
Unity.Entities.ComponentSystemGroup:OnUpdate() (at Library/PackageCache/com.unity.entities@0.17.0-preview.41/Unity.Entities/ComponentSystemGroup.cs:417)
Unity.Entities.ComponentSystem:Update() (at Library/PackageCache/com.unity.entities@0.17.0-preview.41/Unity.Entities/ComponentSystem.cs:114)
Unity.Entities.DummyDelegateWrapper:TriggerUpdate() (at Library/PackageCache/com.unity.entities@0.17.0-preview.41/Unity.Entities/ScriptBehaviourUpdateOrder.cs:333)
I think it makes sense. I think it is complaining that my Job is still running at the time the next frame kicks off another copy of the same job. I am doing a physics raycast in my job like so:
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
using Unity.Physics;
using Unity.Physics.Systems;
[UpdateAfter(typeof(EndFramePhysicsSystem))]
[UpdateInGroup(typeof(FixedStepSimulationSystemGroup))]
public class EnemySystem : SystemBase
{
protected override void OnUpdate()
{
//this code doesn't "work" anymore, it just is the mimum to reproduce the runtime error.
var pw = World.GetOrCreateSystem<BuildPhysicsWorld>().PhysicsWorld;
Entities
.WithReadOnly(pw)
.ForEach((int nativeThreadIndex, ref Movable mov, ref Enemy enemy, in Translation trans) =>
{
var targetDir = new float3(0, 0, -1);
var ray = new RaycastInput()
{
Start = trans.Value,
End = trans.Value + (targetDir * 0.9f),
Filter = new CollisionFilter()
{
GroupIndex = 0,
BelongsTo = 1u << 1, //bitmasks, so using bitshifts
CollidesWith = 1u << 2
}
};
var hit = pw.CastRay(ray, out Unity.Physics.RaycastHit closestHit);
if (hit)
{
mov.direction = targetDir;
}
enemy.lastPos = trans.Value;
}).ScheduleParallel();
}
}
In Entities 0.16 I didn’t get an error on that. In 0.17 I do. I can understand that if that Job takes multiple frames to complete, the raycast is going to be innacurate, plus that there will be multiple runs of this job (1 each frame) stacking on top of eachother.
Then “solution” is simple, add
this.Dependency.Complete();
to the bottom.
My question is: Adding the .Complete() call will stall the frame completion until this Job completes, right? Or does it stall starting of other Jobs that need to be enqueued this frame? If this was “normal” c# then it would be the latter (bad) case. But as this is burst compiled I hope this is smart enough to init other jobs while this is completing.
EDIT: updated code to mimum repro