Search Unity

Inconsistencies with Translations in IK implementation

Discussion in 'Entity Component System' started by BigRookGames, Mar 17, 2021.

  1. BigRookGames

    BigRookGames

    Joined:
    Nov 24, 2014
    Posts:
    330
    I am having a few issues with a system that is acting as a basic IK solver. To test, I have setup the same code on a gameobject as well as on a group of entities.

    Initially, it seems to work the same between both systems, the IK "Leg" going to the IK target in the same manner with little to no difference in calculated values. But after the target moves, the ECS-based solver seems to break away from expected calculations and shows undesired results:
    (left is ECS, right is GameObject)


    Although the equations being used to solve the simple IK systems are identical between the traditional and the ECS system (both using Unity.Mathematics), there is a big difference in how the data is handled.

    As you know, in the ECS System the translation values are not calculated until end of frame (In other words, if Rotation was assigned a new value within a system, the related variables such as LocalToWorld and Position of child objects would not be updated within that same system, but in the TransformSystemGroup instead)

    To account for this, I am calculating the positions and rotations within the IK system and using those values to solve the IK calculations. I have tested these calculations quite a few times and I am pretty confident they are not the issue.

    That being said, the problem seems to happen after a few frames to the point where the system goes haywire. I don't know if it is a problem others have faced and solved, but I'm looking for some guidance on how to proceed troubleshooting with this issue, and if theoretically, the values should be correct.

    For the ECS System I am using the LTW values (Position and Rotation) and the system is running in LateSimulationSystemGroup.
    I am using the EndSimulationEntityCommandBufferSystem and assigning rotation to the IK pivot points (no other variables being assigned)

    Should I be assigning the LTW with updated values instead? I don't have anything else updating the position, so I wouldn't expect the following to be a problem, but could it be unsynced if I assign the Rotation and another system in the next cycle uses the LTW to update the values since I am updating the IK after the position and rotation calculations are made to the entity?

    Any info might help, and I really appreciate any thought into this. I've been facing this issue for quite some time now.

    Thanks!
     
  2. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,759
    Does this not mean you are assigning translation/rotation after the LTW component is updated therefore LTW isn't going to be updated till the end of the next frame?

    I feel like you should
    a) be updating before the TransformSystemGroup
    b) directly modifying Translation/Rotation values and not using an entity command buffer
     
    BigRookGames likes this.
  3. BigRookGames

    BigRookGames

    Joined:
    Nov 24, 2014
    Posts:
    330
    @tertle Yeah, I have been updating after due to the fact that other systems are making modifications to the rotation and position and I am using the LTW for the calculations in the IK solver. I assume that the LTW is not updated correctly until the LTW is recalculated for that frame.

    You may be right about updating before TransformSystemGroup and not using a buffer as being a viable solution. I prefer to still update after Transform system group, as a lot of the systems that alter the position and rotation need to be calculated.

    I decided to rewrite it using LTW but instead of writing to the rotation/position I write directly to LTW and it now works as I have been expecting it to, so I will carry forward with this solution.

    The only downside is that I had to write calculations for every single child bone for each movement in the chain with adjusting position and rotation in parent entities because it is using world coordinates for LTW. Before I was only calculating the change for each bone itself because the Transform system would recalculate the LTW later, but just an extra couple of steps.

    One weird thing though.. I noticed that in a chain of parent-child entities, if I adjust the highest parent in the chain that contains a renderer, the child entities move with the parent all the way down the chain, but if any other bone is moved solely by itself, it does not affect other child entities. I found this very strange because the parent that rotated the children was a child itself, it just didn't have a parent with a renderer.