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

Official Unity Physics Discussion

Discussion in 'Physics for ECS' started by smcclelland, Mar 18, 2019.

Thread Status:
Not open for further replies.
  1. NGC6543

    NGC6543

    Joined:
    Jun 3, 2015
    Posts:
    228
    Oops, sorry. Post deleted.
     
    Last edited: May 10, 2019
  2. Brian-FJ

    Brian-FJ

    Joined:
    Apr 23, 2013
    Posts:
    9
    Hi Stevee, sorry to be back with another problem. I implemented this and it worked quite well. By re activating objects in a pair after the broadphase stage it seemed like entities almost always had a PhysicsVelocity before the collision happened.

    However, if I had a joint connecting two objects and I remove the PhysicsVelocity from both then I get an assert in Solver.cs, GetMotions(...) as both objects are static. This is for when we're solving the joint jacobians. That assert does make sense really, but could the joint jacobians be filtered out if there are two static bodies on the joint?

    I could of course remove the joint component when both bodies are sleeping, it's just a bit more work to re awaken as I need to cache the joint values (as you know I don't need to cache the PhysicsVelocity, the values are 0 as it was resting).

    Anyway, this isn't really blocking us, just wanted to give some feedback.
     
    steveeHavok likes this.
  3. SamOld

    SamOld

    Joined:
    Aug 17, 2018
    Posts:
    333
    They're not a built out feature yet. You can linearly go through all collisions with
    World.Active.GetExistingSystem<StepPhysicsWorld>().Simulation.CollisionEvents
    and find the ones you need, but that's obviously not efficient unless you want to process many at once. I've been using spacial queries instead without much trouble.

    For your example, each bullet can raycast forward by
    dt * velocity
    to detect collisions.
     
    Last edited: May 10, 2019
    steveeHavok likes this.
  4. merpheus

    merpheus

    Joined:
    Mar 5, 2013
    Posts:
    202
    Well personally I need something similar, but Idk making a AABB component to detect collisions is actually an easier approach or am I mistaken :D
     
  5. SamOld

    SamOld

    Joined:
    Aug 17, 2018
    Posts:
    333
    Sorry, I don't fully understand your scenario. Do you mean an entity with an AABB collider on it?

    To get those collision events you need to enumerate through the full world's collisions and find them manually. In a world with many bodies giving events that all need to be handled differently, this is quite a hassle and computationally inefficient. You could go through the entire list and preprocess those events out into another structure to make them easier to look up by body index. It's not impossible but it's a hassle, and I believe it's an area that will be overhauled with a more usable API soon. @steveeHavok has mentioned further up the thread that they've not really got to that yet.

    I've found it much easier to have systems perform spacial queries when they need trigger information. The better option will depend on the situation, but I've never found it easier to use
    Simulation.CollisionEvents
    yet.

    In the particular case of bullets as @WAYN_Group was mentioning, it's often better to use ray casts or collider casts anyway because they can be very fast moving and you don't want to miss collisions because the integration step is too large.
     
  6. SamOld

    SamOld

    Joined:
    Aug 17, 2018
    Posts:
    333
    Is it expected that APIs that use unsafe pointers (particularly colliders) will be replaced by safe alternatives?
     
  7. merpheus

    merpheus

    Joined:
    Mar 5, 2013
    Posts:
    202
    Yes, I just wanna decrease the health of my player when a bullet hits to it. In potato mono way we were doing it with OnCollisionEnter and stuff. I understand that we are not there yet, but raycast examples are look quite a bit complicated, personally I couldn't cast and detect entities yet. Despite I've been trying and getting "slicing errors" for days. I belive I'll settle for a clear example here. :)

    So, when I said AABB, I was mentioning about not using Unity.Physics and just making a custom system and a custom component that detects collisions with AABB.
    Thanks
     
  8. SamOld

    SamOld

    Joined:
    Aug 17, 2018
    Posts:
    333
    If you want to build your own little system for it then by all means, but it's not hard to get basic casting working in Unity Physics. This should get you started, and there's more in the official samples.

    Code (CSharp):
    1.  
    2. static bool RaycastFirstHit(float3 from, float3 ray, uint mask, out RaycastHit hit)
    3. {
    4.     var physicsWorld = World.Active.GetOrCreateSystem<BuildPhysicsWorld>().PhysicsWorld;
    5.     var rayInput = new RaycastInput() {
    6.         Filter = {CategoryBits = uint.MaxValue, MaskBits = mask},
    7.         Ray = {Origin = from, Direction = ray}
    8.     };
    9.     var didHit = physicsWorld.CastRay(rayInput, out hit);
    10.     return didHit;
    11. }
    12.  
    If you're getting an exception to do with slicing that sounds like a bug you should report.
     
    merpheus likes this.
  9. merpheus

    merpheus

    Joined:
    Mar 5, 2013
    Posts:
    202
    UPDATE: Problem is solved, I realized I was setting Filter wrong and that was the reason behind this Assert message.
    As a feedback, @Joachim_Ante it would be great to have a more explicit message in future for filter definition.

    I'm glad you asked :)

    So, I saw those examples although they all hybrid examples and not even jobified. I want to do this in jobs. So I have a JobComponent system and my job struct is as follows:
    Code (CSharp):
    1.    [BurstCompile]
    2.     struct BulletCollisionHandlingJob : IJobForEach<PhysicsVelocity, LocalToWorld, BulletCollisionComponent>
    3.     {
    4.         [ReadOnly] public CollisionWorld world;
    5.         public void Execute(ref PhysicsVelocity physicsVelocity, ref LocalToWorld localToWorld, ref BulletCollisionComponent bulletCollision)
    6.         {
    7.             RaycastInput input = new RaycastInput
    8.             {
    9.                 Ray = new Ray
    10.                 {
    11.                     Origin = localToWorld.Position,
    12.                     Direction = localToWorld.Forward
    13.                 }
    14.             };
    15.                 bulletCollision.Raycasting = world.CastRay(input, out RaycastHit hit);
    16.         }
    17.     }
    But when I do that I got this:
    Code (CSharp):
    1. Assertion failure. Value was False
    2.  
    3. Expected: True
    4. UnityEngine.Assertions.Assert:IsTrue(Boolean)
    5. Unity.Physics.Broadphase:CastRay(RaycastInput, NativeSlice`1, ClosestHitCollector`1&) (at Library/PackageCache/com.unity.physics@0.0.2-preview.1/Unity.Physics/Collision/World/Broadphase.cs:350)
    6. Unity.Physics.CollisionWorld:CastRay(RaycastInput, ClosestHitCollector`1&) (at Library/PackageCache/com.unity.physics@0.0.2-preview.1/Unity.Physics/Collision/World/CollisionWorld.cs:115)
    7. Unity.Physics.QueryWrappers:RayCast(CollisionWorld&, RaycastInput, RaycastHit&) (at Library/PackageCache/com.unity.physics@0.0.2-preview.1/Unity.Physics/Collision/Queries/Collidable.cs:105)
    8. Unity.Physics.CollisionWorld:CastRay(RaycastInput, RaycastHit&) (at Library/PackageCache/com.unity.physics@0.0.2-preview.1/Unity.Physics/Collision/World/CollisionWorld.cs:111)
    9. BulletCollisionHandlingJob:Execute(PhysicsVelocity&, LocalToWorld&, BulletCollisionComponent&) (at Assets/DOTS/Systems/BulletCollisionHandlingSystem.cs:29)
    10.  
    Which BulletCollisionHandlingSystem.cs:29 is actually the world.CastRay(input, out RaycastHit hit); line,
    I was getting a NativeSlice error in default example of documentation, I guess because of my ColliderWorld is somehow not allow me to write.
    Edit: I realized I get

    ArgumentException: Slice may not be used on a restricted range array
    Parameter name: array

    when I remove [ReadOnly] tag from PhysicsWorld/CollisionWorld. (Both of them gives the same error)

    Any way, I am basically following a pretty similar example as you suggested but I got an assertion failure.
     
    Last edited: May 14, 2019
  10. LlamaFarmer42

    LlamaFarmer42

    Joined:
    Jul 19, 2013
    Posts:
    9
    I've found that if you have a prefab gameobject (using ConvertToEntity) with a child that has a PhysicsShape on it, when raycasting it's being treated as if the child's collider is always at the child's coords in the prefab no matter where it was instantiated or where it's moved to. So if the child with the collider has its transform set to (10,0,20) that's where the raycast will think it is, even though the mesh renderer will correctly put it at (10,0,20) *relative* to the parent as expected.

    Code (CSharp):
    1. Prefab GameObject [ConvertToEntity]
    2.     -> Child GameObject [Mesh, MeshRenderer, PhysicsShape]
    This is using CollisionWorld.CastRay. Everything else about that code is working fine, and if I move the child's components onto the parent it works perfectly, so seems to be it being on a child that causes the problem. Effectively it seems to be taking the child's transform position (that should be read as relative to the parent) as if that's it's absolute world position. Is this some inherent limitation at this time, or is there some step I'm missing?
     
  11. steveeHavok

    steveeHavok

    Joined:
    Mar 19, 2019
    Posts:
    481
    The Collider has a header struct, which then read further into memory based on information in the header (e.g. depending on which type of collider it is). When you do
    var collider = physicsCollider.Value.Value
    you are taking a copy of that header which ends up pointing to random memory, giving you the dodgy Aabb.
    This section of the intro video discuss the reasoning behind the use of the collider headers.
    If you use
    ref var collider = physicsCollider.Value.Value
    you would have been ok.
     
  12. steveeHavok

    steveeHavok

    Joined:
    Mar 19, 2019
    Posts:
    481
    I'll try and setup a repo and check this out (unless you have one handy?).
    You may well be right on the system ordering thought. If you have spawned a new bullet, it won't be in the CollisionWorld until after the BuildPhysicsWorld system has ran. So if your system is running before BuildPhysicsWorld, you will be quering the state of the physics from the previous frame.

    There are three main systems in Unity Physics:
    1. BuildPhysicsWorld - take the ECS data and convert it to NativeArray information. Holds the collision world.
    2. StepPhysicsWorld - perform collision detection and respond. Holds the simulation (and Trigger/Collision events).
    3. ExportPhysicsWorld - put the data in the NativeArray back into the appropriate ECS ComponentDataPhysics
    Each of those systems has a public `FinalJobHandle` so if your own systems need to query the information from one of the Physics systems it would be best to add FinalJobHandle as a dependancy for your own Jobs.
     
  13. steveeHavok

    steveeHavok

    Joined:
    Mar 19, 2019
    Posts:
    481
    Thanks for the details. There have been a few combinations that fire these asserts. I've logged them all and we'll see want can be done to make life a little easier.
     
    SamOld likes this.
  14. WAYNGames

    WAYNGames

    Joined:
    Mar 16, 2019
    Posts:
    988
    Hi,

    I'm a bit confused on how to apply damage to my enemies.

    For now here is how I do it :

    I cast a ray from my bullet to find which entity I hit.
    If I hit something, I destroy my bullet, and add the entity to a native queue with the damage to apply.
    Then I have another job that goes through every entity that have a health component and for each of them I loop through my queue to compare the job entity to the entity store in the queue. If they match I update the health.

    It work but it seems odd that I need to :
    1) go through every entity that have health even the one I know where not hit.
    2) go through all my queue to link the amount of damage to apply to the entity i need to apply it to when the match was already done when doing the ray casting from the bullet to provision the queue.

    That does not seem very efficient.
    I assume this use case will be covered differently when the collision events are implemented, am I correct ?

    I could use the command buffer to set the health component of the entity I hit but I have no way to decrease it, meaning I can't get it's current value from within the job, nor can I add a "relative" command to the buffer (instead of set do and update with an offset +/- damageAmount) .Would the relative update be a relevant/interesting feature ?
     
    NotaNaN likes this.
  15. LlamaFarmer42

    LlamaFarmer42

    Joined:
    Jul 19, 2013
    Posts:
    9
    The documentation about filtering appears to be written the wrong way around in the table about the CollisionFilter members. It says MaskBits is "A bitmask which describes which layers a collider belongs too." and CategoryBits is "A bitmask which describes which layers this collider should interact with".

    Testing shows that actually these are the other way around, in line with the sentence further down: "Currently the editor view of the Collision Filter just exposes the Category and Mask as 'Belongs To' and 'Collides With'."
     
    SamOld likes this.
  16. LlamaFarmer42

    LlamaFarmer42

    Joined:
    Jul 19, 2013
    Posts:
    9
    Given you're probably not getting many hits per frame, I'd probably try adding a 'Damaged' component onto the hit entities with a value for the damage amount. Then use another job like you're doing now, but only targeting those with both Health and Damaged components, use the value from Damaged to change the Health, then remove the Damaged component.

    That would also mean you've clearly separated out the concept of 'damaged' from the work of doing the damage for any other logic or filtering you might want to do - eg setting damage type and applying resistances.
     
    NotaNaN likes this.
  17. steveeHavok

    steveeHavok

    Joined:
    Mar 19, 2019
    Posts:
    481
    Burst supports a subset of C# so there are some patterns needed to This is due to the limitations of Burst currently. As I mentioned above, it is briefly discussed in the intro video.
     
    hippocoder likes this.
  18. steveeHavok

    steveeHavok

    Joined:
    Mar 19, 2019
    Posts:
    481
    Thanks, we've renamed Category and Mask to match the PhysicsShape 'BelongsTo' and 'CollidesWith' to reduce this sort of confusion.
     
    Shinyclef likes this.
  19. SamOld

    SamOld

    Joined:
    Aug 17, 2018
    Posts:
    333
    I've not used Burst much yet so maybe there's a restriction I've not noticed, but is there a reason that those unsafe bits of the public API couldn't be abstracted away with safe wrappers? For a rough untested example:

    Code (CSharp):
    1. unsafe readonly struct ColliderPtrWrapper
    2. {
    3.     private readonly Collider* colliderPtr;
    4.  
    5.     public ColliderPtrWrapper(Collider* ptr) => this.colliderPtr = ptr;
    6.     public ColliderPtrWrapper(PhysicsCollider collider) => this.colliderPtr = collider.ColliderPtr;
    7.  
    8.     // Delegate methods through to pointers
    9.     public Aabb CalculateAabb() => this.colliderPtr->CalculateAabb();
    10. }
    I really dislike that the Unity Physics API is requiring me to mark my gameplay code as unsafe. I'm writing a character controller at the moment and most of the methods end up being unsafe because they touch colliders. That feels bad.

    I understand that the header trick is a workaround for restrictions, but I worry that if it's part of the public API it's going to be responsible for 90% of all "HELP MY PHYSICS DOESN'T WORK" forum posts. It's just too easy to accidentally copy by value instead of by reference, and too hard to work out what went wrong and where it happened. Have you concluded that it's not possible to abstract these things away from the public interface?

    Edited to make struct readonly because I'm not a monster.
     
    Last edited: May 15, 2019
    steveeHavok likes this.
  20. WAYNGames

    WAYNGames

    Joined:
    Mar 16, 2019
    Posts:
    988
    True I'm not getting many hit per frame in this use case but my reflection is in a more extansible framework. With you suggestion, what would appen if the same netity was hit by more than one "source of damage" per frame ? I would end up with multiple Damage compoanent on the same entity. I'm not sure it's even possible...
     
  21. steveeHavok

    steveeHavok

    Joined:
    Mar 19, 2019
    Posts:
    481
    Let me summarise the issues so far:
    1. /*ref*/ Collider collider = physicsCollider.Value.Value 

      If the ref is not included we are making a copying of the Collider. Collider is really a header with information about an associated block of memory that follows it. Copying the header means subsequent queries access inappropriate memory offset from the header giving jibberish results. Current solution: add ref.
    2. Collider* collider = physicsCollider.ColliderPtr

      Using this pattern mean you need to mark you own code as unsafe.
    There are two possibilities to help with these issues.
    First we can add a unique marker into the collider blob following the header. This marker would be checked before the likes of CastRay is called. If a header is copied, rather than referenced, this marker will not be there and an appropriate warning can be issued. This at least informs folk appropriately in case (1) above or where colliders are being generated at runtime independant of the PhysicsCollider struct.
    Second, we could have the PhysicsCollider IComponentData struct implement the ICollider interface. This would mean you could call the likes of
    physicsCollider.CastRay
    directly rather than
    physicCollider.Value.Value.CastRay
    or
    physicsCollider.ColliderPtr->CastRay
    . This would help the unsafe concerns in case (2).
    Both of these are logged, and we'll check them out.

    Please let me know if there are any other usecases I've missed or any other thoughts on this.
     
    SamOld likes this.
  22. SamOld

    SamOld

    Joined:
    Aug 17, 2018
    Posts:
    333
    I'll have a proper think about this and maybe get back to you in more detail, but the main usecase I think you're missing is with
    ColliderCastInput
    and similar. Those currently take a pointer, meaning
    physicsWorld.CastCollider(input)
    scenarios are unsafe too.

    This is a bit of an aside, but it would be nice to have
    physicsWorld.CastSphere
    ,
    physicsWorld.CastCapsule
    etc as methods that don't require a collider input at all.
     
    steveeHavok likes this.
  23. SamOld

    SamOld

    Joined:
    Aug 17, 2018
    Posts:
    333
    I spent a little time going through things and making some notes for my own understanding. This is a raw log of my thoughts so far. It's long and messy, but if I spend time tidying it up I'll never get around to posting it. Maybe there's something of value here.

    ---

    Unsafe code and pointers are not idiomatic C#. They are used in rare cases only, and should not be part of business/game logic.

    Unity has cultivated a community of devs without a strong software engineering background. They aim to be accessible to game designers who want to do a bit of scripting, as well as software engineers who want to make a game. This lead to design decisions I didn't like, coming from a software background, but I worry that lurching hard the other way is going to cause problems and resistance from the community. Expecting people used to using C# as a scripting language to smoothly handle the edge cases and complexities of references, values, and pointers is going to be a point of friction. How many experienced C# devs can even reliably name all places the compiler silently makes a defensive copy? Where at all possible, I would like to see those things abstracted away behind more robust and forgiving APIs.

    ---

    Colliders seem to be represented in three different ways in the API.

    - `(ref?) Collider`
    - `Collider*`
    - `BlobAssetReference<Collider>`

    The specialised collider types (SphereCollider etc) have static factories that return the base `BlobAssetReference<Collider>` rather than their own type. That's weird. Why not put factories on `Collider`?

    As far as I can see, the specialised types are only exposed publicly for their factories. Every other use of them is internal delegation via `Collider`. The exception is explicit casting to edit data. SteveeHavok provided this sample:
    Code (CSharp):
    1. fixed (Collider* collider = [PhysicsCollider]->ColliderPtr)
    2. {
    3.     switch (collider->Type)
    4.     {
    5.         ...
    6.         case ColliderType.Box:
    7.             var boxCollider = ((BoxCollider*)collider);
    8.             boxCollider.Size = new float3( x, y, z );
    9.             break;
    10.         ...
    11.         default:
    12.             break;
    13.     }
    14. }
    I don't like it because it's encouraging lots of unsafe things for something that might be in basic gameplay code. I shouldn't need to go anywhere near pointers to resize a box. That's not C#, that's C.

    ---

    Rough proposal - not tested any of this yet

    This attempts to make a safe API around collider pointers:

    Code (CSharp):
    1. // Wraps Collider*
    2. // Can be used in safe contexts - no more unsafe gameplay methods
    3. // Safe to copy by value because it just copies the pointer
    4. // Should replace anything that currently uses Collider*
    5. public readonly unsafe struct ColliderReference : ICollider, ICollidable
    6. {
    7.     // Pointer exposed internally so easy to adopt
    8.     internal readonly Collider* ptr;
    9.  
    10.     internal ColliderReference(Collider* ptr) => this.ptr = ptr;
    11.  
    12.     public bool IsValid => this.ptr != null;
    13.  
    14.  
    15.     // Pass public API through to pointer
    16.     public ColliderType Type => this.ptr->Type;
    17.     public CollisionType CollisionType => this.ptr->CollisionType;
    18.     public MassProperties MassProperties => this.ptr->MassProperties;
    19.     public int MemorySize => this.ptr->MemorySize;
    20.     // ...
    21.  
    22.     // Allow safe explicit conversion to sub types
    23.     public static explicit operator SphereColliderReference(ColliderReference collider)
    24.     {
    25.         Assert.IsTrue(collider.IsValid && collider.Type == ColliderType.Sphere);
    26.         return new SphereColliderReference((SphereCollider*)collider.ptr);
    27.     }
    28.     // ...
    29. }
    30.  
    31. // Wraps SphereCollider*
    32. // Faux child type of ColliderReference
    33. // This is the public API interface for SphereCollider
    34. // Can now make SphereCollider an internal type
    35. // Access to updatable collider properties now possible without touching pointers
    36. public readonly unsafe struct SphereColliderReference : ICollider, ICollidable
    37. {
    38.     // pointer exposed internally so easy to adopt
    39.     internal readonly SphereCollider* ptr;
    40.  
    41.     internal SphereColliderReference(SphereCollider* ptr) => this.ptr = ptr;
    42.  
    43.     public bool IsValid => this.ptr != null && this.ptr->Type == ColliderType.Sphere;
    44.  
    45.     // Pass public API through to pointer
    46.     public ColliderType Type => this.ptr->Type;
    47.     public CollisionType CollisionType => this.ptr->CollisionType;
    48.     public MassProperties MassProperties => this.ptr->MassProperties;
    49.     public int MemorySize => this.ptr->MemorySize;
    50.     // ...
    51.  
    52.     // Access to the properties specific to this type
    53.     public float Radius { get => this.ptr->Radius; set => this.ptr->Radius = value; }
    54.     public float3 Center { get => this.ptr->Center; set => this.ptr->Center = value; }
    55.  
    56.     // Allow implicit conversion to the faux base type to mimic reference behaviour
    57.     public static implicit operator ColliderReference(SphereColliderReference collider)
    58.         => new ColliderReference((Collider*)collider.ptr);
    59. }
    This doesn't address PhysicsCollider... Let's look at that.

    I don't fully understand BlobAssetReference<T> yet. It seems to be a wrapper around a pointer to preallocated memory that handles validation and release. It looks like it allocates and then throws away 256MB every time a tiny collider is created - I need to go back and check because that's crazy. Oh, I think I was supposed to manually release my colliders! TODO! Unity ECS is able to serialise this data, which is why it's needed in IComponentData.

    Code (CSharp):
    1. // I'm not completely comfortable with how blobs work
    2. // Can we change this to wrap a BlobAssetReference<Collider>?
    3. // That in turn wraps the pointer
    4. // This might now be serialisable directly in IComponentData
    5. public readonly unsafe struct ColliderReference : ICollider, ICollidable
    6. {
    7.     // By storing the blob instead, this should now be serialisable by ECS
    8.     // I hope
    9.     internal readonly BlobAssetReference<Collider> blob;
    10.     internal Collider* ptr => (Collider*)this.blob.GetUnsafePtr();
    11.  
    12.     internal ColliderReference(BlobAssetReference<Collider> blob)
    13.         => this.blob = blob;
    14.  
    15.     // ...
    16. }
    17.  
    18. // We can have this wrap a BlobAssetReference<Collider> too
    19. // This is good because they should be the same, and it makes factories nice
    20. public readonly unsafe struct SphereColliderReference : ICollider, ICollidable
    21. {
    22.     internal readonly BlobAssetReference<Collider> blob;
    23.     internal SphereCollider* ptr => (SphereCollider*)this.blob.GetUnsafePtr();
    24.  
    25.     internal SphereColliderReference(BlobAssetReference<Collider> blob)  => this.blob = blob;
    26.  
    27.  
    28.     // ...
    29.  
    30.  
    31.     // Factory returns this type
    32.     // You will usually just want a ColliderReference
    33.     // It implicitly casts, so that's fine
    34.     public static SphereColliderReference Create(float3 center, float radius)
    35.         => new SphereColliderReference(SphereCollider.Create(center, radius))
    36. }
    37.  
    38. // Is this now valid because it's wrapping a blob?
    39. // This could get us down to a single interface pattern for colliders
    40. // Would be no need to worry about value/ref semantics because Collider is never exposed
    41. public struct PhysicsCollider : IComponentData
    42. {
    43.     public ColliderReference Value;
    44. }
    If we can get all collider use down to a single reference wrapper type (and faux sub types) that would be neat. We would have the same API everywhere, no pointers, and no worry about value/reference semantics (because it's all references under the hood). The
    Collider
    type itself could be made internal. That would be good, because its weird header nature is a minefield and should be only an implementation detail. Users shouldn't know or care about that weirdness.

    These patterns might also apply to joints.
     
    Last edited: May 16, 2019
  24. rz_0lento

    rz_0lento

    Joined:
    Oct 8, 2013
    Posts:
    2,361
    Unity Physics 0.0.2-preview.1 doesn't seem to play nice with IL2CPP at least on Windows builds (didn't test with the first package, just pointing out that current one doesn't work with it). You can see this with any 2019.x version that can run physics samples from DOTS samples repo. Just add some physics scene on your build, swap it to use IL2CPP and note how it throws errors around.

    edit: Apparently there's many things going wrong with IL2CPP builds now:

    - 2019.1.2f1 IL2CPP fails to include some file from engine folder which is present so that could be totally different issue.
    - 2019.3.0a2 can't process PhysicsMaterialCoefficient struct, it gives error:
    when I manually remove [SoftRange(0f, 1f, TextFieldMax = float.MaxValue)] tag on PhysicsMaterialCoefficient struct, that error goes away.
    - 2019.3 also gives errors on tests but removing tests on both DOTS sample repo's physics samples + Unity Physics package resolves this part
    - 2019.3 still instantly crashes when you play the IL2CPP built standalone if you use latest 0.0.1-preview.12 Hybrid Renderer and 0.0.12-preview.31 Entities packages. Using one step older versions works even in standalone build.

    edit #2:

    - 2019.3 works latest packages on IL2CPP standalone builds if you disable burst, some physics are wonky still (joints freak out) but it doesn't instantly crash to desktop like it does when Burst (1.0.4) is being used.

    edit #3:

    - after doing other fixes, I found out that Entities p.32 is what is giving trouble with Unity Physics. Up to Entities p.31 everything works fine, after p.32 joints seem to break and seek for some index that is totally out of range, this is probably also what makes Burst hard crash.

    edit #4:

    - on my other project, even p.31 causes hard crash on standalone IL2CPP build because Entity Tracker gets some null pointer. If I put few frames delay on that script alone, it doesn't crash and then it tracks the entity properly but for some reason Unity Physics collisions don't work in IL2CPP there (they do work on Mono build).
     
    Last edited: May 17, 2019
  25. sebas77

    sebas77

    Joined:
    Nov 4, 2011
    Posts:
    1,641
    Hello, I thought about this and the part where you say "your own logic" scares me a bit. Let's immagine there are leaves that are sleeping, a blow of wind won't be able to move them without me adding logic that actually shouldn't be needed to add. I wonder then if something as simple as forcing the velocity to be zero if under a given threshold would make sense.
     
    steveeHavok likes this.
  26. steveeHavok

    steveeHavok

    Joined:
    Mar 19, 2019
    Posts:
    481
    It depends on what you want your sleeping mechanism for. If to help stacking, then tweaking velocities to zero might help. However, if it is needed to help performance (i.e. removing the cost of narrow phase collision detection cost) then you'll have to make your leaves static.
    Your wind example is great one. The wind system would already need some logic to know which bodies to apply forces to. If it affected all the bodies all the time then nothing should be sleeping. A wind system could instead blow everything inside a trigger volume for example. In this case, as leaf bodies enter the winds trigger volume they can be woken up (i.e. have a PhysicsVelocity component added). As leaf bodies exit the trigger volume they can sleep (i.e. have the PhysicsVelocity component removed) when the velocity drops below the threshold you mention.
    We are looking at mechanism this could help with this sort of component manipulation.
     
    SamOld likes this.
  27. steveeHavok

    steveeHavok

    Joined:
    Mar 19, 2019
    Posts:
    481
    Sorry about your troubles there. We have a pull request going through now with a p32 upgrade. We'll post more details when available.
     
    Shinyclef and rz_0lento like this.
  28. rz_0lento

    rz_0lento

    Joined:
    Oct 8, 2013
    Posts:
    2,361
    Ah don't get me wrong, I'm mainly reporting these here in case others go through the same + give feedback to you guys. I'm used to preview builds being wonky at times :)

    I do have question about IL2CPP builds though, is this something you test when you release a new version?
     
  29. sebas77

    sebas77

    Joined:
    Nov 4, 2011
    Posts:
    1,641
    Thanks we profiled the two scenarios and the difference is different than you may expect.
    In a scenario with 1000 cubes without collision, making them static improve the performance of around 10%. However when collisions come in to play, as we need to listen to the collision events to awake the cubes, this overhead makes the static approach slower than just setting the velocity to 0.
    Also since we force the velocity to be actually 0 (and not close to 0), I wonder if you could instead add optimizations to skip some processing when the module is really 0.
     
  30. alfiare

    alfiare

    Joined:
    Feb 10, 2017
    Posts:
    30
    Very excited about where ECS and Unity.Physics is going! Is there any plan to support the burst compiler for MeshCollider.Create(...)? The internals of it currently use managed arrays so that keeps it from being Burst-able. I took a quick look and it didn't seem like there was anything in there that would keep use of a NativeArray or NativeList from being possible but just wondering if that's planned?
     
    FROS7 and SamOld like this.
  31. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    Yes. We were just discussing it the other day. Its also a big bottleneck in conversion flow, we'll fix it soon.

    Generally lots of threading changes are incoming soon. We did a big pass and removed every single syncpoint. It's quite awesome to see physics run and only when the objects get rendered does it have to complete the physics jobs on main thread...
     
    hippocoder, siggigg, NotaNaN and 13 others like this.
  32. SamOld

    SamOld

    Joined:
    Aug 17, 2018
    Posts:
    333
    That's really cool. I'm curious, does doing that have a big impact on performance in a typical scene?
     
    FROS7 likes this.
  33. steveeHavok

    steveeHavok

    Joined:
    Mar 19, 2019
    Posts:
    481
    Fantasic reply and in general we all agree. Its not as high a priority as other things at the minute, but it is something we'll look at before a v1.0 release.
     
    Sarkahn, thelebaron and SamOld like this.
  34. SamOld

    SamOld

    Joined:
    Aug 17, 2018
    Posts:
    333
    Thanks, that's great to hear, and it's cool how much you guys are consulting the community on this.
     
    steveeHavok and FROS7 like this.
  35. Srokaaa

    Srokaaa

    Joined:
    Sep 18, 2018
    Posts:
    169
    I have a question about setting initial kinematic body velocity programmatically. I have a prefab converted from game object to entity by implementing IConvertGameObjectToEntity and IDeclareReferencedPrefabs. Then I spawn it like this:

    Code (CSharp):
    1.  
    2. var prefabEntity = commandBuffer.Instantiate(featurePrefab);
    3.  
    and want to set initial velocity like this:
    Code (CSharp):
    1.                                
    2. var rigidBodyIndex = physicsWorld.GetRigidBodyIndex(prefabEntity);
    3. physicsWorld.SetLinearVelocity(rigidBodyIndex, speed);
    4.  
    This obviously does not work since the entity had no chance to be registered in the physics world yet. So I am left with a entity standing still. Any hints on how to do this correctly?
     
  36. WAYNGames

    WAYNGames

    Joined:
    Mar 16, 2019
    Posts:
    988
    Set the velocity of the prefab in your inspector if it's a fixed number or set the PhysycsVelicity component with the command buffer without passing by the physics world.
     
  37. Srokaaa

    Srokaaa

    Joined:
    Sep 18, 2018
    Posts:
    169
    @WAYN_Group I'm spawning a lot of those entities and each has a different position, speed and rotation which are procedurally generated
     
  38. WAYNGames

    WAYNGames

    Joined:
    Mar 16, 2019
    Posts:
    988
    I do something similar in my shooting system :
    Code (CSharp):
    1. // Create teh bullet
    2.                 var instance = CommandBuffer.Instantiate(index, shotParam.spawnCapabilityParameters.Spawnable);
    3.  
    4.                 // Place it at the end of the gun
    5.                 CommandBuffer.SetComponent(index, instance, new Translation { Value = location.Position });
    6.                 CommandBuffer.SetComponent(index, instance, new Rotation { Value = quaternion.LookRotationSafe(location.Forward, math.up()) });
    7.                 CommandBuffer.SetComponent(index, instance, location);
    8.                 CommandBuffer.AddComponent(index, instance, new Speed() { Value = shotParam.Speed});
    9.  
    10.                 // Make it move forward
    11.                 CommandBuffer.SetComponent(index, instance, new PhysicsVelocity { Linear = location.Forward * shotParam.Speed });
    12.  
    Full source available here.
     
    steveeHavok likes this.
  39. SamOld

    SamOld

    Joined:
    Aug 17, 2018
    Posts:
    333
    @steveeHavok Sorry for filling this thread up with this topic, but I just realised that I never made clear my reason for thinking the ref/value issue with
    Collider
    is so important. You've probably inferred my point already, but I'd just like to state it explicitly for completeness.

    Accidentally copying a normal struct by value instead of reference is a harmless bug - some functionality will break, but nothing else will go wrong. Copying one of the weird header structs by value is far more dangerous as they read from and write to whatever memory is directly after themselves. Setting a specialised property on a value copied Collider is writing to an arbitrary memory location. This can create horrible random bugs that manifest erratically and are almost impossible to debug. That's why I feel it's so important that those types are never publicly exposed and the user doesn't have a chance to get into that situation from a minor typo forgetting a
    ref
    . I'm sure you don't want to have to contemplate that possibility every time you get a bug report, either.
     
    Orimay and steveeHavok like this.
  40. TLRMatthew

    TLRMatthew

    Joined:
    Apr 10, 2019
    Posts:
    65
    I'm having some trouble moving my collision/raycasts over to the new Physics package. I generate a single large mesh at runtime, and need a reasonably accurate Collider for it as well, as I want to display a cursor on the surface of the mesh.

    Previously, I was simply using:

    Code (CSharp):
    1. MeshCollider collider = GetComponent<MeshCollider>();
    2. collider.sharedMesh = mountainMesh;
    And this was fast enough even for a very large mesh (1 million+ tris), considering I do it just once at startup.

    However, generating an equivalent Unity.Physics.MeshCollider for my large meshes takes an inordinate amount of time, seemingly either increasing exponentially with vert/tri count, or simply hanging my editor entirely. For example, ~380k triangles takes 55 seconds, ~620k triangles takes 130 seconds, ~1 million triangles takes 5.5 minutes, and anything larger than that I've yet to see complete.

    I also tried generating a large CompoundCollider, but (as expected) that's less efficient, taking 7 minutes for ~380k triangles.

    Is there some better way to approach what I'm trying to do here, or is it simply that creating a MeshCollider is not optimised yet? I saw Joachim say it will be burstable soon, but given how fast the "old" way of doing it was, it feels like maybe I'm approaching it wrong. Maybe that's just because the old way was able to share all the existing Mesh data and this version can't?

    I should note that I'm not going to be using dynamic bodies, I'll only be using these colliders for raycasting. The mesh collider itself COULD stay in Monobehaviour land, since there will only be one of them and it shouldn't have much impact on performance, but I will have other Entities with colliders and I'd rather not try to manage two different raycast systems interoperating with each other!
     
    steveeHavok likes this.
  41. steveeHavok

    steveeHavok

    Joined:
    Mar 19, 2019
    Posts:
    481
    Putting larger meshes in a subscene means they can be prebaked for load in the main scene. However, that will not help your use case if you need to build a MeshCollider on the fly.

    You are approaching things correctly. The building of a MeshCollider (or Compound) is simply not optimised yet, though as you mentioned the team are looking at it.
     
    TLRMatthew likes this.
  42. TLRMatthew

    TLRMatthew

    Joined:
    Apr 10, 2019
    Posts:
    65
    Thanks for the reply, for now I've reverted to using the old MeshCollider and doing both types of raycasts, and I'll swap over when those optimisations come through :)

    For what it's worth, prebuilding the Mesh and MeshCollider at import time would be workable for me in the short term, but I've never seen it finish at all with my full sized mesh. I could try leaving it running overnight but it's probably not worthwhile knowing that improvements are coming anyway.
     
    steveeHavok likes this.
  43. wesley_unity341

    wesley_unity341

    Joined:
    Dec 14, 2018
    Posts:
    9
    Hi. I am very raw on Unity Physics and have only just started looking into it. I have a concept in my head that requires real-time mesh deformation with generation of the mesh collider. This wasn't possible for larger meshes in the old system as the mesh collider had to be rebaked on the main thread.

    How does this now work with Unity physics? Can I update the collision mesh in real time now?
     
  44. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    We have some issues with generating blob data on a job right now, but we are definitely planning for creation of all blob shapes to be possible from a job.
     
    wesley_unity341 and FROS7 like this.
  45. Adam-Mechtley

    Adam-Mechtley

    Administrator

    Joined:
    Feb 5, 2007
    Posts:
    290
    Sorry I took so long to get back! Thanks for reporting this. I verified with my fixes and this should work as expected in the next release.
     
    hippocoder, zephyr831125 and FROS7 like this.
  46. Rodolphito

    Rodolphito

    Joined:
    Jan 31, 2014
    Posts:
    17
    I've found an inefficiency in Unity Physics on Convex <--> Convex collision detection, in file Collision/Geometry/ConvexHull.cs line 105, there's an unnecessary square root, and this is a pretty hot code path. It can be fixed like so:
    Code (CSharp):
    1.  
    2. 105 -                    float dot = math.abs(math.dot(direction, edgeDirection)) * math.rsqrt(math.lengthsq(edgeDirection));
    3. 105 +                    float dot = math.dot(direction, edgeDirection); //abs not needed here, dot is squared on the next line
    4. 106 +                    dot = (dot * dot) * (1.0f / math.lengthsq(edgeDirection)); //sqrt is not needed here, it doesnt modify the ordering
    5.  
    The reason being that `dot` is only used for ranking, so the actual value doesnt matter only the relative ordering is important. sqrt(x) is monotone increasing where it is defined, so it does not change the ordering. Therefore it can be removed without altering the functionality of the code.

    I haven't profiled this, maybe burst catches it and fixes it anyways. I dont know if burst goes that far with its optimization, though.

    I know that it must be a licensing mess for you guys, and I hope you are working on a solution to be able to accept contributions on github :)
     
    illinar, FROS7, steveeHavok and 3 others like this.
  47. firsy

    firsy

    Joined:
    Oct 2, 2016
    Posts:
    1
    Is there anyway i can replace a physics phase with my own implementation? im thinking specifically about the broadphase rn. i tried changing the physics layers so nothing collides and then adding pairs myself right after the normal broadphase, but there was no way to add pairs as far as i could see.
     
  48. wesley_unity341

    wesley_unity341

    Joined:
    Dec 14, 2018
    Posts:
    9
    Thanks for the reply Joachim. I take it this is a more broad generalisation of the problem with generating blobs of data on a thread at the moment than just updating the sharedMesh of a MeshCollider. I am just starting to investigate Unity Physics and collisions. Just how are mesh colliders generated/used in the case of Unity Physics? Why is updating the MeshCollider still a problem in a stateless physics system?
     
  49. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    We accidentally used some managed arrays in the blob creation process. It's not biggie, architecture was all made for this. Easy to fix.
    (We really need a compiler validation mode for our own code where we can specify certain functions must be burst compatible...)
     
    FROS7 likes this.
  50. SamOld

    SamOld

    Joined:
    Aug 17, 2018
    Posts:
    333
    This is slightly off topic for physics, but I've been thinking for a while about investigating putting together a set of Roslyn analyzers that could do this. Methods could be marked with attributes indicating whether they should be burst safe, then analyzers could ensure that burst safe methods only do burst safe things, including only calling burst safe methods. This way the IDE would be strictly enforcing the subset of C#. This would work best if Unity's own APIs embraced it and standardised the attributes. Is this something you might be interested in doing? If there's a conversation to have here, we should probably make a separate thread for it.
     
    FROS7 and dadude123 like this.
Thread Status:
Not open for further replies.