Search Unity

  1. Unity Asset Manager is now available in public beta. Try it out now and join the conversation here in the forums.
    Dismiss Notice
  2. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  3. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Feedback DOTS Dynamic Bones (WIP) Demo V0.8.2.1

Discussion in 'DOTS Animation' started by NT_Ninetails, Sep 29, 2021.

  1. NT_Ninetails

    NT_Ninetails

    Joined:
    Jan 21, 2018
    Posts:
    195
    Demo available at the link

    https://github.com/Steven9Smith/DOTS-Dynamic-Bone-Demo

    to use just place the 2 dll files inside your Assets/Plugins folder (this is what I do)

    There are still 1 known bug(s).
    1) physics calculation glitch that causes jittering

    temp solution: set Inert to > 0. This makes if so the player's position is ignored in calculations.

    -Update V0.8.1.3: Dynamic Bones calculations now work however, there seems to be an small issue with initial positions/rotations. I will be working on that next.

    -Update V0.8.2: Fixed the previous issue. turns out I forgot to switch from AnimatedLocalToRoot to AnimatedLocalToWorld. The Core functionality should work now, please provide feedback and issues.

    -Update V0.8.2.1: - Fixed the exclusions calculations. however I think the unexpected result of V0.8.2 should probably be a feature.
     
    Last edited: Nov 2, 2021
    andreiagmu likes this.
  2. NT_Ninetails

    NT_Ninetails

    Joined:
    Jan 21, 2018
    Posts:
    195
    just released V0.8.1.1...I forgot to re-add the rotations after I was finished testing.

    I also tried to solve the issue of calculations with a rotated axis but converting an AnimatedLocalToWorld to an AnimatedLocalToRoot is really.....dumb....
     
    Last edited: Oct 11, 2021
    andreiagmu likes this.
  3. andreiagmu

    andreiagmu

    Joined:
    Feb 20, 2014
    Posts:
    175
    @NT_Ninetails I tried adding a Dynamic Bone to my character, but it didn't seem to work yet.
    I'm getting some Burst errors that may be impeding the system to run correctly, what version of Burst are you using? I'm using Burst 1.5.6, Unity 2020.3.19f.
    Code (CSharp):
    1. (0,0): Burst error BC1028: Creating a managed array `System.String[]` is not supported
    2.  
    3. at DOTSDynamicBone.DOTSDynamicBone.ConvertLocalToWorldToLocalToRoot(DOTSDynamicBone.DOTSDynamicBone* this, ref Unity.Entities.DynamicBuffer`1<DOTSDynamicBone.Particle> m_Particles, ref Unity.Entities.DynamicBuffer`1<Unity.Animation.AnimatedLocalToRoot> altr, ref Unity.Entities.DynamicBuffer`1<Unity.Animation.AnimatedLocalToWorld> altw, int start, int end)
    4. at DOTSDynamicBone.DOTSDynamicBone.UpdateDynamicBones(DOTSDynamicBone.DOTSDynamicBone* this, float t, Unity.Core.TimeData timeData, Unity.Transforms.LocalToWorld* coreLTW, Unity.Entities.DynamicBuffer`1<Unity.Animation.AnimatedLocalToWorld>* altw, ref Unity.Entities.DynamicBuffer`1<Unity.Animation.AnimatedLocalToRoot> altr, ref Unity.Entities.DynamicBuffer`1<DOTSDynamicBone.Particle> m_Particles, int start, int end)
    5. at DOTSDynamicBone.DOTSDynamicBone.mLateUpdate(DOTSDynamicBone.DOTSDynamicBone* this, ref Unity.Entities.DynamicBuffer`1<DOTSDynamicBone.Particle> m_Particles, Unity.Core.TimeData timeData, int start, int end, Unity.Transforms.LocalToWorld* coreLTW, Unity.Entities.DynamicBuffer`1<Unity.Animation.AnimatedLocalToWorld>* altw, Unity.Entities.DynamicBuffer`1<Unity.Animation.AnimatedLocalToRoot>* altr)
    6. at DOTSDynamicBone.DynamicBoneLateUpdateSystem.DOTSDynamicBone.<>c__DisplayClass_OnUpdate_LambdaJob0.OriginalLambdaBody(DOTSDynamicBone.DynamicBoneLateUpdateSystem.DOTSDynamicBone.<>c__DisplayClass_OnUpdate_LambdaJob0* this, ref Unity.Transforms.LocalToWorld coreLTW, ref DOTSDynamicBone.DOTSDynamicBone bone, ref Unity.Entities.DynamicBuffer`1<DOTSDynamicBone.Particle> particles, ref Unity.Entities.DynamicBuffer`1<Unity.Animation.AnimatedLocalToRoot> altr, ref Unity.Entities.DynamicBuffer`1<Unity.Animation.AnimatedLocalToWorld> altw)
    7. at DOTSDynamicBone.DynamicBoneLateUpdateSystem.DOTSDynamicBone.<>c__DisplayClass_OnUpdate_LambdaJob0.IterateEntities(DOTSDynamicBone.DynamicBoneLateUpdateSystem.DOTSDynamicBone.<>c__DisplayClass_OnUpdate_LambdaJob0* this, ref Unity.Entities.ArchetypeChunk chunk, ref DOTSDynamicBone.DynamicBoneLateUpdateSystem.DOTSDynamicBone.<>c__DisplayClass_OnUpdate_LambdaJob0.LambdaParameterValueProviders.Runtimes runtimes)
    8. at DOTSDynamicBone.DynamicBoneLateUpdateSystem.DOTSDynamicBone.<>c__DisplayClass_OnUpdate_LambdaJob0.Execute(DOTSDynamicBone.DynamicBoneLateUpdateSystem.DOTSDynamicBone.<>c__DisplayClass_OnUpdate_LambdaJob0* this, Unity.Entities.ArchetypeChunk* chunk, int chunkIndex, int firstEntityIndex)
    9. at Unity.Entities.JobChunkExtensions.JobChunkProducer`1<DOTSDynamicBone.DynamicBoneLateUpdateSystem.DOTSDynamicBone.<>c__DisplayClass_OnUpdate_LambdaJob0>.ExecuteInternal(ref Unity.Entities.JobChunkExtensions.JobChunkWrapper`1<DOTSDynamicBone.DynamicBoneLateUpdateSystem.DOTSDynamicBone.<>c__DisplayClass_OnUpdate_LambdaJob0> jobWrapper, System.IntPtr bufferRangePatchData, ref Unity.Jobs.LowLevel.Unsafe.JobRanges ranges, int jobIndex) (at C:\Projetos\_Unity\nekosuki\Library\PackageCache\com.unity.entities@0.17.0-preview.42\Unity.Entities\IJobChunk.cs:386)
    10. at Unity.Entities.JobChunkExtensions.JobChunkProducer`1<DOTSDynamicBone.DynamicBoneLateUpdateSystem.DOTSDynamicBone.<>c__DisplayClass_OnUpdate_LambdaJob0>.Execute(ref Unity.Entities.JobChunkExtensions.JobChunkWrapper`1<DOTSDynamicBone.DynamicBoneLateUpdateSystem.DOTSDynamicBone.<>c__DisplayClass_OnUpdate_LambdaJob0> jobWrapper, System.IntPtr additionalPtr, System.IntPtr bufferRangePatchData, ref Unity.Jobs.LowLevel.Unsafe.JobRanges ranges, int jobIndex) (at C:\Projetos\_Unity\nekosuki\Library\PackageCache\com.unity.entities@0.17.0-preview.42\Unity.Entities\IJobChunk.cs:353)
    11.  
    12.  
    13. While compiling job: System.Void Unity.Entities.JobChunkExtensions/JobChunkProducer`1<DOTSDynamicBone.DynamicBoneLateUpdateSystem/DOTSDynamicBone.<>c__DisplayClass_OnUpdate_LambdaJob0>::Execute(Unity.Entities.JobChunkExtensions/JobChunkWrapper`1<T>&,System.IntPtr,System.IntPtr,Unity.Jobs.LowLevel.Unsafe.JobRanges&,System.Int32)
    14. at <empty>:line 0
     
  4. andreiagmu

    andreiagmu

    Joined:
    Feb 20, 2014
    Posts:
    175
    Ok, it didn't seem to work before because I tried to add the DOTSDynamicBonesComponent to a specific bone of my rig (character tail bone). So, I added it to the main gameobject with the RigComponent instead, then the system worked.

    But the system is twisting the tail bones in a weird way. Before, I used standard DynamicBone in the tail bone, so now I copied the same parameters from the original DynamicBone to the DOTSDynamicBone, but the results aren't the same. (I know some parameters aren't working yet, but still, it seems like a bug)

    Also, can those Debug.Logs from ConvertLocalToWorldToLocalToRoot be disabled? (they're killing my performance :confused:) Or are those enabled on purpose for the demo?

    capture_20211003_191526_001.png

    capture_20211003_191846_002.png
     
  5. andreiagmu

    andreiagmu

    Joined:
    Feb 20, 2014
    Posts:
    175
    @NT_Ninetails Another odd thing is, even when all the DynamicBone parameters are zeroed out, the affected bones still keep moving/shaking wildly. I guess when the parameters are all 0, it shouldn't even try to move the bones, right? Is that a bug?

    EDIT: Actually, that also happens with standard (non-DOTS) Dynamic Bone, so I guess that's not a bug.
    I also think it would be useful to add an option to enable/disable dynamic physics on each DynamicBone element.
     
    Last edited: Oct 4, 2021
  6. NT_Ninetails

    NT_Ninetails

    Joined:
    Jan 21, 2018
    Posts:
    195
    Oh, my bad about the debugging. I can disable that and update the files. I'll also clean up some extra calculations...I went a little overboard on trying to fix the origin rotation issue...

    Also for the twisting, could you show/tell me how the bones are setup/oriented so I can try to replicate it?
     
    andreiagmu likes this.
  7. andreiagmu

    andreiagmu

    Joined:
    Feb 20, 2014
    Posts:
    175
    Great, thanks for the support! I'll send you my character .fbx in a DM. :)
     
  8. NT_Ninetails

    NT_Ninetails

    Joined:
    Jan 21, 2018
    Posts:
    195
    As of now I do believe I got the bone translation working properly. There was a hidden calculation during the physics calculation I overlooked which always made the bones in a specific orientation no matter what the Root bone's rotation was i.e. the root was rotated 90 deg on the X axis but the positions acted like there was no rotation. After extensive digging and searching I came across vital information:

    "Unity ECS LocalToParent is not updated the same way Transforms are and must be accounted for"

    So I had to change 1 line

    Code (CSharp):
    1.  Matrix4x4 m0 = TransformsExtensions.GetTRSMatrix(
    2.                         p0.m_Transform.localPosition,
    3.                         p0.m_Transform.localRotation,
    4.                         p0.m_Transform.localScale);
    5.                  
    into

    Code (CSharp):
    1.  Matrix4x4 m0 = TransformsExtensions.GetTRSMatrix(
    2.                         p0.m_Transform.localPosition,
    3.                 math.mul(p0.m_Transform.localRotation, m_Core.rotation),
    4.                         p0.m_Transform.localScale);
    5.                  
    idk maybe it does update properly...I'll do more test after I get rotation working...

    Working on rotation now...
     
    andreiagmu likes this.
  9. NT_Ninetails

    NT_Ninetails

    Joined:
    Jan 21, 2018
    Posts:
    195
    ooooooohhhhhhhhhhhhhhhh boyyyyyyyyyyyyyyyy, Got rotation working this morning, gonna clean up the code and post a new demo version soon. I will also perform other tests to make sure everything is in order.

    I can now delete 200+ lines of test code and commented failed attempts....
     
    Last edited: Oct 11, 2021
    NotaNaN and andreiagmu like this.
  10. NT_Ninetails

    NT_Ninetails

    Joined:
    Jan 21, 2018
    Posts:
    195
    cleaned up the code so now the system runs using Entities.ForEach().ScheduleParallel().
    Here's a screenshot with 250 entities running the system (pls ignore my camera system, its not done)
    upload_2021-10-11_14-48-12.png
     
    andreiagmu likes this.
  11. andreiagmu

    andreiagmu

    Joined:
    Feb 20, 2014
    Posts:
    175
    Ok, I just tested v0.8.2, the issues I had before are now gone (Debug.Log killing performance, weird bones rotations, etc.)
    The DynamicBone features that your system got so far are working great, with nice performance too!
    Thank you so much for taking your time to port DynamicBone to DOTS :D

    Hope it doesn't take too long to implement the other features, I'm particularly waiting for the DynamicBoneColliders and the Distrib curves, as I used them before in my character.
    But of course, you can take your time with those, as the core functionality is working in DOTS and that's already awesome :)

    I sure hope that there isn't anything worse than the rotations and calculations issues next, I hope that there aren't any bigger obstacles to this system :eek:

    More feedback:
    - I'd add a bool to each DynamicBone element (or something like "Update Mode -> None"?), to enable/disable that bone's dynamic physics processing. Sometimes I may add an element to the list of DynamicBones, then I copy the component to another character, but I may want to disable certain elements (without removing them from the list).

    - Your current system only works when the DOTSDynamicBonesComponent is attached to the same gameobject as the RigComponent, but standard DynamicBone used to also work even when it was attached to other gameobjects.
    Maybe the user could set the correct RigComponent in the bone's parameters and it should work in theory, but in the current version, it doesn't work.

    I ask about this feature because I want to support a more modular DynamicBones organization, where each (root) gameobject of a dynamic part of my character (clothes, hair, tail, etc.) has its own DynamicBone list. In that way, I could prepare prefabs of clothes/hair/tail, etc., and easily swap them in my characters, without having to mess with the DynamicBones list in the RigComponent gameobject (so I don't have to manually add/remove elements every time I change some part).

    I don't know if that's more or less performant than having only a single DOTSDynamicBonesComponent in the RigComponent gameobject, though.
     
    Last edited: Oct 12, 2021
    NT_Ninetails likes this.
  12. NT_Ninetails

    NT_Ninetails

    Joined:
    Jan 21, 2018
    Posts:
    195
    Thank you for the feedback, I can answer these questions and provide possible solutions for each.

    -
    As far as I can tell, the core functionality of the system works. So anything else added will most likely be a feature or settings (and there are a lot of possible settings I can add)

    -
    This is actually easy to implement however, I can't say what the results will be due to calculations taking the parent entity in mind. So I you have a 3 bone system and the middle bone has no calculations on it then the last bone may look weird. But sure, I should be able to add this with little issue.

    It would work but there might be a downgrade in performance due to data fetching (At least using a regualr Entities.ForEach system). The current system uses this to determine when to run the system.
    Code (CSharp):
    1.  Entities
    2.              
    3.                     .WithBurst()
    4.                     .ForEach((
    5.                         ref DynamicBuffer<DOTSDynamicBone_BufferElement> bones,
    6.                         ref DynamicBuffer<Particle> particles,
    7.                         ref DynamicBuffer<Unity.Animation.AnimatedLocalToRoot> altr,
    8.                         ref LocalToWorld coreLTW,
    9.                         in DynamicBuffer<Unity.Animation.AnimatedLocalToWorld> altw) =>
    10.                         {
    11. ...
    12.                         })
    13.                     .ScheduleParallel();
    The
    Code (csharp):
    1. Unity.Animation.AnimatedLocalToRoot
    and
    Code (csharp):
    1. Unity.Animation.LocalToWorld
    data is stored on the root entity. In order to simplify the data structure and job structure we add 2 DynamicBuffers which hold all the information regarding the dynamic bones (calculations are done within the job and are Burst Compatible). In order to have the data stored on the bone entity itself it would need to acquire the LocalToWorld,AnimatedLocalToRoot, and the AnimatedLocalToWorld of the root enity. Using Entities.ForEach I only know 1 ways of doing this, using a ComponentDataFromEntity (which is slow) but I could maybe use some sort of IJobEntityBatch (I could take a look at this as there might not be a performance hit). Also with the bone entities having the data stored on them causes more allocation for DynamicBuffers, but I'm not 100% sure how this will affect performance though because I do know that I would be able to remove 2 ints from
    Code (csharp):
    1. DOTSDynamicBone_BufferElement
    which would save some memory but I don't know it that outweighs the accessing time.

    So in short, yeah its possible but most likely there may be a performance hit which may increase linearly which each dynamic bone....maybe. But I'll look into it

    Just remember, I can't use references so I really have to play around with which data I need, how it's represented (to save space in the structs), and how to pass data efficiently to different places.

    At least, this is my though process when working in DOTS.

    Thanks for the feedback :D
     
    Last edited: Oct 12, 2021
    andreiagmu likes this.
  13. andreiagmu

    andreiagmu

    Joined:
    Feb 20, 2014
    Posts:
    175
    @NT_Ninetails Thanks for the detailed explanations!

    My feature request to make the system work outside of the root gameobject isn't essential, I guess it adds a bit more complexity to the system than I thought. Anyway, I can work with using the system on the root gameobject only (also to ensure better performance), but I really appreciate the info!

    About my other feature request, just to clarify (as it's maybe a bit confusing to explain), I meant in case I have in my DOTSDynamicBonesComponent the following elements in the Bones list: (I assign each part's root bone to the element)
    - Tail
    - Hair (back)
    - Skirt
    - BreastL
    - BreastR

    What I meant is that, depending on the character, I may want to, for example, disable both Breasts' dynamic physics, or disable the tail dynamic physics, etc.
    Would that only be possible by deleting the elements from the Bones list? Or does an enable/disable toggle (on each element's data) could be implemented for that?
     
  14. NT_Ninetails

    NT_Ninetails

    Joined:
    Jan 21, 2018
    Posts:
    195
    Oh so you mean like attach the DynamicBone to another GameObject/Entity entirely? This is possible but would have the same concerns as mentioned before, but yeah, it's possible. I can take a look into it.

    Do you mean the Exclusions dropdown? I forgot to mention it but the Exclusion dropdown does work but it's not 100% functional. Like those entities in the exclusions are ignored but there's an issue with children and parents. Since the main system is working I can look into this next.
     
  15. andreiagmu

    andreiagmu

    Joined:
    Feb 20, 2014
    Posts:
    175
    No, the feature I ask for is different/independent of the Exclusions dropdown.
    I mean like, if I want to disable one of the DynamicBone configurations I set up, it seems there's currently no way to do that without deleting the Element from the main list (and then losing the parameters that I set up to that DynamicBone configuration, curves, exclusions, etc.)

    For example, imagine that these 4 elements in the list consist of DynamicBone configurations for my character's Tail (Element 0), Skirt (Element 1), and Left/Right Breast (Elements 2 and 3)
    Each element would have its parameters, its own exclusions set up, etc.

    capture_20211012_195702_003.png

    If I wanted to disable the breasts, it seems I'd have to delete Element 2 and Element 3 from the list. I wanted a way to keep those elements in the list, but with a toggle on each element that defines if it's going to have DynamicBone physics applied or not.

    I may even want to enable/disable elements from the list at runtime, for example during cutscenes with special animations for the tail, etc.


    capture_20211012_195720_004.png
    My suggestion is that each element could have another bool above UpdateLocalToWorldTransforms, "Enable Dynamic Bone", something like that.
    Or in Update Mode, a new option "None", which would disable dynamic physics for that bone configuration.
     
  16. andreiagmu

    andreiagmu

    Joined:
    Feb 20, 2014
    Posts:
    175
    Yeah, it could be another GameObject/Entity. But what I mostly meant to do is attaching DynamicBone components to prefabs/GameObjects that would be children of the root GameObject with the RigComponent.
    Then those DynamicBones (in child objects) could point to the root object's RigComponent and get its entity, something like that.

    This feature worked in standard non-DOTS DynamicBone asset, but I guess the Entity conversion workflow would make implementing that feature a bit more complex now?
     
  17. NT_Ninetails

    NT_Ninetails

    Joined:
    Jan 21, 2018
    Posts:
    195
    Oh, yeah I don't see a problem with that. Also you are free to edit the DynamicBuffer<Particles> and DynamicBuffer<DOTSDynamicBone_BufferElement> during runtime.....I should make a documentation....I'll get started on that after I finish up some other things
     
    andreiagmu likes this.
  18. NT_Ninetails

    NT_Ninetails

    Joined:
    Jan 21, 2018
    Posts:
    195
    Yeah, that's possible. like you said, it will become a more complex however only in accessing the RigComponentData. I could treat that as a special case and make a new component from that since it requires different methods of access certain data efficently.
     
    andreiagmu likes this.
  19. NT_Ninetails

    NT_Ninetails

    Joined:
    Jan 21, 2018
    Posts:
    195
    So I fixed exclusions by setting the excluded bones and thier children's stiffness to 1, elasticity to 0 and damping to 0.
    I will uploading the changes soon. V0.8.2.1
     
    andreiagmu likes this.
  20. NT_Ninetails

    NT_Ninetails

    Joined:
    Jan 21, 2018
    Posts:
    195
    Update: I believe I have successfully got DOTS Dynamic Bones working fully with the exception of the DynamicBonePlaneCollider (The normal DynamicBoneCollider works). As far as colliders go I want to use the DOTS Physics system for collision since it allows for more dynamic interactions in a DOTS environment. The original system is pretty closed looped (you have to manually drag in the colliders that affect the bones for a particular DynamicBone) and I think using DOTS Physics to do queries on all bodies in a scene will look and feel nice as well. As far as the demo is concerned, I believe it is a fine stable version of the core concepts of DynamicBone and runs efficiently with burst, and as such, will be a Demo of DOTSDynamicBone.

    Future Plans: After creating some samples and a tutorial video I will initially put this on the AssetStore in beta. All new or improved features will be applied to the store version of DOTSDynamicBone. Any bug fixes or efficency improvements will be applied to both the AssetStore and Demo version of DOTSDynamicBone.

    As for the tutorials and documentation....expect them to be longish because the original system was a little difficult to get a good understanding in but DOTS make it a whole lot more complicated. ForExample:

    In the current version of the system there is a DOTSDynamicBone Component and a IndependantDynamicBone Component. The only difference between them is where they get placed and 1 line in the Entities.ForEach systems.

    DOTSDynamicBone MUST be used placed in the same component as the RigComponent. However IndependantDOTSDyanmicBone can be placed on any entity and will work as just as fine as long as you reference the right Components for conversion. Here's the line of code if your interested (Note the Entities.ForEach is also slightly altered)
    Code (CSharp):
    1. //GetLTW = ComponentDataFromEntity<LocalToWorld>();
    2. LocalToWorld coreLTW = GetLTW[bone.m_RigComponentEntity];
    3.  
     
    andreiagmu likes this.
  21. NT_Ninetails

    NT_Ninetails

    Joined:
    Jan 21, 2018
    Posts:
    195
    Update: So I have been working on this when I have time and so far have implemented just about everything. Currently working on creating a Component that lets you edit the bones in the editor during runtime. Just wanted to let you know I'm still working on it
     
    andreiagmu likes this.
  22. NT_Ninetails

    NT_Ninetails

    Joined:
    Jan 21, 2018
    Posts:
    195
    Update: So while working on getting ECS PhysicsCollider to work I realized I would need to do some restructuring of the systems. For example: I currently use AnimatedLocalToWorld which is generated from data like AnimationData and AnimatedLocalToRoot however, since they aren't tied to the TransformSystems like LocalToWorld, Translation, Rotation, etc, then PhysicsColliders have no affect on them. So in order to have PhysicsColliders affect the DOTSDynamicBones I would have to bridge the gap. I can try to switch over to using LocalToWorld but there will be a slight performace downgrade due to me having to get all the LocalToWorld values. For now I'll put that on hold and work on making the tutorial and doc for the release of V0.9.5.2. This version will be available in the asset store when everything is done.
     
    andreiagmu likes this.
  23. NT_Ninetails

    NT_Ninetails

    Joined:
    Jan 21, 2018
    Posts:
    195
    I recorded a quick tutorial of the system (needs editing) and I'm working on the documentation for the system
    upload_2021-10-28_12-43-6.png
     
    andreiagmu likes this.
  24. NT_Ninetails

    NT_Ninetails

    Joined:
    Jan 21, 2018
    Posts:
    195
    Update: Finished the Scripting API, working on the Manual now
     
    andreiagmu likes this.
  25. NT_Ninetails

    NT_Ninetails

    Joined:
    Jan 21, 2018
    Posts:
    195
  26. NT_Ninetails

    NT_Ninetails

    Joined:
    Jan 21, 2018
    Posts:
    195
    andreiagmu likes this.