Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help  Adding Solvers to Obi Updaters at Runtime
#1
Hey there!

I have enemies (ships on the ocean) that spawn in dynamically and I'd like to add their various cloth solvers (there are about 6 solvers per enemy) to an Obi Updater component in the scene (fixed update). And I'm also concerned about frame rate stuttering when enemies load in and out of the scene (since we are also planning to use dynamic loading in the scene to save on memory and compute as the player explores an open-world map).

How would I go about getting the solvers to dynamically add themselves and remove themselves from this master obi fixed update component at runtime?

(Amazing asset by the way. I have 66 cloth solvers simulating cloth physics on some single-sided low poly sails on ships, and I'm using the proxy feature to get two-sided cloth working with proper lighting on each side) running in realtime at the moment, and it takes about 2ms of the frame.)
Reply
#2
(16-09-2023, 07:19 PM)scionious Wrote: Hey there!

I have enemies (ships on the ocean) that spawn in dynamically and I'd like to add their various cloth solvers (there are about 6 solvers per enemy) to an Obi Updater component in the scene (fixed update). And I'm also concerned about frame rate stuttering when enemies load in and out of the scene (since we are also planning to use dynamic loading in the scene to save on memory and compute as the player explores an open-world map).

How would I go about getting the solvers to dynamically add themselves and remove themselves from this master obi fixed update component at runtime?

(Amazing asset by the way. I have 66 cloth solvers simulating cloth physics on some single-sided low poly sails on ships, and I'm using the proxy feature to get two-sided cloth working with proper lighting on each side) running in realtime at the moment, and it takes about 2ms of the frame.)

Figured it out:

obiMasterFixedUpdater.GetComponent<ObiUpdater>().solvers.Add(solver);

Remove the same way with .Remove(solver)

Probably should do this in a new thread, but what's the process for doing this with WindZones? Is there a measurable performance cost with just instancing a new one for each enemy instance? I'd like to add them the same way, but I think it's an Array instead of a List and I'm not sure I have enough brain cells to figure that one out.
Reply
#3
(17-09-2023, 05:39 AM)scionious Wrote: Figured it out:

obiMasterFixedUpdater.GetComponent<ObiUpdater>().solvers.Add(solver);

Remove the same way with .Remove(solver)

Probably should do this in a new thread, but what's the process for doing this with WindZones? Is there a measurable performance cost with just instancing a new one for each enemy instance? I'd like to add them the same way, but I think it's an Array instead of a List and I'm not sure I have enough brain cells to figure that one out.



Code:
///WINDZONES
        //Copy current weather system state to a temp list
        tempSolverList.Clear();
        foreach (ObiSolver solver in obiMasterWindZone.affectedSolvers)
        {
            tempSolverList.Add(solver);
        }

        //Add new solvers to list for inheriting wind
        foreach (ObiSolver solver in obiSolversToInheritWind)
        {
            tempSolverList.Add(solver);
        }

        //Write all solvers to array
        obiMasterWindZone.affectedSolvers = tempSolverList.ToArray();

And figured out the Force Zones. This is a pretty ok way to do this?

Also, why am I getting huge 20ms spikes in LateFixedUpdate from Obi when I'm only using FixedUpdate as far as I know? 
Is this a side-effect of using a bunch of Proxies?

I have around 70 solvers in the scene, with a Single ObiFixedUpdater component and and an AmbientForceZone component.
I'm using proxies on those 70 solvers  - is this why?

Any other way I can get double sided cloth in URP with proper lighting?
Reply
#4
(17-09-2023, 07:17 AM)scionious Wrote:
Code:
        ///WINDZONES
        //Copy current weather system state to a temp list
        tempSolverList.Clear();
        foreach (ObiSolver solver in obiMasterWindZone.affectedSolvers)
        {
            tempSolverList.Add(solver);
        }

        //Add new solvers to list for inheriting wind
        foreach (ObiSolver solver in obiSolversToInheritWind)
        {
            tempSolverList.Add(solver);
        }

        //Write all solvers to array
        obiMasterWindZone.affectedSolvers = tempSolverList.ToArray();

And figured out the Force Zones. This is a pretty ok way to do this?

Also, why am I getting huge 20ms spikes in LateFixedUpdate from Obi when I'm only using FixedUpdate as far as I know? 
Is this a side-effect of using a bunch of Proxies?

I have around 70 solvers in the scene, with a Single ObiFixedUpdater component and and an AmbientForceZone component.
I'm using proxies on those 70 solvers  - is this why?

Any other way I can get double sided cloth in URP with proper lighting?

Hi!

While this will work, it is an extremely inefficient way of doing it since you're copying all items twice (one when adding them to a temp list, then another when converting to an array), and the first time you do it one by one which will cause a lot of list reallocations - lists work by scrapping their entire contents and moving them to a new internal array of twice its original length every time they reach max capacity.

Regular C# arrays have a Resize() function you can call to set a new size for the array, which only reallocates once.


(17-09-2023, 07:17 AM)scionious Wrote: Any other way I can get double sided cloth in URP with proper lighting?

You can just use 2 materials per mesh (one front-facing and one back-facing, this works in all render pipelines and is what all included sample scenes do) or just use a single, two-sided material. In URP this is very easy to do as the Lit shader has a two-sided version, just set "Render Face" to "Both":

This has close to zero cost.

(17-09-2023, 07:17 AM)scionious Wrote: Also, why am I getting huge 20ms spikes in LateFixedUpdate from Obi when I'm only using FixedUpdate as far as I know?
Is this a side-effect of using a bunch of Proxies?

I have around 70 solvers in the scene, with a Single ObiFixedUpdater component and and an AmbientForceZone component.
I'm using proxies on those 70 solvers  - is this why?

No, proxies are updated in Update. LateFixedUpdate is only used when using ObiLateFixedUpdater component.

Anyway, if you're using proxies to get double-sided cloth, using double-sided materials (see above) is much simpler and a whole lot faster.

let me know if I can be of further help,

kind regards
Reply
#5
Noted on all the other comments - thanks for the detailed response! I'll dig more into them.


Quote:You can just use 2 materials per mesh (one front-facing and one back-facing, this works in all render pipelines and is what all included sample scenes do) or just use a single, two-sided material. In URP this is very easy to do as the Lit shader has a two-sided version, just set "Render Face" to "Both"

Regarding the above ^ I believe I tried that as many ways as I could, but each time I would get improper lighting. I have a directional light in the scene, and when using this method in URP, I only get light hitting the cloth when the side with normals facing the lighting. If I throw a second material on the mesh to render the back side, there is no option to flip normals so that lighting on the back side of the face is respected. Essentially, what you get is cloth is lit brightly on both sides when the "front" side is facing the light, and no sides are lit when the "back" side is facing the light. All solutions I've tried to find online that allegedly have this normal-flipping feature to get proper lighting all end up not working or show up as pink in the scene.

If you have any ideas on fixing this (or if there is an oversight I'm making), I'd love to pick your brain.

Thanks again for the other answers!
Reply
#6
(20-09-2023, 01:12 PM)scionious Wrote: Regarding the above ^ I believe I tried that as many ways as I could, but each time I would get improper lighting. I have a directional light in the scene, and when using this method in URP, I only get light hitting the cloth when the side with normals facing the lighting. If I throw a second material on the mesh to render the back side, there is no option to flip normals so that lighting on the back side of the face is respected. Essentially, what you get is cloth is lit brightly on both sides when the "front" side is facing the light, and no sides are lit when the "back" side is facing the light. All solutions I've tried to find online that allegedly have this normal-flipping feature to get proper lighting all end up not working or show up as pink in the scene.

If you have any ideas on fixing this (or if there is an oversight I'm making), I'd love to pick your brain.

Thanks again for the other answers!

If you want to flip the normals of backfaces, this is trivial to do in ShaderGraph:

[Image: upload_2020-9-11_6-7-35-png.697486]

Btw, the "Is Front Face" node in shadergraph is equivalent to the VFACE semantic in hlsl, so it's also very easy to write this shader if you prefer hand-written shaders.
Reply
#7
I'll take a deeper dive into it - Thanks!
Reply