IKControl Footplant and Strafing for Rig 15

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.




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

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

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

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

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

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

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

-- > 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

local Humanoid = Character:FindFirstChildOfClass("Humanoid")

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

-- > 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)
    RightLegTarget.Transparency = 1
    LeftLegTarget.Transparency = 1

-- > 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)
            RightLegWeld.C0 = RightLegWeld.C0:Lerp(RightLegWeldC0, DeltaTime)
        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)
            LeftLegWeld.C0 = LeftLegWeld.C0:Lerp(LeftLegWeldC0, DeltaTime)

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???

1 Like

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!

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