Here is the topic that i made before ( How to move your gun smoothly along with your cursor in FPS game?) . It turns out, it wasn’t because it doesn’t have spring or anything like that to simulate recoil or something similiar to it. The problem is the server doesn’t replicate everything perfectly to the client like this video has demonstrated:
The question is how would i avoid this delay?
Here is the code:
localscript inside a tool(aka to gun):
repeat
wait()
until game:IsLoaded()
local runservice = game:GetService("RunService")
local player = game.Players.LocalPlayer
local char = player.Character
local coordinate = game:GetService("ReplicatedStorage").coordinate
repeat
wait()
until char.Head
local head = char:WaitForChild("Head")
local leftupperarm = char:WaitForChild("LeftUpperArm")
local rightupperarm = char:WaitForChild("RightUpperArm")
local neck = head:WaitForChild("Neck")
local mouse = player:GetMouse()
local originCFrame = neck.C0
local leftorigin = leftupperarm.LeftShoulder.C0
local rightorigin = rightupperarm.RightShoulder.C0
local tool = script.Parent
local replicatedstorage = game:GetService("ReplicatedStorage")
local reverse = replicatedstorage:WaitForChild("reverse")
local connection
local poseanim = replicatedstorage:WaitForChild("poseanim")
local anim = game:GetService("ReplicatedStorage").anim
local debounce = false
tool.Equipped:Connect(function(mouse)
poseanim:FireServer()
connection = mouse.Move:Connect(function(dt)
if neck then
local mousepos = mouse.Hit.p
local headcframe = head.CFrame.p
local height = mousepos.Y-headcframe.Y
local distance = (mousepos - headcframe).Magnitude
local angle = math.asin(height/distance)
local turn = CFrame.fromAxisAngle(originCFrame.RightVector,angle)
coordinate:FireServer(neck,turn,leftupperarm,rightupperarm,leftorigin,rightorigin,originCFrame)
debounce = false
anim:FireServer(debounce)
end
end)
end)
tool.Unequipped:Connect(function(mouse)
debounce = true
anim:FireServer(debounce)
reverse:FireServer()
connection:Disconnect()
end)
client control( also another localscript but the purpose is to modify the default setting of the player:
repeat
wait()
until game:IsLoaded()
local player = game.Players.LocalPlayer
player.CameraMode = Enum.CameraMode.LockFirstPerson
repeat
wait()
until player.Character
local char = player.Character
local lefthand = char:WaitForChild("LeftHand")
local leftlowerarm = char:WaitForChild("LeftLowerArm")
local leftupperarm = char:WaitForChild("LeftUpperArm")
local righthand = char:WaitForChild("RightHand")
local rightlowerarm = char:WaitForChild("RightLowerArm")
local rightupperarm = char:WaitForChild("RightUpperArm")
local runservice = game:GetService("RunService")
runservice.RenderStepped:Connect(function(dt)
lefthand.LocalTransparencyModifier = 0
leftlowerarm.LocalTransparencyModifier = 0
leftupperarm.LocalTransparencyModifier = 0
righthand.LocalTransparencyModifier = 0
rightlowerarm.LocalTransparencyModifier = 0
rightupperarm.LocalTransparencyModifier = 0
end)
serverscript:
local char
game.Players.PlayerAdded:Connect(function(player)
char = player.Character
if char then
local animator = Instance.new("Animator")
animator.Parent = char.Humanoid
end
end)
local reverse = game:GetService("ReplicatedStorage").reverse
local poseanim = game:GetService("ReplicatedStorage").poseanim
local starterplayer = game:GetService("StarterPlayer")
local loading = starterplayer.StarterPlayerScripts.client.loading
local poseanimation = starterplayer.StarterPlayerScripts.client.poseanim
local a = 0
local debounce = false
poseanim.OnServerEvent:Connect(function(player)
if player.Character then
local playeranimator = player.Character.Humanoid.Animator
local playerloading = playeranimator:LoadAnimation(loading)
playerloading:Play()
playerloading.Stopped:Wait()
local playerpose = playeranimator:LoadAnimation(poseanimation)
playerpose:Play()
end
end)
reverse.OnServerEvent:Connect(function(player)
if player.Character then
local playeranimator = player.Character.Humanoid.Animator
local playerpose
for i,v in pairs(playeranimator:GetPlayingAnimationTracks()) do
print(i)
if v.IsPlaying then
print(v)
end
v.TimePosition = 0
v:Stop()
end
end
end)
local coordinate = game:GetService("ReplicatedStorage").coordinate
coordinate.OnServerEvent:Connect(function(player,neck,turn,leftarm,rightarm,leftori,rightori,origin)
neck.C0 = origin*turn
leftarm.LeftShoulder.C0 = leftori*turn
rightarm.RightShoulder.C0 = rightori*turn
end)
local anim = game:GetService("ReplicatedStorage").anim
anim.OnServerEvent:Connect(function(player,debounce)
if debounce then
print("god")
player.Character.Animate.fall.FallAnim.AnimationId = "rbxassetid://507767968"
player.Character.Animate.jump.JumpAnim.AnimationId = "rbxassetid://507765000"
player.Character.Animate.run.RunAnim.AnimationId = "rbxassetid://913376220"
player.Character.Animate.walk.WalkAnim.AnimationId = "rbxassetid://913402848"
return
end
if player.Character then
player.Character.Animate.fall.FallAnim.AnimationId ="rbxassetid://7394638408"
player.Character.Animate.jump.JumpAnim.AnimationId = "rbxassetid://7394621028"
player.Character.Animate.run.RunAnim.AnimationId = "rbxassetid://7393184029"
player.Character.Animate.walk.WalkAnim.AnimationId = "rbxassetid://0"
end
end)
This is a brief description about how do i make this system:
The equipped pose( the pose when you are holding the gun) was made by using an animation that loops constantly unlike traditional system that use fake arms to simulate the pose. The hand and the gun follow my cursor by calculating the angle using trigonometry as demonstrated in the code above. Extra information is that i change the default animation into my custom animation in order to make the arms not swinging too much because it would be difficult to aim if the hands swinging so hard while moving.
Note: some people might suggest that i should clone hands in the client side but i don’t want to do this for now
If anyone could help, feel free to give me some advice