Unity crash when using OverlapSphereCommand

Hi, im using Unity 2022.3.22f1 (LTS) and create a system to find enemies (RTS game), in Update for each unit I call the FindEnemyAsync() method which uses Jobs to execute OverlapSphereCommand, but my code causes Crash unity editor (in build the same, crash build), what am I doing wrong, or what is the problem?

    public void FindEnemyAsync()
    {
        if (!IsSpawned || IsHasEnemy) return;

        var commands = new NativeArray<OverlapSphereCommand>(1, Allocator.TempJob);
        var results = new NativeArray<ColliderHit>(3, Allocator.TempJob);
        queryParameters = new QueryParameters
        {
            layerMask = visionLayerMask,
            hitTriggers = QueryTriggerInteraction.Collide,
        };
        commands[0] = new OverlapSphereCommand(aiPath.position, unitData.Characteristics.ViewRadius, queryParameters);
        OverlapSphereCommand.ScheduleBatch(commands, results, 1, 3).Complete();

        enemy = results.GetEnemy(aiPath.position);

        commands.Dispose();
        results.Dispose();
    }

Native Crash Reporting

=================================================================
Native Crash Reporting

Got a UNKNOWN while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries
used by your application.

=================================================================
Managed Stacktrace:

at <0xffffffff>
at Unity.Jobs.JobHandle:ScheduleBatchedJobsAndComplete <0x000e0>
at Unity.Jobs.JobHandle:Complete <0x000f2>
at UnitObject:FindEnemyAsync <0x0085a>
at TowerUnit:Update <0x0020a>
at System.Object:runtime_invoke_void__this__ <0x00187>

Received signal SIGSEGV
Obtained 30 stack frames
0x00007ff79db5ed8d (Unity) ujob_execute_job
0x00007ff79db60509 (Unity) ujob_wait_for
0x00007ff79db5a7a7 (Unity) CompleteFenceInternal
0x00007ff79d0b542f (Unity) JobHandle_CUSTOM_ScheduleBatchedJobsAndComplete
0x000001c95b71f2a1 (Mono JIT Code) (wrapper managed-to-native) Unity.Jobs.JobHandle:ScheduleBatchedJobsAndComplete (Unity.Jobs.JobHandle&)
0x000001c95b71f113 (Mono JIT Code) Unity.Jobs.JobHandle:Complete ()
0x000001c95e0cd23b (Mono JIT Code) UnitObject:FindEnemyAsync () (at C:/UnityProjects/Server/Assets/Scripts/UnitObject.cs:175)
0x000001c95e0cb97b (Mono JIT Code) TowerUnit:Update () (at C:/UnityProjects/Server/Assets/Scripts/TowerUnit.cs:53)
0x000001c9108adcb8 (Mono JIT Code) (wrapper runtime-invoke) object:runtime_invoke_void__this__ (object,intptr,intptr,intptr)
0x00007ff830524c1e (mono-2.0-bdwgc) mono_jit_runtime_invoke (at C:/build/output/Unity-Technologies/mono/mono/mini/mini-runtime.c:3445)
0x00007ff83045d254 (mono-2.0-bdwgc) do_runtime_invoke (at C:/build/output/Unity-Technologies/mono/mono/metadata/object.c:3068)
0x00007ff83045d3cc (mono-2.0-bdwgc) mono_runtime_invoke (at C:/build/output/Unity-Technologies/mono/mono/metadata/object.c:3115)
0x00007ff79df40c44 (Unity) scripting_method_invoke
0x00007ff79df1e9b4 (Unity) ScriptingInvocation::Invoke
0x00007ff79df061a4 (Unity) MonoBehaviour::CallMethodIfAvailable
0x00007ff79df062ca (Unity) MonoBehaviour::CallUpdateMethod
0x00007ff79d9991db (Unity) BaseBehaviourManager::CommonUpdate
0x00007ff79d9a073a (Unity) BehaviourManager::Update
0x00007ff79dbd590d (Unity) InitPlayerLoopCallbacks'::2’::UpdateScriptRunBehaviourUpdateRegistrator::Forward
0x00007ff79dbb4a3c (Unity) ExecutePlayerLoop
0x00007ff79dbb4bb0 (Unity) ExecutePlayerLoop
0x00007ff79dbbb445 (Unity) PlayerLoop
0x00007ff79eb88955 (Unity) PlayerLoopController::InternalUpdateScene
0x00007ff79eb9581d (Unity) PlayerLoopController::UpdateSceneIfNeededFromMainLoop
0x00007ff79eb93b01 (Unity) Application::TickTimer
0x00007ff79f00e67a (Unity) MainMessageLoop
0x00007ff79f013550 (Unity) WinMain
0x00007ff7a03f594e (Unity) __scrt_common_main_seh
0x00007ff8dba77344 (KERNEL32) BaseThreadInitThunk
0x00007ff8dd5226b1 (ntdll) RtlUserThreadStart

Could be related to this issue (marked as won’t fix due to failure to reproduce)
https://issuetracker.unity3d.com/issues/crash-on-overlapspherecommandjob-when-entering-the-play-mode
If you can create a reliable reproducing (“repro”) project, perhaps file a bug report with it.

2 Likes

When you use jobs, give them time to complete in the background. You call Complete() on the job right away so the main thread has to wait for them (the one) to finish. At the least Complete() should be deferred to LateUpdate or the next frame.

Then you are running a single command with at most three results. The whole point of batching is to run numerous commands in parallel, possibly dozens or hundreds, not just a single one. The effort to set this command up will likely be even higher than any benefit gained from running this jobified command.

Practically speaking you are forfeiting most of the benefits of using jobs in the first place, so you could as well just use the non-batched, non-jobified OverlapSphere.

1 Like

As MYRON answered on the link in Issue Tracker, it was necessary to increase the number of maxHits when forming ScheduleBatch otherwise if the number of collisions is more than the maxHits set in ScheduleBatch - crash occurs. Although I think this behavior is considered a bug, because I specifically specify both the array size and the number of maxHits I want to get, other collisions should be ignored and not cause a crash.

1 Like

I have a hundred units in a level that are searching for a target, would it be beneficial to place these calls through the standard OverlapSphereNonAlloc in Update? Wouldn’t this behavior result in lower fps than using Jobs in the backgroud?

I think their point is that you’re not doing it in the background with your current use of the API. You’re immediately locking up the main thread. So right now you’re not getting any advantage.

1 Like

I tried different variants of my task with Jobs (including the delayed call Complete() in the next frame) and it turns out that the usual OverlapSphereNonAlloc at 300 units on the scene is executed much faster than OverlapSphereCommand (apparently because the planning of the task, is more expensive than the task itself), as a result, on a scene with 300 units with Jobs I have 35 fps, and when using the usual raycast 100 fps.

Indeed, there was a misunderstanding of how OverlapSphereCommand works in Jobs, i.e. it is reasonable to do it for example if a unit has to perform many operations in one frame, not one single raycast. If there are many operations - then you can apply Jobs by scheduling a whole array in OverlapSphereCommand.ScheduleBatch.

1 Like