Oh, hmm…
I’ve never been good with IK, sorry…
I wouldn’t use the surface normal since this is prone to glitches if your foot is over multiple surfaces. I’d fire a downwards ray at the toes position, then just get the angle between the heel & wherever that hits.
In case anyone gets stuck where I did, here’s some more info from WhoBloxedWho
I have been messing with this for a while, but I can’t seem to get it to work…
https://gyazo.com/d53e7776b913948b62ba056fac56e80c
local fromAxisAngle = CFrame.fromAxisAngle
local acos = math.acos
local max = math.max
local min = math.min
local cfNew = CFrame.new
local forwardV3 = Vector3.new(0, 0, -1)
local pi = math.pi
local cfAngles = CFrame.Angles
wait(2)
local upperTorso = workspace.ViewModel.UpperTorso
local shoulderMotor = workspace.ViewModel.RightUpperArm.RightShoulder
local elbowMotor = workspace.ViewModel.RightLowerArm.RightElbow
local lowerC0 = elbowMotor.C0
-- OriginCF is the CFrame of the shoulder, direction is important
-- TargetPos is the Vector3 position we're reaching to
-- l1 and l2 are both numbers that represent the length of the segments of the arm
local function solveIK(originCF, targetPos, l1, l2)
-- put our position into local space in regards to the originCF
local localized = originCF:pointToObjectSpace(targetPos)
-- this breaks if OriginCF and targetPos are at the same position
local localizedUnit = localized.unit
-- the distance to from originCF.p to targetPos
local l3 = localized.magnitude
-- build an axis of rotation for rolling the arm
-- forwardV3 is Vector3.new(0, 0, -1)
local axis = forwardV3:Cross(localizedUnit)
-- find the angle to rotate our plane at
local angle = acos(-localizedUnit.Z)
-- create a rotated plane to base the angles off of
local planeCF = originCF * fromAxisAngle(axis, angle)
-- L3 is between the length of l1 and l2
-- return an offset plane so that one part reaches the goal and "folded" angles
if l3 < max(l2, l1) - min(l2, l1) then
return planeCF * cfNew(0, 0, max(l2, l1) - min(l2, l1) - l3), -pi/2, pi
-- l3 is greater than both arm lengths
-- return an offset plane so the arm reaches its goal and flat angles
elseif l3 > l1 + l2 then
return planeCF * cfNew(0, 0, l1 + l2 - l3), pi/2, 0
-- the lengths check out, do the law of cosines math and offset the plane to reach the targetPos
-- return the offset plane, and the 2 angles for our "arm"
else
local a1 = -acos((-(l2 * l2) + (l1 * l1) + (l3 * l3)) / (2 * l1 * l3))
local a2 = acos(((l2 * l2) - (l1 * l1) + (l3 * l3)) / (2 * l2 * l3))
return planeCF, a1 + pi/2, a2 - a1
end
end
-- simple demo for how its called
local TARGET_POS = Vector3.new(0, 3, 0)
local SHOULDER_C0_VALUE = CFrame.new(1, 0.4, 0)
game:GetService("RunService").RenderStepped:Connect(function()
--local shoulderCF = upperTorso.CFrame * shoulderMotor.C0
local shoulderCF = shoulderMotor.Part0.CFrame
local plane, shoulderAngle, elbowAngle = solveIK(shoulderCF, workspace.Front.Position, shoulderMotor.Part0.Size.Y, shoulderMotor.Part1.Size.Y)
shoulderMotor.C0 = upperTorso.CFrame:toObjectSpace(plane) * cfAngles(shoulderAngle, 0, 0)
elbowMotor.C0 = lowerC0 * cfAngles(elbowAngle, 0, 0)
end)
If you’re trying to keep the arm from moving a point past its length. @systack quoted @WhoBloxedWho Regarding this right before your post.
You will want to change this condition statement.
elseif l3 > l1 + l2 then
return planeCF * cfNew(0, 0, l1 + l2 - l3), pi/2, 0
To
elseif l3 > l1 + l2 then
return planeCF, math.pi/2, 0
I figured out how to keep it at a fixed point. However, if you look at the gif, the arm isn’t grabbing the block exactly how it should.
Could it possibly be the lengths in which the function is solving with (l1 and l2)? I’ve noticed instead of using the two values 0.515 and 1.1031
you are using both part’s Size.Y.
I am using the code provided by @LMH_Hutch. It works alright assuming that the joints are all lined up.
But they aren’t. I am cframing the hand to the weapon, and using the wrist position from the hand as the targetpoint, but the wrist position from the lower arm does not connect to it. Anyone have suggestions on how I can take attachments into account?
you could use attachments as target points just set the goal to Attachment.WorldPosition
That is what I am doing, but all of the other attachments in the parts that make up the arm are not lining up with the target point. The code assumes I am trying to line up the arm. I am not trying to line up the arm, but trying to line up the attachment in the arm.
Oh so you are using attachments instead of motor6ds ? If then even i tried it and it kept glitching out