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

Question AimConstraintNode with entity as a target

Discussion in 'DOTS Animation' started by xseagullx, Mar 1, 2022.

  1. xseagullx

    xseagullx

    Joined:
    Nov 7, 2019
    Posts:
    24
    Can someone please share a simple code that will be setting AimConstraintNode's
    SourcePositions based on given entity's position?

    The fact that it's an array, is making it a little hard for me to understand how the code should look.
    I found an example in Unity.Animation.Samples/Constraints/ConstraintGraphComponent.cs but there we setup target position statically, so even if I later change it's position, it IK will not be updated.
     
  2. StickyKevin

    StickyKevin

    Joined:
    Jul 1, 2020
    Posts:
    22
    Every KernelPort can either have their data set with NodeSet.SetData() or be connected to with NodeSet.Connect().
    So it is possible to drive the AimConstraintNode's SourcePositions by index at runtime.
    You can specify the array element when setting up the connection by passing it as an extra parameter the end of the NodeSet.Connect().

    This would be how I would do it:
    Code (CSharp):
    1. NodeSet set = graphSystem.Set;
    2.  
    3. NodeHandle<ComponentNode> rigEntityNode = graphSystem.CreateNode(graphHandle, rigEntity);
    4. NodeHandle<ComponentNode> aimTargetEntityNode = graphSystem.CreateNode(graphHandle, aimTargetEntity);
    5.  
    6. NodeHandle<WorldToRootNode> worldToRootNode = graphSystem.CreateNode<WorldToRootNode>(graphHandle);
    7. set.Connect(rigEntityNode, worldToRootNode, WorldToRootNode.KernelPorts.Input, NodeSetAPI.ConnectionType.Feedback);
    8. set.Connect(rigEntityNode, worldToRootNode, WorldToRootNode.KernelPorts.RootEntity, NodeSetAPI.ConnectionType.Feedback);
    9. set.Connect(aimTargetEntityNode, worldToRootNode, WorldToRootNode.KernelPorts.LocalToWorldToRemap);
    10.  
    11. //Custom node which outputs the position (float3) from a transform (float4x4)
    12. NodeHandle<PositionFromTransformNode> positionFromTransformNode = graphSystem.CreateNode<PositionFromTransformNode>(graphHandle);
    13. set.Connect(worldToRootNode, WorldToRootNode.KernelPorts.Output, positionFromTransformNode, PositionFromTransformNode.KernelPorts.input);
    14.  
    15. NodeHandle<AimConstraintNode> aimConstraintNode = graphSystem.CreateNode<AimConstraintNode>(graphHandle);
    16. set.Connect(rigEntityNode, aimConstraintNode, AimConstraintNode.KernelPorts.Input, NodeSetAPI.ConnectionType.Feedback);
    17. set.Connect(positionFromTransformNode, PositionFromTransformNode.KernelPorts.output, aimConstraintNode, AimConstraintNode.KernelPorts.SourcePositions, 0);
    I have left out the SetData() and SendMessage() for simplicity.

    Unfortunately there is not a node that can output the root position of an entity. Hence I have created my own PositionFromTransformNode.
    You should be able to create a similar node that suit your needs. If you want to dive into creating custom nodes, I suggest you start with the FloatMulNode as a base example.

    Good luck!
     
    Last edited: Mar 1, 2022
    xseagullx likes this.
  3. xseagullx

    xseagullx

    Joined:
    Nov 7, 2019
    Posts:
    24
    Thank you, Kevin for the detailed response!

    After asking that question yesterday, I got to the same conclusion, that I'll need my node. Luckily it looks pretty straightforward!

    I think I also need to set the node's port size before connecting it, otherwise I'm getting OutOfBounds exception.

    I'll give it a try
     
    StickyKevin likes this.
  4. StickyKevin

    StickyKevin

    Joined:
    Jul 1, 2020
    Posts:
    22
    No problem Seagull!

    That is indeed required.
    You can set the port size with:
    Code (CSharp):
    1. NodeSet.SetPortArraySize(aimConstraintNode, AimConstraintNode.KernelPorts.SourcePositions, amount);