im kinda confused for the github script to we paste it in a module script in replicatestorage?
yeah, just copy and paste the code onto a module script in replicated storage
Hey, thanks for the response.
I’m kind of stuck, I’m sorry I’ve never used IK before so I’m a bit lost. I’ve pasted the script into a module script in replicated storage. it doesn’t work even though im in r6.
In the github, do I also add in the 2 scripts in “How to use”?
thanks for your patience
Potentially as the IK position Y goes up, limit its Z more and more
Wow, this is neat. I’ll try experimenting with this later, see that I could do.
is it possbile to use this module
for custom limbs
for example an custom arm that is attached to the player
I did a similar approach to number 1.
I made so the client does the Ik and uses a unreliable remote to send the motor6d hips C0 to server and the server again applies the C0 to clients motor6d hips.
I’m not so sure with this approach as you said it could put stress to the server, So far it has worked fine at even 10 players in the server beyond 10 I have not tested.
It doesn’t seem to work with the default roblox animations, Im trying to maintain player walking animations but have the arm animations change. Here’s my code, any idea what’s going wrong?
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TweenService = game:GetService("TweenService")
local RunService = game:GetService("RunService")
local PlayerService = game:GetService("Players")
local Player = PlayerService.LocalPlayer
local Ik6 = require(ReplicatedStorage.Modules.R6IK)
Player.CharacterAppearanceLoaded:Connect(function()
local leftarm = Ik6.New(Player.Character)
RunService.Heartbeat:Connect(function()
leftarm:ArmIK("Right", workspace.IkTestPart.Position)
end)
end)
This module sadly does not support animation playing on the same limb as what the ik is using
I had the player play a looped animation with the arms down to completely disable any arm movement with roblox animations
how do you do that? Im pretty new to all this programming stuff…
Hey i saw this recently i dont know if your still looking or an answer but i got this to work
You can adjust it way more heres the rewritten code all i added was clamps
Attributes setup
code ()
local function SolveArmIK(originCFF, targetPos, l1, l2, C1Off, Side : "Left" | "Right")
-- build intial values for solving
local originCF
if Side == "Left" then
originCF = originCFF*CFrame.new(0,0,C1Off.X)
elseif Side == "Right" then
originCF = originCFF*CFrame.new(0,0,-C1Off.X)
end
local localized = originCF:pointToObjectSpace(targetPos)
local localizedUnit = localized.unit
local l3 = localized.magnitude
-- build a "rolled" planeCF for a more natural arm look
local axis = Vector3.new(0, 0, -1):Cross(localizedUnit)
local angle = math.acos(-localizedUnit.Z)
local planeCF = originCF * CFrame.fromAxisAngle(axis, angle)
-- case: point is to close, unreachable
-- return: push back planeCF so the "hand" still reaches, angles fully compressed
if l3 < math.max(l2, l1) - math.min(l2, l1) then
return planeCF * CFrame.new(0, 0, math.max(l2, l1) - math.min(l2, l1) - l3), -math.pi/2, math.pi
-- case: point is to far, unreachable
-- return: for forward planeCF so the "hand" still reaches, angles fully extended
elseif l3 > l1 + l2 then
return planeCF, math.pi/2, 0, l3
-- case: point is reachable
-- return: planeCF is fine, solve the angles of the triangle
else
local a1 = -math.acos((-(l2 * l2) + (l1 * l1) + (l3 * l3)) / (2 * l1 * l3))
local a2 = math.acos(((l2 * l2) - (l1 * l1) + (l3 * l3)) / (2 * l2 * l3))
return planeCF, a1 + math.pi/2, a2 - a1
end
end
local function SolveLegIK(originCFF, targetPos, l1, l2, C1Off)
-- build intial values for solving
local originCF = originCFF*CFrame.new(-C1Off.X,0,0)
local localized = originCF:pointToObjectSpace(targetPos)
local localizedUnit = localized.unit
local l3 = localized.magnitude
-- build a "rolled" planeCF for a more natural arm look
local axis = Vector3.new(0, 0, -1):Cross(-localizedUnit)
local angle = math.acos(-localizedUnit.Z)
local planeCF = originCF * CFrame.fromAxisAngle(axis, angle):Inverse()
-- case: point is to close, unreachable
-- return: push back planeCF so the "hand" still reaches, angles fully compressed
if l3 < math.max(l2, l1) - math.min(l2, l1) then
return planeCF * CFrame.new(0, 0, math.max(l2, l1) - math.min(l2, l1) - l3), -math.pi/2, math.pi
-- case: point is to far, unreachable
-- return: for forward planeCF so the "hand" still reaches, angles fully extended
elseif l3 > l1 + l2 then
return planeCF, math.pi/2, 0, l3
-- case: point is reachable
-- return: planeCF is fine, solve the angles of the triangle
else
local a1 = -math.acos((-(l2 * l2) + (l1 * l1) + (l3 * l3)) / (2 * l1 * l3))
local a2 = math.acos(((l2 * l2) - (l1 * l1) + (l3 * l3)) / (2 * l2 * l3))
return planeCF, math.pi/2-a1, -(a2 - a1)
end
end
local function WorldCFrameToC0ObjectSpace(motor6DJoint,worldCFrame)
local part1CF = motor6DJoint.Part1.CFrame
local part0 = motor6DJoint.Part0
local c1Store = motor6DJoint.C1
local c0Store = motor6DJoint.C0
local relativeToPart0 = part0.CFrame:inverse() * worldCFrame * c1Store
local goalC0CFrame = relativeToPart0
return goalC0CFrame
end
local R6IK = {}
R6IK.__index = R6IK
function R6IK.New(Character)
local self = {}
self.Torso = Character.Torso
self.HumanoidRootPart = Character.HumanoidRootPart
self.LeftArm = Character["Left Arm"]
self.RightArm = Character["Right Arm"]
self.LeftLeg = Character["Left Leg"]
self.RightLeg = Character["Right Leg"]
self.Motor6Ds = {
["Left Shoulder"] = self.Torso["Left Shoulder"],
["Right Shoulder"] = self.Torso["Right Shoulder"],
["Left Hip"] = self.Torso["Left Hip"],
["Right Hip"] = self.Torso["Right Hip"],
["RootJoint"] = self.HumanoidRootPart["RootJoint"]
}
self.C0s = {
["Left Shoulder"] = self.Motor6Ds["Left Shoulder"].C0,
["Right Shoulder"] = self.Motor6Ds["Right Shoulder"].C0,
["Left Hip"] = self.Motor6Ds["Left Hip"].C0,
["Right Hip"] = self.Motor6Ds["Right Hip"].C0,
["RootJoint"] = self.Motor6Ds["RootJoint"].C0
}
self.C1s = {
["Left Shoulder"] = self.Motor6Ds["Left Shoulder"].C1,
["Right Shoulder"] = self.Motor6Ds["Right Shoulder"].C1,
["Left Hip"] = self.Motor6Ds["Left Hip"].C1,
["Right Hip"] = self.Motor6Ds["Right Hip"].C1,
["RootJoint"] = self.Motor6Ds["RootJoint"].C1
}
self.Part0s = {
["Left Shoulder"] = self.Motor6Ds["Left Shoulder"].Part0,
["Right Shoulder"] = self.Motor6Ds["Right Shoulder"].Part0,
["Left Hip"] = self.Motor6Ds["Left Hip"].Part0,
["Right Hip"] = self.Motor6Ds["Right Hip"].Part0,
["RootJoint"] = self.Motor6Ds["RootJoint"].Part0
}
self.Part1s = {
["Left Shoulder"] = self.Motor6Ds["Left Shoulder"].Part1,
["Right Shoulder"] = self.Motor6Ds["Right Shoulder"].Part1,
["Left Hip"] = self.Motor6Ds["Left Hip"].Part1,
["Right Hip"] = self.Motor6Ds["Right Hip"].Part1,
["RootJoint"] = self.Motor6Ds["RootJoint"].Part1
}
self.LeftUpperArmLength = 1
self.LeftLowerArmLength = 1
self.RightUpperArmLength = 1
self.RightLowerArmLength = 1
self.LeftUpperLegLength = 1
self.LeftLowerLegLength = 1
self.RightUpperLegLength = 1
self.RightLowerLegLength = 1
self.TorsoIK = false
return setmetatable(self, R6IK)
end
function R6IK:ArmIK(Side : "Left" | "Right", Position:Vector3)
if Side == "Left" then
local OriginCF = self.Torso.CFrame*self.C0s["Left Shoulder"]
local C1Off = self.C1s["Left Shoulder"]
local PlaneCF,ShoulderAngle,ElbowAngle, l3 = SolveArmIK(OriginCF, Position, self.LeftUpperArmLength, self.LeftLowerArmLength, C1Off, Side)
local ShoulderAngleCFrame, ElbowAngleCFrame = CFrame.Angles(ShoulderAngle, 0, 0), CFrame.Angles(ElbowAngle, 0, 0)
local ShoulderCF = PlaneCF * ShoulderAngleCFrame*CFrame.new(0,-self.LeftUpperArmLength * 0.5,0)
local ElbowCF = ShoulderCF*CFrame.new(0,-self.LeftUpperArmLength * 0.5,0)* ElbowAngleCFrame * CFrame.new(0, -self.LeftLowerArmLength*0.5, 0)*CFrame.new(0,(self.LeftArm.Size.Y-self.LeftLowerArmLength)*0.5,0)
return WorldCFrameToC0ObjectSpace(self.Motor6Ds["Left Shoulder"], ElbowCF)
elseif Side == "Right" then
local OriginCF = self.Torso.CFrame*self.C0s["Right Shoulder"]
local C1Off = self.C1s["Right Shoulder"]
local PlaneCF,ShoulderAngle,ElbowAngle, l3 = SolveArmIK(OriginCF, Position, self.RightUpperArmLength, self.RightLowerArmLength, C1Off, Side)
local ShoulderAngleCFrame, ElbowAngleCFrame = CFrame.Angles(ShoulderAngle, 0, 0), CFrame.Angles(ElbowAngle, 0, 0)
local ShoulderCF = PlaneCF * ShoulderAngleCFrame*CFrame.new(0,-self.RightUpperArmLength * 0.5,0)
local ElbowCF = ShoulderCF*CFrame.new(0,-self.RightUpperArmLength * 0.5,0)* ElbowAngleCFrame * CFrame.new(0, -self.RightLowerArmLength*0.5, 0)*CFrame.new(0,(self.RightArm.Size.Y-self.RightLowerArmLength)*0.5,0)
return WorldCFrameToC0ObjectSpace(self.Motor6Ds["Right Shoulder"], ElbowCF)
end
end
function R6IK:LegIK(Side : "Left" | "Right", Position:Vector3)
if Side == "Left" then
local OriginCF = self.Torso.CFrame*self.C0s["Left Hip"]
local C1Off = self.C1s["Left Hip"]
local PlaneCF,ShoulderAngle,ElbowAngle, l3 = SolveLegIK(OriginCF*CFrame.Angles(0, math.pi/2, 0), Position, self.LeftUpperLegLength, self.LeftLowerLegLength, C1Off)
local HipAngleCFrame, KneeAngleCFrame = CFrame.Angles(math.clamp(ShoulderAngle,script:GetAttribute("lege"),script:GetAttribute("legs")), 0, 0), CFrame.Angles(math.clamp(ElbowAngle,script:GetAttribute("lege"),script:GetAttribute("legs")) , 0, 0)
local HipCF = PlaneCF * HipAngleCFrame*CFrame.new(0,-self.LeftUpperLegLength * 0.5,0)
local KneeCF = HipCF*CFrame.new(0,-self.LeftUpperLegLength * 0.5,0)* KneeAngleCFrame * CFrame.new(0, -self.LeftLowerLegLength*0.5, 0)*CFrame.new(0,(self.LeftLeg.Size.Y-self.LeftLowerLegLength)*0.5,0)
return WorldCFrameToC0ObjectSpace(self.Motor6Ds["Left Hip"], KneeCF)
elseif Side == "Right" then
local OriginCF = self.Torso.CFrame*self.C0s["Right Hip"]
local C1Off = self.C1s["Right Hip"]
local PlaneCF,ShoulderAngle,ElbowAngle, l3 = SolveLegIK(OriginCF*CFrame.Angles(0, -math.pi/2, 0), Position, self.RightUpperLegLength, self.RightLowerLegLength, C1Off)
local HipAngleCFrame, KneeAngleCFrame = CFrame.Angles(math.clamp(ShoulderAngle,script:GetAttribute("lege"),script:GetAttribute("legs")), 0, 0), CFrame.Angles(math.clamp(ElbowAngle,script:GetAttribute("lege"),script:GetAttribute("legs")) , 0, 0)
local HipCF = PlaneCF * HipAngleCFrame*CFrame.new(0,-self.RightUpperLegLength * 0.5,0)
local KneeCF = HipCF*CFrame.new(0,-self.RightUpperLegLength * 0.5,0)* KneeAngleCFrame * CFrame.new(0, -self.RightLowerLegLength*0.5, 0)*CFrame.new(0,(self.RightLeg.Size.Y-self.RightLowerLegLength)*0.5,0)
return WorldCFrameToC0ObjectSpace(self.Motor6Ds["Right Hip"], KneeCF)
end
end
return R6IK
Hey brother i found a solution to this too run ik on a seperate charecter that is like a viewmodel weld the viewmodel to the torso disable the physics on the viewmodel’s humanoid
And it works well
Also quick tip turn off can query and can collide and can touch on all of the viewmodel limbs
Hi @robert_stevey, I’m quite new to IK and I am trying to make a gun system that uses IK. I haven’t done much yet, but my problem is that the arms are taking the position of the first limb rather than second limb. The green balls are the right arm’s target position and the blue ones the left arm’s target position. Also, how do I increase the weight of the IK so that the animation doesn’t affect it much or at all? This is the script I have right now:
local R6IK = require(game.ReplicatedStorage.R6IK)
local character = script.Parent
local hrp:Part = character:WaitForChild('HumanoidRootPart')
local torso:Part = character:WaitForChild('Torso')
local rIKAtt = Instance.new('Attachment', hrp)
rIKAtt.Name = 'rIKAtt'
local ikSolver = R6IK.New(character)
game:GetService("RunService").PreRender:Connect(function()
local RtargetPosition = (torso.Position + (torso.CFrame.RightVector * 1.2) + (torso.CFrame.UpVector * -0.4)) + (torso.CFrame.LookVector * 2.5)
local Rp1 = Instance.new('Part', workspace)
Rp1.Position = RtargetPosition
Rp1.Anchored = true
Rp1.Color = Color3.fromRGB(0, 255, 0)
Rp1.Shape = Enum.PartType.Ball
Rp1.Size = Vector3.new(0.5, 0.5, 0.5)
Rp1.CanCollide = false
Rp1.CanTouch = false
Rp1.CanQuery = false
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {character}
raycastParams.FilterType = Enum.RaycastFilterType.Exclude
raycastParams.IgnoreWater = true
local RraycastResult = workspace:Raycast((torso.Position + (torso.CFrame.RightVector * 1.2) + (torso.CFrame.UpVector * -0.4)), torso.CFrame.LookVector * 2.5, raycastParams)
if RraycastResult then
print(RraycastResult.Instance)
local Rp2 = Instance.new('Part', workspace)
Rp2.Position = RraycastResult.Position
Rp2.Anchored = true
Rp2.Color = Color3.fromRGB(255, 0, 0)
Rp2.Shape = Enum.PartType.Ball
Rp2.Size = Vector3.new(0.5, 0.5, 0.5)
Rp2.CanCollide = false
Rp2.CanTouch = false
Rp2.CanQuery = false
ikSolver:ArmIK("Right", Rp2.Position)
else
ikSolver:ArmIK("Right", Rp1.Position)
end
-----------------------------------------------------------------------------------------------
local LtargetPosition = (torso.Position + (torso.CFrame.RightVector * 1.1) + (torso.CFrame.UpVector * -0.4)) + (torso.CFrame.LookVector * 4)
local Lp1 = Instance.new('Part', workspace)
Lp1.Position = LtargetPosition
Lp1.Anchored = true
Lp1.Color = Color3.fromRGB(0, 0, 255)
Lp1.Shape = Enum.PartType.Ball
Lp1.Size = Vector3.new(0.5, 0.5, 0.5)
Lp1.CanCollide = false
Lp1.CanTouch = false
Lp1.CanQuery = false
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {character}
raycastParams.FilterType = Enum.RaycastFilterType.Exclude
raycastParams.IgnoreWater = true
local LraycastResult = workspace:Raycast((torso.Position + (torso.CFrame.RightVector * 1.1) + (torso.CFrame.UpVector * -0.4)), torso.CFrame.LookVector * 4, raycastParams)
if LraycastResult then
print(LraycastResult.Instance)
local Lp2 = Instance.new('Part', workspace)
Lp2.Position = LraycastResult.Position
Lp2.Anchored = true
Lp2.Color = Color3.fromRGB(255, 170, 0)
Lp2.Shape = Enum.PartType.Ball
Lp2.Size = Vector3.new(0.5, 0.5, 0.5)
Lp2.CanCollide = false
Lp2.CanTouch = false
Lp2.CanQuery = false
ikSolver:ArmIK("Left", Lp2.Position)
else
ikSolver:ArmIK("Left", Lp1.Position)
end
end)
Hello, The code works great, but I can’t seem to replicate what you have in the picture where your legs follow the IK, only the arms for me.
Sorry for late response time zones are yucky
What i did was raycast to the ground and update it every runservice.heartbeat
For the arms i welded a second humanoid to the charecter and named it world arms
Disabled can query for all of them
And ran the ik on the specific arm when it gets used thats mostly it!
If you want some code examples feek free to ask.
Don’t even worry about timezones, rarely fall asleep anyway. But yes, code examples would be lovely, trying to learn to script.
i am in desperate need of help plsss
IKStuff.rbxl (80.6 KB)
This is a place file that will show how the ik will work with tools
and how it will work with feet
i hope this helps
I put a resource right above this message