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!
- What is it supposed to be?
- A LocalScript!
- Where do i put it?
- StarterCharacterScripts!
- 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
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)