Hello everyone!
I’m currently exeprimenting the AI planner preview package (v0.2.3) and after multiple tests, I’ve figured out that objects with trait that are instanciated after an agent doesn’t exist for this agent.
So I’ve downloaded the official Unity samples and checked the Vacuum Robot example where the robot cleans dust heaps that appear after the robot to understand how it works.
And I found this code in the VacuumRobot script:
m_Controller.AutoUpdate = true;
if (m_UpdateStateWithWorldQuery && m_Controller.PlanExecutionStatus != PlanExecutionStatus.ExecutingAction)
{
m_Controller.UpdateStateWithWorldQuery();
m_UpdateStateWithWorldQuery = false;
}
The important part is the call to UpdateStateWithWorldQuery method allowing the robot to see all dust heaps that spawned since the last call.
So my question is: why don’t we update the world state each time a job is finished by default?
This call can’t be done when a job is executing, and for me there is no interface yet to know if the current job is finished.
And in my case, checking the PlanExecutionStatus like it’s done for the VacuumRobot is not enough, I get a lot of errors doing that:
InvalidOperationException: The previously scheduled job ClientIdle writes to the NativeArray ClientIdle.m_StateDataContext.EntityCommandBuffer. You must call JobHandle.Complete() on the job ClientIdle, before you can deallocate the NativeArray safely.
Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle.CheckDeallocateAndThrow (Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle handle) (at <3dc54541a2574ac7826a004a212a4332>:0)
Unity.Collections.LowLevel.Unsafe.DisposeSentinel.Dispose (Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle& safety, Unity.Collections.LowLevel.Unsafe.DisposeSentinel& sentinel) (at <3dc54541a2574ac7826a004a212a4332>:0)
Unity.Entities.EntityCommandBuffer.Dispose () (at Library/PackageCache/com.unity.entities@0.9.1-preview.15/Unity.Entities/EntityCommandBuffer.cs:942)
Generated.AI.Planner.StateRepresentation.ClientPlan.StateManager.ClearECBs () (at Packages/generated.ai.planner.staterepresentation/Generated.AI.Planner.StateRepresentation/ClientPlan/PlanStateRepresentation.cs:1081)
Generated.AI.Planner.StateRepresentation.ClientPlan.StateManager.OnUpdate (Unity.Jobs.JobHandle inputDeps) (at Packages/generated.ai.planner.staterepresentation/Generated.AI.Planner.StateRepresentation/ClientPlan/PlanStateRepresentation.cs:1073)
Unity.Entities.JobComponentSystem.Update () (at Library/PackageCache/com.unity.entities@0.9.1-preview.15/Unity.Entities/JobComponentSystem.cs:129)
Unity.Entities.ComponentSystemGroup.UpdateAllSystems () (at Library/PackageCache/com.unity.entities@0.9.1-preview.15/Unity.Entities/ComponentSystemGroup.cs:134)
UnityEngine.Debug:LogException(Exception)
Unity.Debug:LogException(Exception) (at Library/PackageCache/com.unity.entities@0.9.1-preview.15/Unity.Entities/Stubs/Unity/Debug.cs:19)
Unity.Entities.ComponentSystemGroup:UpdateAllSystems() (at Library/PackageCache/com.unity.entities@0.9.1-preview.15/Unity.Entities/ComponentSystemGroup.cs:138)
Unity.Entities.ComponentSystemGroup:OnUpdate() (at Library/PackageCache/com.unity.entities@0.9.1-preview.15/Unity.Entities/ComponentSystemGroup.cs:114)
Unity.Entities.ComponentSystem:Update() (at Library/PackageCache/com.unity.entities@0.9.1-preview.15/Unity.Entities/ComponentSystem.cs:108)
Unity.Entities.DummyDelegateWrapper:TriggerUpdate() (at Library/PackageCache/com.unity.entities@0.9.1-preview.15/Unity.Entities/ScriptBehaviourUpdateOrder.cs:200)
Depending on how many objects are in the scene, querying can be expensive, which is why we try to do it only when necessary. You can manually trigger it via DecisionController.UpdateStateWithWorldQuery().
Which job is preventing this? The planning jobs are forced to complete before any state queries occur.
Have you looked at IsIdle ?
Thank you for your answer!
The IsIdle property seems to be better than the comparison I did before, I will use that now!