Yep it is! all things that I open sourced for Roblox related projects are placed in the repository!
P.S. if you’re interested in the dynamic sound module here is a post about it
Yep it is! all things that I open sourced for Roblox related projects are placed in the repository!
P.S. if you’re interested in the dynamic sound module here is a post about it
i have an r6 startercharacter and i inserted this script inside it, it isnt working. can you help me?
Did you only insert it without requiring it and using it like a module? I’m not sure what’s the problem here
When i use it the player’s arm starts flying off into the sunset.
Code:
–Some Localscript
local Remote = game:GetService(‘ReplicatedStorage’).Remotes.Grapple
local Plr = game.Players.LocalPlayer
local Mouse = Plr:GetMouse()
local uis = game:GetService(‘UserInputService’)
while task.wait() do
if uis:IsKeyDown(Enum.KeyCode.Q) then
Remote:FireServer(Mouse.hit.Position)
end
end
–Some ServerScript
local Remote = game:GetService(‘ReplicatedStorage’).Remotes.Grapple
local R6IK = require(game:GetService(‘ReplicatedStorage’).Modules.R6IK)
Remote.OnServerEvent:Connect(function(Plr, MouseHit : Vector3)
if Plr.Character then
local IK = R6IK.New(Plr.Character)
IK:ArmIK(‘Left’, MouseHit)
end
end)
It flies off into the sunset once you press E. It works for the legs but not the arms
I see the problem here, I should have stated this before but you must use the .New function Once and not every time you want to do IK.
So to fix your code, here is the solution that I found. (Server script)
local Remote = game:GetService("ReplicatedStorage").Remotes.Grapple
local Players = game:GetService("Players")
local R6IK = require(game:GetService("ReplicatedStorage").Modules.R6IK)
local PlayerInfo = {}
Players.PlayerAdded:Connect(function(Player)
Player.CharacterAdded:Connect(function()
PlayerInfo[Player] = {IK = R6IK.New(Player.Character)}
end)
end)
Remote.OnServerEvent:Connect(function(Plr, MouseHit : Vector3)
if Plr.Character then
local IK = PlayerInfo[Plr].IK
IK:ArmIK("Left", MouseHit)
end
end)
Can you give a sample of using this for footplanting pls
I can’t figure out a way for ik to be compatible with my walking animations
That is up to you to implement, I haven’t done any footplanting code which includes this module yet. I might do it in the future but im not sure
I keep getting a buffing error while opening the game, are you able to link a model?
Im kinda stuck with resetting the arm back to normal, how do i do that?
Very good module, currently using it on some of my projects.
Pretty good module, I hate r15 tbh but it was my only option to use ikcontrols since roblox but it was really buggy and pretty bad looking, tried for 2 days straight to solve it but the only option was changing to R6IK
I expected it to be pretty limited but it surprised me how well it worked!
Might need to put some way to stop the ikcontrol instead of just destroying it like I did
Hey, Can u reply with the source, because I can’t get it from the link.
i also hate r15
found another module
i really want the roblox’s ik control to work for r6 without bugging
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)
self.Motor6Ds["Left Shoulder"].C0 = 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)
self.Motor6Ds["Right Shoulder"].C0 = 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(ShoulderAngle, 0, 0), CFrame.Angles(ElbowAngle, 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)
self.Motor6Ds["Left Hip"].C0 = 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(ShoulderAngle, 0, 0), CFrame.Angles(ElbowAngle, 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)
self.Motor6Ds["Right Hip"].C0 = WorldCFrameToC0ObjectSpace(self.Motor6Ds["Right Hip"], KneeCF)
end
end
return R6IK
Hey there
I know this post is a bit old but I’m looking forward to using this module and I just can’t figure out how to IK a limb dynamically/repeatedly (like in the showcase) without it freaking out.
did you use the .New function once and not every time you want to use the IK?
Hi, im new to ik and i was playing around with this module trying to create a foot planting system and i got stuck trying to figure out how to change the roation of the ik to make it look better.
Heres an example:
What im trying to achive:
Heres how im trying to handle the foot planting system:
local function getTerrainHeight(position)
local ray = Ray.new(position + Vector3.new(0, 50, 0), Vector3.new(0, -100, 0))
local part, hitPosition = Workspace:FindPartOnRay(ray, character)
return hitPosition
end
local function updateLegPositions()
local rootPart = character.HumanoidRootPart
local rootCF = rootPart.CFrame
local rootPos = rootPart.Position
local leftFootOffset = Vector3.new(-0.5, -character.Humanoid.HipHeight - ik.LeftUpperLegLength - ik.LeftLowerLegLength / 0.1, 0)
local rightFootOffset = Vector3.new(0.5, -character.Humanoid.HipHeight - ik.RightUpperLegLength - ik.RightLowerLegLength / 0.1, 0)
local leftFootTarget = rootCF:PointToWorldSpace(leftFootOffset)
local rightFootTarget = rootCF:PointToWorldSpace(rightFootOffset)
local leftFootTerrainHeight = getTerrainHeight(leftFootTarget)
local rightFootTerrainHeight = getTerrainHeight(rightFootTarget)
leftFootTarget = Vector3.new(leftFootTarget.X, leftFootTerrainHeight.Y, leftFootTarget.Z)
rightFootTarget = Vector3.new(rightFootTarget.X, rightFootTerrainHeight.Y, rightFootTarget.Z)
ik:LegIK("Left", leftFootTarget)
ik:LegIK("Right", rightFootTarget)
end
I hope you understand the problem and someone can help me
I see the what you’re aiming for with the leg IK, sadly I’m unsure on how to change the leg IK algorithm to fit your needs. Maybe the R6 IK algorithm in this post might help?
This was actually surprisingly easy to setup and use, and it works well, thanks for making this module!