Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice
  4. Dismiss Notice

Question Clamp Distance / Radius - IK - Inverse Kinematic - Excavator simulator

Discussion in 'Scripting' started by ZeFirestarter, Aug 26, 2020.

  1. ZeFirestarter

    ZeFirestarter

    Joined:
    Oct 24, 2014
    Posts:
    17
    Hello Unity Forum, I need your help.

    First a little bit of CONTEXT:
    I am trying to achieve a little bit of simulation from the "pistons" of an excavator.
    I use the following model that consists of three pistons. I will refer to the pistons as "sets" from now on.
    BaggerNoHints.jpg

    Each set consists of three points (green, blue, red).
    The two smaller sets (the ones from the left) work very well with an asset called IKConstructor, but the bigger set (the one from the right) doesn't work with it even if it has the same relation of child/parent etc.

    ---------------------------------------------------------------------------------------------------------------

    GOAL:
    What I want to achieve is that the user inputs the desired length of the "piston" (distance from blue circle to red circle, the red line) and everything else adjusts accordingly.

    BaggerWithHints.jpg
    ----------------------------------------------------------------------------------------------------------------------
    MY DUMB SOLUTION:

    Given the desired length of the piston (equals the distance between blue and red circle), I calculate the "direction Vector" from the blue to the red circle and place the point at the distance given by the user.

    Code (CSharp):
    1.     public static Vector3 PointAlongDirection(Vector3 startingPoint, Vector3 pointTowards, float distance)
    2.     {
    3.         Vector3 heading = pointTowards - startingPoint;
    4.         Vector3 directionOnly = heading.normalized;
    5.         Vector3 pointAlongDirection = startingPoint + (directionOnly * distance);
    6.         return pointAlongDirection;
    7.     }
    This works fine, but the red circle needs to be constraint/clamped to have always the same distance to the green circle. Since the only movement allowed from the red circle is circular to the green circle, the distance between these two points is the clamp-radius.

    Code (CSharp):
    1.     public static Vector3 ClampMovementToRadius(Vector3 objectPosition, Vector3 circleCenter, float radius)
    2.     {
    3.         Vector3 offset = objectPosition - circleCenter;
    4.         offset = ClampToRadius(offset, radius);
    5.         return circleCenter + offset;
    6.     }
    7.     public static Vector3 ClampToRadius(Vector3 v, float radius) => v.normalized * radius;
    This also works, with a couple of LookAt() everything moves correctly.

    ----------------------------------------------------------------------------------------------

    Now to THE PROBLEM:

    I have to input a different desired value to get the real distance value I actually want.
    See this gif.

    If the desired value is bigger than the original value, the real value is smaller than the desired value.
    DesiredBiggerThanReal.jpg

    If the desired value is smaller than the original value, the real value is bigger than the desired value.
    DesiredSmallerThanReal.jpg

    I thought I could somehow figure out the difference, find some formula so the user can input a real value that would be converted to an adjusted "desired" value so at the end it real distance is what the user puts in, but for the life of me I can't figure it out. I thought maybe "reversing" the ClampToRadius, making that inverse, but I haven't been able to figure it out.

    The tricky thing is to move the distance and clamp it to the radius in the same update.

    ------------------------------------------------------------------------------------------------------------------

    If anyone could help in any way possible I would be more than thankful.

    Please also check out this thread.

    -----------------------------END OF MESSAGE---------------------------------------------------------
     
    Last edited: Aug 26, 2020
  2. gamemakerzone

    gamemakerzone

    Joined:
    Oct 11, 2018
    Posts:
    1
    So, at least you're the scripter. Thats gives hope. First of all you are using IKArm in a very unusual way. It was never designed to work in any constrained modes. Still I'm finding your idea just brilliant. Seriously, its very inventive!
    Thanx for your blueprints and animations. It is very clear what you are try to achieve. Judging by your gif applied I cannot say what's wrong exactly. Asset designed in such a way, that every component always computes a final transform during a single frame. It is very weird to see such "lerping" animation. I suspect you are messing with an update cycles. I dont believe it is a computationsl problem. To me it looks like something is rewrites transforms after IK update is finished. If you like, you can send me a full project so I can see both an hierarchy setup, and scripts.
    Most of all I want to see your object hierarchy, and update functions.

    P.S. Are you using physics within your construct? Rigidbodies?
     
    ZeFirestarter likes this.
  3. ZeFirestarter

    ZeFirestarter

    Joined:
    Oct 24, 2014
    Posts:
    17
    First I wanted to thank you for your answer and interest.
    We are currently not using any rigidbodies, for the moment we don't need physics.
    I have uploaded the project and will send you a PM with the link.

    I think the problem is, that two GameObjects have their IKAxis-target in the children of each other.
    The problem is that for the other piston the hierarchy is exactly the same and it still works.
    So why is the first one acting differently. The only difference I see is that in the first one, the green line (from green dot to red dot is way longer), and the distance between green and blue is much shorter than in the others.