0 votes
asked in Grounder by

Hi there, the foot.position.y - root.position.y does work to a degree, but that's the equivalent of animating a float in the animation as i can't know whether the foot is actually touching the ground.

According to your documentation the grounder script already calculates the distance between the feet and the ground (y1 and y2) and while i could do it on my own with a raycast, the results will differ if the grounder is set to use "Simple" or "Best" quality settings, which can cause wrong results when a foot is next to an edge.

Looking at the code, i can see that indeed that is the case: SetFootToPlane(capsuleHit.normal, capsuleHit.point, heelHit.point); can be found in the grounder class, which will then be used by the GroundingLeg class.

I could extend or edit the class in order to gain access to those values, but that's not an ideal solution as updates could cause problems.

Unless there is a way to read those values already that i'm not seeing, it'd be amazing if you could add a way to see exactly how far away the foot is from the ground (which should hopefully be easy to do as the calculations are already there, unless i'm mistaken) and/or alternatively a way to pin the foot's Z/X axis when it's within a max height from the ground (which would be neat especially if the ik solver is set to work in any direction, such as spherical surfaces).

Pinning the legs can be useful to remove unwanted foot sliding from an animation and for mechanical or spider characters.

Having accurate access to the foot's distance from the ground may also be useful when adding step sounds or effects (more efficient than a collider, more accurate and efficient than a single raycast).

Thank you for your help. :)

p.s.

The email notifications aren't being sent, i checked both inbox and spam folders but there's nothing from the last 2 times you replied, while i did receive the notification a few months ago after my first question.

1 Answer

0 votes
answered by (16.3k points)
 
Best answer
Hey, sorry for the delay.

Thinking about it some more, I don't think you can use the raycast info from Grounder to get foot height from ground accurately. The reason is that there are also the toes. And there are situations when the foot bone is really quite high, but it is rotated down and the toes are still reaching the ground. The foot bone is also not beneath the foot, but where the ankle joint is. So probably the best way to get foot planting info from height would be to parent a new gameobject to the toe bone and place it beneath the shoe, then read it's Y in LateUpdate. I'm sorry, I don't currently have an out of the box solution for that kind of stuff.

About the notifications, I'm aware of that, tried to fix it, but seems to be some kind of a problem with Question2Answer, I'm looking into ways to implement another better solution.

Best,

Pärtel
commented by

I see what you mean, altho i wouldn't see that as an issue necessarily: if you're moving around and you're only touching the ground with the toes some sliding is expected.

However, if the point of the foot below the ankle is within an offset from the ground, then i'd expect the foot to not move any further.

That's how, unless i'm mistaken, the grounder script works already: it moves the ankle joint to the ground with an offset. If that's the case then it should be precise enough for all/most applications where you'd want to pin the feet.

The main reason i'd want to read the grounder's capsule cast specifically is to avoid situations where the grounder thinks a foot is on a platform while my cast says otherwise (or vice versa) as that'd cause unwanted results.

Or in other words, i want to know where the grounder script wants to put the feet, if that doesn't match with the feet shape then i'd be having issues regardless of whether i wanted to pin or not.

Also, by pinning i only mean pinning on the X and Z axis, meaning the grounder script remains free to adjust the feet height without impairment.

That said, adding Debug.DrawRay(heelHitPoint, new Vector3(0,1,0), Color.green); to the GroundingLeg class shows exactly what i'm looking for (it looks in the wrong place if i'm also pinning and moving the character, but i suspect it's caused by the update order).

I could edit or extend that class but that will/may cause trouble with future updates. If you were to sneak a way to read that value in the next update i could then add the pinning myself fairly easily. :)

commented by (16.3k points)
Hey,

I'll change private RaycastHit heelhit; to public RaycastHit heelHit { get; private set; } in GroundingLeg.cs does that work for you?

You should be able to use gerounder.solver.legs[i].isGrounded to see if the foot is on a platform or not.

Best,

Pärtel
commented by

I've been testing with that a bit and reading capsuleHit would be what i'm looking for over heelHit (that way if i move a platform away from the edge of the feet the raycast will still point to the platform, unlike heelHit).

When not using the "best" quality then using heelHit is perfect (since capsuleHit doesn't exist).

So ideally a public GetHitPoint function that returns either capsuleHit when using "best" or heelHit otherwise would be ideal.

The only issue left is that the raycast always comes from the animation's foot position rather than the real foot position. (the cyan ray is heelHit.point, the magenta ray is capsuleHit.point, i'm not sure why the capsule cast hits in front but it works correctly either way)

Which means the values aren't correct when IK pinning the feet, which prevents the grounder script from grounding the feet correctly (if they're pinned on top of a platform but the character moves beyond it the script will think they're off the platform and either not ground them at all or move them inside the platform).

I tried changing the script execution order but that didn't help. Keep in mind this issue occurs whenever using IK targets with the feet, not just in my specific case.

That can be fixed by overloading GetRaycastHit and GetCapsuleHit to also accept a transform/vector3 that will be used instead of the heel transform (which should be easy).

Having GetHitPoint use those new functions would be enough for my purposes (as i can manually fix the height of the feet on my own).

So it'd look like this: public raycastHit GetHitPoint (Vector3 position), where position is the position of the foot.

To fix that issue for everyone who's setting IK targets to a character's legs, then you'd need some way to switch between either type of GetRaycastHit and GetCapsuleHit depending on whether a limb's IKweight is 0 or greater than 0 (which is more difficult).

Or at least that's the solution i came up with, i'm not sure about the last point (as there may be issues when not following the animation's feet positions) but otherwise it should be good.

Is that reasonable?

commented by (16.3k points)

Hey,

Please import this GroundingLeg.cs.

I added public void SetFootPosition(), which you can use to override the animated position of the foot. You can use it like this:

public GrounderFBBIK grounder;

    void Start()

    {

        grounder.OnPreGrounder += OnPreGrounder;

    }

    void OnPreGrounder()

    {

        grounder.solver.legs[0].SetFootPosition(plantedLeftFootPosition);

    }

Cheers,

Pärtel

commented by
That worked, i really like your solution.

Thank you for your help, i greatly appreciate it. :)

Welcome to RootMotion Q&A, where you can ask questions and receive answers from the developer of Final IK and PuppetMaster and other members of the community.

Post as a guest, create an account or login via Facebook.

Please use the correct category when you post your questions.

...