This is a support category for asking questions about how to get something done on the Roblox websites or how to do something on Roblox applications such as Roblox Studio.
You can write your topic however you want, but you need to answer these questions:
-
What I want to achieve; creating a reliable fast weapon system with less desync
-
What is the issue? At the moment, for the purpose of having smooth hit detection, raycasting and part creation, what I do is create the essentials on the client like how things were before fe, then for all other players I fire a server remote event that just fires the same event on the client which copies what was done on the main client. It definitely works perfectly for a smooth experience but sometimes the clients can desync where a knife would hit the player but on the other players screen it missed.
-
So far I haven’t found a good solution that doesn’t make the weapon very slow, however I did manage to make it a bit more accurate from client to client by running these things along side eachother.
Here is the client remote event listener from the knife module that is required to everyones client upon entering the server. The parameters starting with “p” are just to have one available to pass vector3s
RemoteEvents.KnifeWeaponFunction.OnClientEvent:Connect(function(p1, p2, p3, p4, p5, p6, p7, p8)
if p3 ~= game.Players.LocalPlayer.Character then
if p2 == "CreateNormal" then
local KnifeTracker = p4
local Knife = p3.Knife.Handle:Clone()
Knife.CanCollide = false
Knife.Anchored = true
Knife.CFrame = p3.Knife.Handle.CFrame
Knife.Name = "tKnife"..KnifeTracker
Knife.Parent = workspace
local ThrowLoop = Instance.new("Sound")
ThrowLoop.Name = "ThrowLoop"
ThrowLoop.Looped = true
ThrowLoop.Volume = 0.3
ThrowLoop.SoundId = "http://www.roblox.com/asset?id="..Sounds.ThrowLoop[1]
ThrowLoop.Parent = Knife
ThrowLoop:Play()
elseif p2 == "AirSwoosh" then
local KnifeTracker = p7
local Knife = workspace:WaitForChild("tKnife"..KnifeTracker)
local Pos, KCP, Distance = p4, p5, p6
for i = 1, Distance, 6 do
Knife.CFrame = CFrame.new(Pos, KCP) * CFrame.new(0,0,i-Distance) * CFrame.fromEulerAnglesXYZ(math.rad(i*15),math.rad(180),math.rad(360))
wait()
end
elseif p2 == "Stop" then
local KnifeTracker = p6
local Knife = workspace:WaitForChild("tKnife"..KnifeTracker)
local P, K = p4, p5
Knife.CFrame = CFrame.new(P, K) * CFrame.new(0,0,0) * CFrame.fromEulerAnglesXYZ(math.rad(90),math.rad(180),math.rad(360))
elseif p2 == "WallHit" then
local KnifeTracker = p4
local Knife = workspace:WaitForChild("tKnife"..KnifeTracker)
local KnifeContents = Knife:GetChildren()
for k = 1, #KnifeContents do
if KnifeContents[k]:IsA("Sound") then
KnifeContents[k]:Destroy()
end
end
local Wallhit = Instance.new("Sound")
Wallhit.Parent = Knife
Wallhit.Volume = 0.5
Wallhit.SoundId = "rbxassetid://"..Sounds.WallHit[math.random(1, 2)]
Wallhit:Play()
Wallhit.Changed:Connect(function()
if Wallhit.IsPlaying == false then
Wallhit:Destroy()
end
end)
delay(10, function()
Knife:Destroy()
Knife = nil
end)
elseif p2 == "DestroyKnife" then
local KnifeTracker = p4
local Knife = workspace:WaitForChild("tKnife"..KnifeTracker)
Knife:Destroy()
elseif p2 == "CreateLaser" then
local KnifeTracker = p4
local Knife = p3.Knife.Handle:Clone()
Knife.CanCollide = false
Knife.Anchored = true
Knife.CFrame = p3.Knife.Handle.CFrame
Knife.Name = "tKnife"..KnifeTracker
Knife.Parent = workspace
elseif p2 == "CreateLaserBeam" then
local KnifeTracker = p4
local Knife = workspace:WaitForChild("tKnife"..KnifeTracker)
local Pos, KCP, Distance = p5, Knife.CFrame.p , p7
local LaserPart = Instance.new("Part")
LaserPart.Name = "Laser"..KnifeTracker
LaserPart.CanQuery = false
LaserPart.Anchored = true
LaserPart.CanCollide = false
LaserPart.Material = "Neon"
LaserPart.Color = Color3.new(1, 0, 0)
LaserPart.TopSurface = Enum.SurfaceType.Smooth
LaserPart.BottomSurface = Enum.SurfaceType.Smooth
LaserPart.Size = Vector3.new(0.2, 0.2, Distance)
LaserPart.CFrame = CFrame.new(Pos, KCP) * CFrame.new(0, 0, (-Distance/2) + 2)
LaserPart.Parent = workspace
elseif p2 == "AnimateLaser" then
local KnifeTracker = p4
local Knife = workspace:WaitForChild("tKnife"..KnifeTracker)
local LaserPart = workspace:WaitForChild("Laser"..KnifeTracker)
local Distance, Pos, KCP = p5, p6, Knife.CFrame.p
for i = 10000, Distance do
Knife.CFrame = CFrame.new(Pos, KCP) * CFrame.new(0,0,i-Distance) * CFrame.fromEulerAnglesXYZ(math.rad(90),math.rad(180),math.rad(360))
end
Knife.CFrame = CFrame.new(Pos, KCP) * CFrame.new(0,0,0) * CFrame.fromEulerAnglesXYZ(math.rad(90),math.rad(180),math.rad(360))
local TweenProperies = {
Size = Vector3.new(0.02, 0.02, Distance);
Transparency = 0.5
}
local FadeLaser = game.TweenService:Create(LaserPart, TweenInfo.new(0.1, Enum.EasingStyle.Linear, Enum.EasingDirection.In), TweenProperies)
FadeLaser:Play()
delay(0.11, function()
LaserPart:Destroy()
end)
elseif p2 == "SecondaryWallHit" then
local KnifeTracker = p4
local Knife = workspace:WaitForChild("tKnife"..KnifeTracker)
local Wallhit = Instance.new("Sound")
Wallhit.Parent = Knife
Wallhit.Volume = 0.5
Wallhit.SoundId = "rbxassetid://"..Sounds.WallHit[math.random(1, 2)]
Wallhit:Play()
Wallhit.Changed:Connect(function()
if Wallhit.IsPlaying == false then
Wallhit:Destroy()
end
end)
delay(10, function()
Knife:Destroy()
Knife = nil
end)
end
end
end)
Here is the server listener
Events.KnifeWeaponFunction.OnServerEvent:Connect(function(p, p1, p2, p3, p4, p5, p6, p7, p8)
local Char = p.Character
Events.KnifeWeaponFunction:FireAllClients("N/A", p2, Char, p4, p5, p6, p7, p8)
end)
Here’s is the function where the knife gets thrown, I am aware I’m using depreciated methods of taycasting, that’s just what I’m used to and it still works, I’ll upgrade soon!
local function ThrowKnife(MousePos)
Throwing = true
Events.KnifeSound:FireServer(Sounds.Throw, Char.Torso, 0.5)
KnifeTracker = KnifeTracker + 1
if KnifePower == "Normal" or KnifePower == "Explosive Knife" or KnifePower == "Electric Knife" then
local Touched = false
spawn(function()
Events.KnifeWeaponFunction:FireServer("N/A", "CreateNormal", "N/A", KnifeTracker)
end)
local Knife = Tool.Handle:Clone()
Knife.CanCollide = false
Knife.Anchored = true
Knife.CFrame = Char.Knife.Handle.CFrame
Knife.Name = "tKnife"..KnifeTracker
Knife.Parent = workspace
local ThrowLoop = Instance.new("Sound")
ThrowLoop.Name = "ThrowLoop"
ThrowLoop.Looped = true
ThrowLoop.Volume = 0.3
ThrowLoop.SoundId = "http://www.roblox.com/asset?id="..Sounds.ThrowLoop[1]
ThrowLoop.Parent = Knife
ThrowLoop:Play()
local NewRay = Ray.new(Knife.CFrame.p, (MousePos - Knife.CFrame.p).unit * 1000)
local Hit, Pos = game.Workspace:FindPartOnRayWithIgnoreList(NewRay, GenerateIgnoreList(Knife, Char))
local Distance = (Pos - Knife.CFrame.p).magnitude
spawn(function()
local P, K, D = Pos, Knife.CFrame.p, Distance
Events.KnifeWeaponFunction:FireServer("N/A", "AirSwoosh", "N/A", P, K, D, KnifeTracker)
end)
for i = 1, Distance, 6 do
DetectHuman(Knife, Char)
Knife.CFrame = CFrame.new(Pos, Knife.CFrame.p) * CFrame.new(0,0,i-Distance) * CFrame.fromEulerAnglesXYZ(math.rad(i*15),math.rad(180),math.rad(360))
wait()
end
spawn(function()
local P, K = Pos, Knife.CFrame.p
Events.KnifeWeaponFunction:FireServer("N/A", "Stop", "N/A", P, K, KnifeTracker)
end)
Knife.CFrame = CFrame.new(Pos, Knife.CFrame.p) * CFrame.new(0,0,0) * CFrame.fromEulerAnglesXYZ(math.rad(90),math.rad(180),math.rad(360))
local KnifeContents = Knife:GetChildren()
for k = 1, #KnifeContents do
if KnifeContents[k]:IsA("Sound") then
KnifeContents[k]:Destroy()
end
end
if Hit then
if game.Players:GetPlayerFromCharacter(Hit.Parent) == nil and game.Players:GetPlayerFromCharacter(Hit.Parent.Parent) == nil then
Knife.Anchored = true
spawn(function()
Events.KnifeWeaponFunction:FireServer("N/A", "WallHit", "N/A", KnifeTracker)
end)
local Wallhit = Instance.new("Sound")
Wallhit.Parent = Knife
Wallhit.Volume = 0.5
Wallhit.SoundId = "rbxassetid://"..Sounds.WallHit[math.random(1, 2)]
Wallhit:Play()
Wallhit.Changed:Connect(function()
if Wallhit.IsPlaying == false then
Wallhit:Destroy()
end
end)
delay(10, function()
Knife:Destroy()
end)
else
local char1, char2 = game.Players:GetPlayerFromCharacter(Hit.Parent), game.Players:GetPlayerFromCharacter(Hit.Parent.Parent)
if char1 ~= nil or char2 ~= nil and char1 ~= Char and char2 ~= Char then
local GetChar = nil
if Hit.Parent:FindFirstChild("Humanoid") and not Hit.Parent.Parent:FindFirstChild("Humanoid") then
GetChar = Hit.Parent
elseif Hit.Parent.Parent:FindFirstChild("Humanoid") and Hit.Parent:IsA("Accessory") and not Hit.Parent:FindFirstChild("Humanoid") then
GetChar = Hit.Parent.Parent
end
if GetChar ~= nil then
local GetTorso = GetChar:FindFirstChild("Torso")
local GetHuman = GetChar:FindFirstChild("Humanoid")
if GetTorso and GetHuman then
if Char then
Events.KnifeSound:FireServer(Sounds.ThrowHit, GetTorso, 0.5)
if game.ReplicatedStorage.Content.GameInProgress.Value == true then
if game.ReplicatedStorage.Content.GameMode.Value == "Wicked Murderer" then
Events.KnifeDamage:FireServer(GetHuman, 100)
elseif game.ReplicatedStorage.Content.GameMode.Value == "Freeze Tag" then
if GetChar:FindFirstChild("Role") and GetChar.Role.Value == "Bystander" then
Events.FreezePlayerKnife:FireServer(GetChar)
end
else
-- any other gamemode not specified
Events.KnifeDamage:FireServer(GetHuman, 100)
end
elseif game.ReplicatedStorage.Content.GameInProgress.Value == false then
Events.KnifeDamage:FireServer(GetHuman, 100)
-- when a game is not occuring
end
end
spawn(function()
Events.KnifeWeaponFunction:FireServer("N/A", "DestroyKnife", "N/A", KnifeTracker)
end)
Knife:Destroy()
end
end
end
end
end
elseif KnifePower == "Laser Knife" then
local Touched = false
spawn(function()
Events.KnifeWeaponFunction:FireServer("N/A", "CreateLaser", "N/A", KnifeTracker)
end)
local Knife = Tool.Handle:Clone()
Knife.CanCollide = false
Knife.Anchored = true
Knife.CFrame = Tool.Handle.CFrame
Knife.Name = "tKnife"..KnifeTracker
Knife.Parent = workspace
local NewRay = Ray.new(Knife.CFrame.p, (MousePos - Knife.CFrame.p).unit * 1000)
local Hit, Pos = game.Workspace:FindPartOnRay(NewRay, Char, false, true)
local Distance = (Pos - Knife.CFrame.p).magnitude
if game.Players.LocalPlayer.Character == Char then
Events.KnifeSound:FireServer(Sounds.Laser, Char.Torso, 0.5)
Events.KnifeSound:FireServer(Sounds.LaserSoundEffects, Char.Torso, 0.3)
end
spawn(function()
local P, K, D = Pos, Knife.CFrame.p, Distance
Events.KnifeWeaponFunction:FireServer("N/A", "CreateLaserBeam", "N/A", KnifeTracker, P, K, D)
end)
local LaserPart = Instance.new("Part")
LaserPart.Name = "Laser"..KnifeTracker
LaserPart.CanQuery = false
LaserPart.Anchored = true
LaserPart.CanCollide = false
LaserPart.Material = "Neon"
LaserPart.Color = Color3.new(1, 0, 0)
LaserPart.TopSurface = Enum.SurfaceType.Smooth
LaserPart.BottomSurface = Enum.SurfaceType.Smooth
LaserPart.Size = Vector3.new(0.2, 0.2, Distance)
LaserPart.CFrame = CFrame.new(Pos, Knife.CFrame.p) * CFrame.new(0, 0, (-Distance/2) + 2)
LaserPart.Parent = workspace
spawn(function()
local D, P, K = Distance, Pos, Knife.CFrame.p
Events.KnifeWeaponFunction:FireServer("N/A", "AnimateLaser", "N/A", KnifeTracker, D, P, K)
end)
for i = 10000, Distance do
Knife.CFrame = CFrame.new(Pos, Knife.CFrame.p) * CFrame.new(0,0,i-Distance) * CFrame.fromEulerAnglesXYZ(math.rad(90),math.rad(180),math.rad(360))
end
Knife.CFrame = CFrame.new(Pos, Knife.CFrame.p) * CFrame.new(0,0,0) * CFrame.fromEulerAnglesXYZ(math.rad(90),math.rad(180),math.rad(360))
local TweenProperies = {
Size = Vector3.new(0.02, 0.02, Distance);
Transparency = 0.5
}
local FadeLaser = game.TweenService:Create(LaserPart, TweenInfo.new(0.1, Enum.EasingStyle.Linear, Enum.EasingDirection.In), TweenProperies)
FadeLaser:Play()
delay(0.11, function()
LaserPart:Destroy()
end)
if Hit then
if game.Players:GetPlayerFromCharacter(Hit.Parent) ~= nil or game.Players:GetPlayerFromCharacter(Hit.Parent.Parent) ~= nil then
local CChar = nil
if Hit.Parent:FindFirstChild("Humanoid") and not Hit.Parent.Parent:FindFirstChild("Humanoid") then
CChar = Hit.Parent
elseif Hit.Parent:IsA("Accessory") and Hit.Parent.Parent:FindFirstChild("Humanoid") then
CChar = Hit.Parent.Parent
end
if CChar ~= nil and CChar ~= Char then
local GetTorso = CChar:FindFirstChild("Torso")
local GetHuman = CChar:FindFirstChild("Humanoid")
if GetTorso and GetHuman then
Events.KnifeSound:FireServer(Sounds.ThrowHit, GetTorso, 0.5)
if game.ReplicatedStorage.Content.GameInProgress.Value == true then
if game.ReplicatedStorage.Content.GameMode.Value == "Wicked Murderer" then
Events.KnifeDamage:FireServer(GetHuman, 100)
elseif game.ReplicatedStorage.Content.GameMode.Value == "Freeze Tag" then
if CChar:FindFirstChild("Role") and CChar.Role.Value == "Bystander" then
Events.FreezePlayerKnife:FireServer(CChar)
end
else
-- any other gamemode not specified
Events.KnifeDamage:FireServer(GetHuman, 100)
end
elseif game.ReplicatedStorage.Content.GameInProgress.Value == false then
Events.KnifeDamage:FireServer(GetHuman, 100)
-- when a game is not occuring
end
spawn(function()
Events.KnifeWeaponFunction:FireServer("N/A", "DestroyKnife", "N/A", KnifeTracker)
end)
Knife:Destroy()
end
end
else
spawn(function()
Events.KnifeWeaponFunction:FireServer("N/A", "SecondaryWallHit", "N/A", KnifeTracker)
end)
Knife.Anchored = true
local Wallhit = Instance.new("Sound")
Wallhit.Parent = Knife
Wallhit.Volume = 0.5
Wallhit.SoundId = "rbxassetid://"..Sounds.WallHit[math.random(1, 2)]
Wallhit:Play()
Wallhit.Changed:Connect(function()
if Wallhit.IsPlaying == false then
Wallhit:Destroy()
end
end)
delay(10, function()
Knife:Destroy()
end)
end
end
end
Throwing = false
end