Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help  Trying to make obi fluids work with terrain holes
#1
Pregunta 
Hey guys! 
Im working on a construction sim which uses Digger pro for voxel terrain and it uses terrain holes when digging downwards and puts a mesh in the place of the hole. Now the problem is fluids does not seem to recognise that there are holes and flows as if there is no hole. 
I tested this with a plain scene with a new terrain and painted a hole and added an emitter on top, but it thinks there is no hole there.

Am I missing a setting somewhere or is there a workaround for this? Any leads will be appreciated.

Regards,
Abhishek Jathan
Reply
#2
(13-02-2026, 06:50 AM)abhijathandsi Wrote: Hey guys! 
Im working on a construction sim which uses Digger pro for voxel terrain and it uses terrain holes when digging downwards and puts a mesh in the place of the hole. Now the problem is fluids does not seem to recognise that there are holes and flows as if there is no hole. 
I tested this with a plain scene with a new terrain and painted a hole and added an emitter on top, but it thinks there is no hole there.

Am I missing a setting somewhere or is there a workaround for this? Any leads will be appreciated.

Regards,
Abhishek Jathan

Hi Abhishek,

Terrain holes are fully supported, they should work. Could you give a few more details about the problem? Specifically, you mentioned:
Quote:Digger pro for voxel terrain and it uses terrain holes when digging downwards and puts a mesh in the place of the hole.

I assume this digging/hole making is happening at runtime? If so, you'll need to manually update Obi's representation of the terrain (it isn't automatically updated every frame, just once when starting the simulation). This is done by calling:

Code:
((ObiTerrainShapeTracker)yourObiCollider.tracker).UpdateHeightData();

kind regards,
Reply
#3
(13-02-2026, 09:07 AM)josemendez Wrote: Hi Abhishek,

Terrain holes are fully supported, they should work. Could you give a few more details about the problem? Specifically, you mentioned:

I assume this digging/hole making is happening at runtime? If so, you'll need to manually update Obi's representation of the terrain (it isn't automatically updated every frame, just once when starting the simulation). This is done by calling:

Code:
((ObiTerrainShapeTracker)yourObiCollider.tracker).UpdateHeightData();

kind regards,
Yes it does change terrain data in runtime. Just tested again in another empty scene with just a terrain which has a hole and an emitter. It does work!! Doesnt seem to be doing it in this specific scene. I'll dig deeper (pun intended). Probably something to do with digger in that case and not obi. 

I'll test the code you gave me. 

Thank you soo much!
Reply
#4
(13-02-2026, 10:48 AM)abhijathandsi Wrote: Yes it does change terrain data in runtime. Just tested again in another empty scene with just a terrain which has a hole and an emitter. It does work!! Doesnt seem to be doing it in this specific scene. I'll dig deeper (pun intended). Probably something to do with digger in that case and not obi. 

I'll test the code you gave me. 

Thank you soo much!
Hi! 

It works!! But it keeps printing an error


Code:
System.IndexOutOfRangeException: Index 0 is out of range of '0' Length.
This Exception was thrown from a job compiled with Burst, which has limited exception support.
#3 Unity.Collections.NativeArray`1[[Obi.HeightFieldHeader, Obi, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]], UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null.FailOutOfRangeError(Unity.Collections.NativeArray`1[[Obi.HeightFieldHeader, Obi, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]*, UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null this, System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 index) -> System.Void, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089_aaaff58bdce476e006d3a95c8933df9f from UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
#4 Unity.Jobs.IJobParallelForExtensions.ParallelForJobStruct`1<Obi.GenerateHeightFieldContactsJob>.Execute(ref Obi.GenerateHeightFieldContactsJob jobData, System.IntPtr additionalPtr, System.IntPtr bufferRangePatchData, ref Unity.Jobs.LowLevel.Unsafe.JobRanges ranges, int jobIndex) -> void_aaaff58bdce476e006d3a95c8933df9f from UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
#5 8279d51aeb8336770a48b54e635052ee
#6 ExecuteJob(ManagedJobData*, void (*)(void*, void*, void*, void*, int), int, unsigned char*)
#7 ExecuteJobCopyData(ManagedJobData*, void (*)(void*, void*, void*, void*, int), int)
#8 ujob_execute_job(ujob_control_t*, ujob_lane_t*, ujob_job_t*, ujob_handle_t, unsigned int)
#9 lane_guts(ujob_control_t*, ujob_lane_t*, int, int, ujob_dependency_chain const*)
#10 worker_thread_routine(void*)
#11 Thread::RunThreadWrapper(void*)
#12 _pthread_start
#13 thread_start

So essentially what I'm doing is there is a callback in the digger package on dig task completion (it also uses burst jobs and awaitables) and in that callback im calling the UpdateHeightData method from the terrainshapetracker using an event subscription

Code:
        /// <summary>
        /// Callback to dig operation
        /// </summary>
        public void UpdateDiggingStatus(ModificationResult result)
        {
            if (result.RemovedMatterQuantity <= 0)
                return;

            if (DigCallContexts.Count == 0)
                return; // safety

            DigCallContext ctx = DigCallContexts.Dequeue();

            OnDigSuccess?.Invoke(
                ctx.position,
                (float)result.RemovedMatterQuantity
            );
            digInFlight = false;
            //numberOfTimesDug++;
        }
        public void UpdateTerrainTracker(Vector3 position, float quantity)
        {
            ObiCollider terrainObiCollider = terrainCollider.GetComponent<ObiCollider>();
            if (terrainObiCollider != null)
            {
                ((ObiTerrainShapeTracker)terrainObiCollider.Tracker).UpdateHeightData();
            }
        }

Im subscribing to OnDigSuccess in the start method so that UpdateTerrainTracker gets called. 

Another issue is that unity crashes when using compute mode in the emitter with this runtime fix, could be related to something else and not obi but thats just something that is happening to me.

(14-02-2026, 06:50 AM)abhijathandsi Wrote: Hi! 

It works!! But it keeps printing an error


Code:
System.IndexOutOfRangeException: Index 0 is out of range of '0' Length.
This Exception was thrown from a job compiled with Burst, which has limited exception support.
#3 Unity.Collections.NativeArray`1[[Obi.HeightFieldHeader, Obi, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]], UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null.FailOutOfRangeError(Unity.Collections.NativeArray`1[[Obi.HeightFieldHeader, Obi, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]*, UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null this, System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 index) -> System.Void, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089_aaaff58bdce476e006d3a95c8933df9f from UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
#4 Unity.Jobs.IJobParallelForExtensions.ParallelForJobStruct`1<Obi.GenerateHeightFieldContactsJob>.Execute(ref Obi.GenerateHeightFieldContactsJob jobData, System.IntPtr additionalPtr, System.IntPtr bufferRangePatchData, ref Unity.Jobs.LowLevel.Unsafe.JobRanges ranges, int jobIndex) -> void_aaaff58bdce476e006d3a95c8933df9f from UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
#5 8279d51aeb8336770a48b54e635052ee
#6 ExecuteJob(ManagedJobData*, void (*)(void*, void*, void*, void*, int), int, unsigned char*)
#7 ExecuteJobCopyData(ManagedJobData*, void (*)(void*, void*, void*, void*, int), int)
#8 ujob_execute_job(ujob_control_t*, ujob_lane_t*, ujob_job_t*, ujob_handle_t, unsigned int)
#9 lane_guts(ujob_control_t*, ujob_lane_t*, int, int, ujob_dependency_chain const*)
#10 worker_thread_routine(void*)
#11 Thread::RunThreadWrapper(void*)
#12 _pthread_start
#13 thread_start

So essentially what I'm doing is there is a callback in the digger package on dig task completion (it also uses burst jobs and awaitables) and in that callback im calling the UpdateHeightData method from the terrainshapetracker using an event subscription

Code:
        /// <summary>
        /// Callback to dig operation
        /// </summary>
        public void UpdateDiggingStatus(ModificationResult result)
        {
            if (result.RemovedMatterQuantity <= 0)
                return;

            if (DigCallContexts.Count == 0)
                return; // safety

            DigCallContext ctx = DigCallContexts.Dequeue();

            OnDigSuccess?.Invoke(
                ctx.position,
                (float)result.RemovedMatterQuantity
            );
            digInFlight = false;
            //numberOfTimesDug++;
        }
        public void UpdateTerrainTracker(Vector3 position, float quantity)
        {
            ObiCollider terrainObiCollider = terrainCollider.GetComponent<ObiCollider>();
            if (terrainObiCollider != null)
            {
                ((ObiTerrainShapeTracker)terrainObiCollider.Tracker).UpdateHeightData();
            }
        }

Im subscribing to OnDigSuccess in the start method so that UpdateTerrainTracker gets called. 

Another issue is that unity crashes when using compute mode in the emitter with this runtime fix, could be related to something else and not obi but thats just something that is happening to me.
This is the error I get when I try to use compute, it glitches out a bit and stops emitting and unity crashes. Also I'm on macos if that helps with this.


Code:
ArgumentNullException: Value cannot be null.
Parameter name: buffer
UnityEngine.Bindings.ThrowHelper.ThrowArgumentNullException (System.Object obj, System.String parameterName) (at /Users/bokken/build/output/unity/unity/Runtime/Export/Scripting/BindingsHelpers.cs:54)
UnityEngine.ComputeShader.Internal_SetGraphicsBuffer (System.Int32 kernelIndex, System.Int32 nameID, UnityEngine.GraphicsBuffer buffer) (at <a36420b0e6c0403a903d04f85f5fc533>:0)
UnityEngine.ComputeShader.SetBuffer (System.Int32 kernelIndex, System.Int32 nameID, UnityEngine.GraphicsBuffer buffer) (at /Users/bokken/build/output/unity/unity/Runtime/Export/Shaders/ComputeShader.bindings.cs:71)
UnityEngine.ComputeShader.SetBuffer (System.Int32 kernelIndex, System.String name, UnityEngine.GraphicsBuffer buffer) (at /Users/bokken/build/output/unity/unity/Runtime/Export/Shaders/ComputeShader.cs:64)
Obi.ComputeTriangleMesh.GenerateContacts (Obi.ComputeSolverImpl solver, Obi.ComputeColliderWorld world, System.Single deltaTime) (at Assets/Obi/Scripts/Common/Backends/Compute/Collisions/ComputeTriangleMesh.cs:44)
Obi.ComputeColliderWorld.GenerateContacts (Obi.ComputeSolverImpl solver, System.Single deltaTime) (at Assets/Obi/Scripts/Common/Backends/Compute/Collisions/ComputeColliderWorld.cs:470)
Obi.ComputeSolverImpl.CollisionDetection (Obi.IObiJobHandle inputDeps, System.Single stepTime) (at Assets/Obi/Scripts/Common/Backends/Compute/Solver/ComputeSolverImpl.cs:953)
Obi.ObiSolver.StartSimulation (System.Single stepDelta, System.Int32 simulationSteps) (at Assets/Obi/Scripts/Common/Solver/ObiSolver.cs:1768)
Obi.ObiSolver.LateUpdate () (at Assets/Obi/Scripts/Common/Solver/ObiSolver.cs:1226)

Edit: Tested fluids with the runtime fix on macos build, does not work. So far it only works on editor. I used CPU mode in the build.
Reply
#5
Hey @[b][b]josemendez [/b][/b]!

I think the issue in my case is that im updating the terrain as well as any other objects that are of the layer "Ground" in runtime and its happening before the next simulation cycle or in between making the heightfield null or inaccurate. The error seems to be pointing at heightFieldHeaders in the 
GenerateHeightFieldContactsJob. I tested with keeping the synchronisation to synchronous, that didnt do anything to the errors I was getting either. 

To reiterate, the simulation and the collision is accurate in cpu compute mode but does not work in build.
In gpu compute mode it doesnt work in the editor nor in build.

Any leads on how this can be fixed would be great! 
Reply
#6
(20-02-2026, 01:55 PM)abhijathandsi Wrote: Hey @[font=Tahoma, Verdana, Arial, sans-serif][b][b]josemendez [/b][/b]!

I think the issue in my case is that im updating the terrain as well as any other objects that are of the layer "Ground" in runtime and its happening before the next simulation cycle or in between making the heightfield null or inaccurate.

UpdateHeightData() must not be called while the simulation is running. Obi is a multithreaded engine and simulation data is *not* double buffered, so if you modify it while the engine is running you risk undefined behavior.

Call it during solver.OnSimulationStart. See: https://obi.virtualmethodstudio.com/manu...olver.html
Reply