Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

["Solved"] Is it possible to create a CollisionWorld manually during conversion?

Discussion in 'Physics for ECS' started by Zec_, Jan 31, 2020.

  1. Zec_

    Zec_

    Joined:
    Feb 9, 2017
    Posts:
    148
    Hi!

    I read a paragraph in the documentation that stated that it's possible to create manual CollisionWorlds, but I can't find any information on how to do it. I've got a project where I'm using SubScenes, where it would be greatly beneficial to be able to use the static colliders during the conversion process to pre-calculate and serialize a whole bunch of static data for the scene.

    My thought was to create a CollisionWorld manually after the physics conversion systems have been run. I'd then run a ton of collision queries (raycasting etc) against it and store the data. If it makes it easier, I don't believe I need to include dynamic colliders, just the static ones.

    Does anyone think it's possible to create a CollisionWorld based on the collider data generated in the conversion world? If you do, do you have any examples or hints on what to investigate? Any links to information about the subject?

    Thanks in advance!
     
  2. Zec_

    Zec_

    Joined:
    Feb 9, 2017
    Posts:
    148
    After investigating for a day or so, it seems like the functionality might not be exposed? All code I find that create and set up collision worlds work against the Broadphase struct inside the CollisionWorld to schedule jobs that set up the CollisionWorld, but that is an internal struct. And most jobs related to setting up the data are also internal. I guess the documentation might mention something that isn't quite ready for usage yet?

    Here's what the documentation says on this page:
    You can choose to create your own collision worlds which are entirely independent of the physics world. However, if you are performing queries against the same physics world you are simulating, which is common, then you can take advantage of the fact that the broad phase had already been built.
     
  3. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    It's not exposed and it should be. Not only are isolated worlds useful they are emphatically the right tool for the job if you want to isolate or partition bodies in some way. With a few minor modifications that only expose access, they are also fairly straight forward to work with and build individually in isolation.

    This came up months ago actually and they made some rumblings about opening stuff up but nothing ever came of it.
     
    NotaNaN and Zec_ like this.
  4. Zec_

    Zec_

    Joined:
    Feb 9, 2017
    Posts:
    148
    Interesting. I did some searching for the topic on the forums before posting this thread but didn't find any topics related to the subject. I'll do some more searching tomorrow for that thread you mentioned, it'd be really interesting to read it! Thanks a lot for the insight and hint!
     
  5. Zec_

    Zec_

    Joined:
    Feb 9, 2017
    Posts:
    148
    I took another shot at this today and actually managed to solve this in a not-too-complex way, albeit still maybe a bit hacky. I feel like it isn't really intended to use the package like this, so I can't guarantee that this will keep working with future updates. Either way, if anyone is looking for using the collision data during conversion, this actually works seemingly flawlessly in the current version.

    I'm personally using this to calculate a ton of data during build-time for my Subscenes.

    Code (CSharp):
    1. using Unity.Entities;
    2. using Unity.Physics.Systems;
    3. using System.Collections.Generic;
    4. using System.Linq;
    5.  
    6. [UpdateInGroup(typeof(GameObjectAfterConversionGroup))] // All the Physics components are set up in the GameObjectConversionGroup, so they're available in the AfterConversion group
    7. public class CollisionCompatibleConversionSystem : GameObjectConversionSystem
    8. {
    9.     protected override void OnUpdate()
    10.     {
    11.         // Fetch the systems that exist in the world before we inject the additional physics systems
    12.         HashSet<ComponentSystemBase> systemsBefore = new HashSet<ComponentSystemBase>(this.DstEntityManager.World.Systems);
    13.  
    14.         // Create a BuildPhysicsWorld system in the DstWorld that contains all the physics components that have been previously converted.
    15.         // When creating the system, it's noteworthy that it will create a chain of additional physics systems due to code in it's OnCreate method.
    16.         // I'm personally only running Update on the BuildPhysicsWorld though, as I'm not interested in the other systems that manage Joints and steps the PhysicsWorld.
    17.         var buildPhysics = DstEntityManager.World.GetOrCreateSystem<BuildPhysicsWorld>();
    18.         buildPhysics.Update(); // Schedules a bunch of jobs to set up and create the PhysicsWorld
    19.         buildPhysics.FinalJobHandle.Complete(); // Complete the scheduled jobs above
    20.  
    21.         // The CollisionWorld is now set up and working. Feel free to run any collision queries here. Raycasting or whatever you want.
    22.         var collisionWorld = buildPhysics.PhysicsWorld.CollisionWorld;
    23.  
    24.         // I'm not sure what effect the injected systems might have, so just to be sure I'm cleaning up all the systems I created. I expect them to clean up after themselves (which they seemingly do).
    25.         // I'm doing that by simply comparing the currently existing systems against the snapshot of systems taken before creating the BuildPhysicsWorld system.
    26.         var currentSystems = this.DstEntityManager.World.Systems.ToArray();
    27.         for (int i = 0; i < currentSystems.Length; i++)
    28.         {
    29.             if (systemsBefore.Contains(currentSystems[i]) == false)
    30.                 this.DstEntityManager.World.DestroySystem(currentSystems[i]);
    31.         }
    32.     }
    33. }
     
    NotaNaN likes this.