Search Unity

Question Changing Entity's velocity via SetComponent creates instability.

Discussion in 'Physics for ECS' started by l_Lobsternator, Mar 26, 2021.

  1. l_Lobsternator

    l_Lobsternator

    Joined:
    Aug 31, 2019
    Posts:
    12
    Recently I've been experimenting with some Unity DOTS and I've come across a peculiar quirk that I can't really figure out.

    Basically, I'm just changing the velocity of a bunch of entities by setting their PhysicsVelocity component via a commandBuffer in a parallel job. Problem is that this causes their physics to get unstable and can sometimes cause jittering and at other times completely break the simulation.

    As a test, I am applying a straight velocity to all entities in the scene towards the center of the simulation; clustering everything in the middle.

    What I expect to see:


    What I get:


    Here in the editor it only causes some mild jittering when all the entities are pulled towards the center, however, this is how it looks if I build the application:


    There's also this strange phenomenon where all the particles cluster in the corners of the domain. I have no idea why this is happening either.

    Again, this is how it's supposed to look:


    If you're wondering what I am changing between examples I am simply just not applying any velocity to the entities in the ones that appear to be stable. And also not just (0, 0, 0), I am not scheduling the job at all.

    One solution I've found so far is to switch to unity physics (I am currently using Havok), however, in my case that lowers the performance of the application too much to be a viable option.

    Another solution I've found is to use the Entities.ForEach functionality in component systems, where you can pass a direct reference to a PhysicsVelocity component. This eliminates the need to use a command buffer or entity manager. Furthermore, this, again, ties into the idea that it has something to do with changing the component itself.

    However, this is also not a viable option because of how I am actually changing the velocity. That being I am passing in an array of velocity changes to the job that directly correspond, element-wise, to an array of entities. The reason I am doing this is because I am using a compute shader to calculate forces between the entities, and need to format it this way to be in compliance with the cpu-to-gpu API.

    If you have any suggestions or ideas, please, I'd be very grateful.
     
  2. milos85miki

    milos85miki

    Joined:
    Nov 29, 2019
    Posts:
    197
    I see 2 potential causes of that behavior:
    - The system that is changing PhysicsVelocity component should update before BuildPhysicsWorld or after ExportPhysicsWorld. Basically, the job that performs the PhysicsVelocity change (either directly or the job that executes ECB) should complete before BuildPhysicsWorld.OnUpdate or should start after all jobs spawned in ExportPhysicsWorld are complete.
    - You might have an index mismatch in velocity change array you're creating, so entities are getting wrong PhysicsVelocity changes.

    There's a sample scene you could look at: UnityPhysicsSamples/Assets/Demos/1. Hello World/1c. Conversion/1c3. DOTS GravityWell.unity . Please let me know if this helps.
     
    l_Lobsternator likes this.
  3. l_Lobsternator

    l_Lobsternator

    Joined:
    Aug 31, 2019
    Posts:
    12
    Ah, yes, updating it before BuildPhysicsWorld makes it stable! However I also need to call Complete on the job, is there any way I could go about this without creating a synch-point?

    I tried adding the JobHandle to the input of the BuildPhysicsWorld like in the example you pointed towards but that didn't seem to have any effect.
     
  4. milos85miki

    milos85miki

    Joined:
    Nov 29, 2019
    Posts:
    197
    The best you can do is to add the handle to BuildPhysicsWorld.AddInputDependencyToComplete(). If it turns out to be a burden, you could try to update your system after ExportPhysicsWorld or EndFramePhysicsSystem, if that fits with your other systems. Just don't forget to register the job handle with BuildPhysicsWorld in any case. :)