This tutorial is outdated, instead follow this one Making a simple fps framework. Part 1
Before I start I got some feedback which understandable.
You should explain some things. It’s bad for someone just to take code, and then later on not understand how to modify it and end up getting demotivated.
This is for people that knows cframes and raycasting
Now lets start!
Step 1 More animations!
Now the most of our animations are going to be CFrame animations.
“What is that?” You may be asking.
Well how I think it is its a cframe lerping.(I can’t get a working example)
So lets get going into our animations!
In the FPS module go to the RenderStepped function and now we are going to make a another idle animation that goes up and down.
But first we need to set the cframe.
So do this :
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RS = game:GetService("RunService")
local Viewmodels = ReplicatedStorage:WaitForChild("Viewmodels")
local viewModel : Model
local IdleCF = CFrame.new()
Later on we will be adding this to the :SetPrimaryPartCFrame function.
This is because just leaving the cframe will do nothing because the code will not know what IdleCF does.
Now set the IdleCF to a CFrame.new() in the EquipGun function just to make sure.
So now we are going to do this in the RenderStepped function:
IdleCF = CFrame.new(0 ,0.1 * math.sin(tick() * 6),0)
I have no idea how it works I just made this by accident when I was working on a fps game.
Now your code should look like this:
local module = {}
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RS = game:GetService("RunService")
local Viewmodels = ReplicatedStorage:WaitForChild("Viewmodels")
local viewModel : Model
local IdleCF = CFrame.new()
function module:animate(type)
if type == "Idle" then
if viewModel then
viewModel.AnimationController:LoadAnimation(viewModel.AnimationController.Idle):Play()
end
end
end
function module:EquipGun(Name)
viewModel = Viewmodels:WaitForChild(Name):Clone()
viewModel.Parent = workspace.CurrentCamera
IdleCF = CFrame.new(0,0,0)
module:animate("Idle")
end
RS.RenderStepped:Connect(function()
if viewModel then
IdleCF = CFrame.new(0 ,0.1 * math.sin(tick() * 6),0)
viewModel:SetPrimaryPartCFrame(workspace.CurrentCamera.CFrame * IdleCF)
end
end)
return module
And you got a idle animation :
Now a shooting(recoil) animation
This is simple so won’t explain this.
Do the same thing as the we did for the idle animation but change the cframe to:
RecoilCF = RecoilCF:Lerp(CFrame.new(0,0,0.5) * CFrame.Angles(math.rad(10),0,0),0.1)
Now your module should look like this:
local module = {}
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RS = game:GetService("RunService")
local Viewmodels = ReplicatedStorage:WaitForChild("Viewmodels")
local viewModel : Model
local IdleCF = CFrame.new()
local RecoilCF = CFrame.new()
function module:animate(type)
if type == "Idle" then
if viewModel then
viewModel.AnimationController:LoadAnimation(viewModel.AnimationController.Idle):Play()
end
end
end
function module:EquipGun(Name)
viewModel = Viewmodels:WaitForChild(Name):Clone()
viewModel.Parent = workspace.CurrentCamera
IdleCF = CFrame.new(0,0,0)
RecoilCF = CFrame.new(0,0,0)
module:animate("Idle")
end
RS.RenderStepped:Connect(function()
if viewModel then
IdleCF = CFrame.new(0 ,0.1 * math.sin(tick() * 6),0)
RecoilCF = RecoilCF:Lerp(CFrame.new(0,0,0.5) * CFrame.Angles(math.rad(10),0,0),0.1)
viewModel:SetPrimaryPartCFrame(workspace.CurrentCamera.CFrame * IdleCF * RecoilCF)
end
end)
return module
But its happing at the same time!
To fix this we need to make bools to check if its true we do the animation but if its false we don’t do the animation.
So your going to replace the module code with this:
local module = {}
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local UIS = game:GetService("UserInputService")
local RS = game:GetService("RunService")
local Players = game:GetService("Players")
local Viewmodels = ReplicatedStorage:WaitForChild("Viewmodels")
local viewModel : Model
local IdleCF = CFrame.new()
local RecoilCF = CFrame.new()
local isRecoil = false
local isIdle = false
local localPlayer = Players.LocalPlayer
local Char = localPlayer.Character or localPlayer.CharacterAdded:Wait()
function module:animate(type)
if type == "Idle" then
if viewModel then
viewModel.AnimationController:LoadAnimation(viewModel.AnimationController.Idle):Play()
end
end
end
function module:EquipGun(Name)
viewModel = Viewmodels:WaitForChild(Name):Clone()
viewModel.Parent = workspace.CurrentCamera
IdleCF = CFrame.new(0,0,0)
RecoilCF = CFrame.new(0,0,0)
module:animate("Idle")
end
RS.RenderStepped:Connect(function()
if viewModel then
viewModel:SetPrimaryPartCFrame(workspace.CurrentCamera.CFrame * IdleCF * RecoilCF)
if IdleCF then
IdleCF = CFrame.new(0 ,0.1 * math.sin(tick() * 6),0)
else
IdleCF = CFrame.new(0,0,0)
end
if isRecoil then
RecoilCF = RecoilCF:Lerp(CFrame.new(0,0,0.5) * CFrame.Angles(math.rad(10),0,0),0.1)
else
RecoilCF = RecoilCF:Lerp(CFrame.new(0,0,0) * CFrame.Angles(math.rad(10),0,0),0.1)
end
end
end)
UIS.InputBegan:Connect(function(inputKey)
if inputKey.UserInputType == Enum.UserInputType.MouseButton1 then
isRecoil = true
end
end)
UIS.InputEnded:Connect(function(inputKey)
if inputKey.UserInputType == Enum.UserInputType.MouseButton1 then
isRecoil = false
end
end)
Char:WaitForChild("Humanoid").Running:Connect(function(speed)
if speed < 0.1 then
isIdle = true
else
isIdle = false
end
end)
return module
Now its fixed well kind of.
We will fix more of it in part 3.
Step 2 Raycasting
To make this a fps shooter we need the shooting.
So raycasting
So create a script called Server in ServerScriptService.
And then create a RemoteEvent called Shoot in ReplicatedStorage.
In the Server script your going to type this in:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Shoot = ReplicatedStorage:WaitForChild("Shoot")
Then connect the RemoteEvent by doing this:
Shoot.OnServerEvent:Connect(function(plr, orgin, dir, distance)
end)
Then in the connection do this:
local rayCastTotal = workspace:Raycast(orgin, dir*distance)
if rayCastTotal.Instance then
if rayCastTotal.Instance.Parent:FindFirstChild("Humanoid") then
rayCastTotal.Instance.Parent:FindFirstChild("Humanoid"):TakeDamage(10)
end
end
Okay now when we click we need to fire this RemoteEvent.
So in our FPS module go to InputBegan function and add this:
if viewModel then
ReplicatedStorage:WaitForChild("Shoot"):FireServer(viewModel.Handle.Position, (Mouse.Hit.Position - viewModel.Handle.Position), 10)
end
Also add a dummy if you want.
And shooting is done!
End!
That is the end of this tutorial!
If you missed part 1 here it is: How to make a lazy fps shooter. Part 1
Tell me if you found this useful or anything!