IKControl Footplant and Strafing for Rig 15

Edit note: Please remember that this is basically a template. The concept is good but you will need to add constraints to make it bed like a normal leg would, don’ t complain in the comments on how it bends unnaturally.
Hey everyone!

I’ m Emper and recently I turned 13 so I wanted to do something for my birthday, and as you hopefully read the title you already know what it is!

This was meant to be private since I didn’ t think it was that good but now here we are with me publishing it.

Before showcasing I’ m gonna tell you more about the script itself:

The script contains Footplanting using IKControl and Strafing Animations, there are functions in the script for you to use and edit, there’ s also a “Debug” variable which adds an Highlight to the target parts used for Raycast. The script also stops itself if it doesn’ t find an Instance it needs.

Now we move on to the showcase part!

The Footplant.

As I mentioned 2 times it has Footplant but what I didn’ t mention is that it has rotation and works for all rig sizes.

Small:

Normal:

Tall:

As you can see it’ s for normal AND custom rigs.

The Strafing:

The Strafing animations use LookVector and RightVector multiplied by the AssemblyLinearVelocity.
The Forward and Sideways are in variables so you can use them whenever u want or clamp them!

Showcase of Strafing and Footplant together:

The script has been optimized so that your fps don’ t have 10 subsequent strokes and die, and also cannot error unless there’ s a syntax error.

Please remember that this was made by one 13 year old kid and this was my first resource post so don’ t be harsh on me and I would really appreciate credit!
If there’ s something that can be improved ( Most definetely is ) please comment! And also remember to give me feedback on how to improve my mini-speechs and code thank you

And now for the part everyone was waiting for:
The script!

  1. What is it supposed to be?
  • A LocalScript!
  1. Where do i put it?
  • StarterCharacterScripts!
  1. It doesn’ t work what do i do?
  • Make sure the rig is R15!
  • Make sure all parts are loaded ( Add a task.wait at the start if they aren’ t ! )

I don’ t expect this to get much attention but I’ ll keep hoping :crying_cat_face:

local Debug = false
local Workspace = game:GetService("Workspace")

-- > Functions variables < --

local Instancenew = Instance.new
local Vector3new = Vector3.new

local CFramenew = CFrame.new
local CFrameAngles = CFrame.Angles

local Color3fromRGB = Color3.fromRGB

local RaycastParameters = RaycastParams.new()
RaycastParameters.RespectCanCollide = true

-- > Main functions < -- 

local function Highlight(FillColor, FillTransparency, OutlineColor, OutlineTransparency, Instance)
    local Highlight = Instancenew("Highlight")
    
    Highlight.Adornee = Instance
    Highlight.FillColor = FillColor
    Highlight.FillTransparency = FillTransparency
    Highlight.OutlineColor = OutlineColor
    Highlight.OutlineTransparency = OutlineTransparency
    Highlight.Parent = Instance
    
    return Highlight
end

local function Part(Size, Parent)
    local Part = Instancenew("Part")
    
    Part.Size = Size
    Part.CanCollide = false
    Part.Parent = Parent
    
    return Part
end

local function IKControl(EndEffector, Target, ChainRoot, Parent)
    local IKControl = Instancenew("IKControl")
    
    IKControl.EndEffector = EndEffector
    IKControl.Target = Target
    IKControl.ChainRoot = ChainRoot
    IKControl.Weight = 1
    IKControl.Parent = Parent
    
    return IKControl
end

local function Weld(Part0, Part1, C0, C1)
    local Weld = Instancenew("Weld")
    
    Weld.Part0 = Part0
    Weld.Part1 = Part1
    Weld.C0 = C0 or CFramenew(0, 0, 0)
    Weld.C1 = C1 or CFramenew(0, 0, 0)
    Weld.Parent = Part1
    
    return Weld
end

local function Instances(Parent, ClassName, Name)
    for _, Instance in next, Parent:GetChildren() do
        if Instance:IsA(ClassName) and Instance.Name == Name then
            return Instance
        end
    end
end

local function Parent(Instance)
    return Instance and Instance.Parent
end

local function Raycast(RaycastOrigin, RaycastDirection)
    return Workspace:Raycast(RaycastOrigin, RaycastDirection, RaycastParameters)
end

-- > Variables < --

local Clamp = math.clamp
local Radians = math.rad

local Size = Vector3new(0.5, 0.5, 0.5)
local White = Color3fromRGB(255, 255, 255)

local LocalPlayer = game:GetService("Players").LocalPlayer

local Character = LocalPlayer.Character or LocalPlayer.CharacterAdded:Wait()
local Animate = Instances(Character, "LocalScript", "Animate")

if Animate then
    Animate.Enabled = false
end

local Humanoid = Character:FindFirstChildOfClass("Humanoid")

if Humanoid.RigType ~= Enum.HumanoidRigType.R15 then
    return print("Rig must be a R15 one!")
end

-- > HumanoidRootPart < --

local HumanoidRootPart = Instances(Character, "BasePart", "HumanoidRootPart")
local HumanoidRootPartSize = HumanoidRootPart and HumanoidRootPart.Size

local HumanoidRootPartSizeX = HumanoidRootPart and HumanoidRootPartSize.Y

local HumanoidRootPartSizeY2 = HumanoidRootPart and HumanoidRootPartSize.Y / 2
local HumanoidRootPartSizeX2 = HumanoidRootPart and HumanoidRootPartSizeX / 2
local HumanoidRootPartSizeX4 = HumanoidRootPart and HumanoidRootPartSizeX / 4

-- > Main Limbs < --

local UpperTorso = Instances(Character, "BasePart", "UpperTorso")

local Waist = UpperTorso and Instances(UpperTorso, "JointInstance", "Waist")
local WaistC0 = Waist and Waist.C0

local Head = Instances(Character, "BasePart", "Head")

local Neck = Head and Instances(Head, "JointInstance", "Neck")
local NeckC0 = Neck and Neck.C0

-- > Legs < --

local RightUpperLeg = Instances(Character, "BasePart", "RightUpperLeg")
local RightLowerLeg = Instances(Character, "BasePart", "RightLowerLeg")
local RightFoot = Instances(Character, "BasePart", "RightFoot")

local RightLegSizeY = ( RightUpperLeg and RightUpperLeg.Size.Y or 0 ) + ( RightLowerLeg and RightLowerLeg.Size.Y or 0 ) + ( RightFoot and RightFoot.Size.Y or 0 )

local LeftUpperLeg = Instances(Character, "BasePart", "LeftUpperLeg")
local LeftLowerLeg = Instances(Character, "BasePart", "LeftLowerLeg")
local LeftFoot = Instances(Character, "BasePart", "LeftFoot")

local LeftLegSizeY = ( LeftUpperLeg and LeftUpperLeg.Size.Y or 0 ) + ( LeftLowerLeg and LeftLowerLeg.Size.Y or 0 ) + ( LeftFoot and LeftFoot.Size.Y or 0 )

-- > Target parts < --

local RightLegTarget = Part(Size, Character)

local RightLegWeld = Weld(RightLegTarget, HumanoidRootPart, CFramenew(- HumanoidRootPartSizeX4, RightLegSizeY, 0))
local RightLegWeldC0 = RightLegWeld.C0

local LeftLegTarget = Part(Size, Character)

local LeftLegWeld = Weld(LeftLegTarget, HumanoidRootPart, CFramenew(HumanoidRootPartSizeX4, LeftLegSizeY, 0))
local LeftLegWeldC0 = LeftLegWeld.C0

if Debug then
    Highlight(Color3fromRGB(0, 0, 255), 0.5, White, 0.5, RightLegTarget)
    Highlight(Color3fromRGB(0, 255, 0), 0.5, White, 0.5, LeftLegTarget)
else
    RightLegTarget.Transparency = 1
    LeftLegTarget.Transparency = 1
end

-- > IKControls < --

local RightLegIKControl = IKControl(RightFoot or RightLowerLeg, RightLegTarget, RightUpperLeg, Humanoid)
local LeftLegIKControl = IKControl(LeftFoot or LeftLowerLeg, LeftLegTarget, LeftUpperLeg, Humanoid)

-- > Raycasts < --

local PreRender

PreRender = game:GetService("RunService").PostSimulation:Connect(function(DeltaTime)
    if Parent(Character) and Parent(RightLegIKControl) and Parent(LeftLegIKControl) and Parent(RightLegWeld) and Parent(LeftLegWeld) and Parent(Waist) and Parent(Neck) then
        DeltaTime = Clamp(DeltaTime * 7.5, 0, 1)
            
        local HumanoidRootPartCFrame = HumanoidRootPart.CFrame
        local AssemblyLinearVelocity = HumanoidRootPart.AssemblyLinearVelocity
        
        local RightVector = AssemblyLinearVelocity * HumanoidRootPartCFrame.RightVector
        local LookVector = AssemblyLinearVelocity * HumanoidRootPartCFrame.LookVector
        
        local Forward = Radians(LookVector.X + LookVector.Z)
        local Sideways = Radians(RightVector.X + RightVector.Z)
        
        Waist.C0 = Waist.C0:Lerp(CFrameAngles(- Forward, - Sideways, - Sideways) * WaistC0, DeltaTime)
        Neck.C0 = Neck.C0:Lerp(CFrameAngles(0, - Sideways, 0) * NeckC0, DeltaTime)
        
        local RightLegRaycastResult = Raycast(( HumanoidRootPartCFrame * CFramenew(HumanoidRootPartSizeX4, - HumanoidRootPartSizeY2, 0) ).Position, Vector3new(0, - RightLegSizeY, 0))
        
        if RightLegRaycastResult then
            local NormalZ = RightLegRaycastResult.Normal.Z
            local LookVector = RightLegTarget.CFrame.LookVector * NormalZ
            
            RightLegWeld.C0 = RightLegWeld.C0:Lerp(CFramenew(0, RightLegRaycastResult.Distance + HumanoidRootPartSizeY2 - NormalZ - RightLegSizeY, 0) * CFrameAngles(LookVector.Z, 0, LookVector.X) * RightLegWeldC0, DeltaTime)
        else
            RightLegWeld.C0 = RightLegWeld.C0:Lerp(RightLegWeldC0, DeltaTime)
        end
        
        local LeftLegRaycastResult = Raycast(( HumanoidRootPartCFrame * CFramenew(- HumanoidRootPartSizeX4, - HumanoidRootPartSizeY2, 0) ).Position, Vector3new(0, - LeftLegSizeY, 0))
        
        if LeftLegRaycastResult then
            local NormalZ = LeftLegRaycastResult.Normal.Z
            local LookVector = LeftLegTarget.CFrame.LookVector * NormalZ
            
            LeftLegWeld.C0 = LeftLegWeld.C0:Lerp(CFramenew(0, LeftLegRaycastResult.Distance + HumanoidRootPartSizeY2 - NormalZ - LeftLegSizeY, 0) * CFrameAngles(LookVector.Z, 0, LookVector.X) * LeftLegWeldC0, DeltaTime)
        else
            LeftLegWeld.C0 = LeftLegWeld.C0:Lerp(LeftLegWeldC0, DeltaTime)
        end
    else
        PreRender:Disconnect()
    end
end)
28 Likes

can you add R6 Support please!

1 Like

I can definetely work on that!

1 Like

nice project for your birthday!
only thing: what happened to the walking animation???

2 Likes

hey congrats on your birthday! and now I just want this in r6.

1 Like

The animate script was disabled because the IKControl actually messes legs animations a bit and since this was supposed to be edited by people I didn’ t give much attention to it!

1 Like

I’ am already on it! Fortunately it won’ t be too hard!

yea cuz its r6 but still its quite a challenge for me i suppose as I have never done anything with IK

1 Like

Is this fixable at all to know knowledge?

Yes you can enable it in the script directly. However you will have to edit the IKControl.Weight in the function because IKControl overrides animations.

2 Likes

Excellent work and fun to experiment with.

Edit: Just realized this was posted on my birthday as well!

1 Like

Does this work with walking animations?

1 Like

Yes, but you would have to edit the .Weight in the IKControl function to 0.5 or lower if you want them to show