In a weapon system I constructed, I cast a ray from the center of the screen straight out to get whatever the player has under their crosshair. I then use an attachment at the end of the gun barrel and the endpoint of the original ray cast to send the bullet to the end position. This is because the game is in 3rd person. The issue is that whenever I and the other developers hop into the published version of the game, whoever joins first has the best experience. I think this is because the host server will be set up wherever the first player joins, but I am not sure. Everyone else who joins after that is situated in different countries and when they fire guns, the fire rate is slowed way down and hitmakers barely register. Is this due to networking issues or could this be an error in the code?
Client Side Fire Function
function WeaponManager:Fire()
local origin, direction = self.Crosshair:Raycast()
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = RaycastFilters:GetRaycastFilter(self.Character)
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
-- local raycastResult = workspace:Raycast(origin, direction, raycastParams)
local raycastResult = workspace:Raycast(origin, direction * self.MaxBulletDistance, raycastParams)
local hitPosition = raycastResult and raycastResult.Position or direction * self.MaxBulletDistance
if raycastResult == nil then
local currentCamera = workspace.CurrentCamera
local focus = currentCamera.Focus
local campos = currentCamera.CFrame.Position
local diff = focus.Position - campos
diff = diff * 20
hitPosition = campos + diff
else
hitPosition = raycastResult and raycastResult.Position
end
local nearbyplayers = WeaponManager:GetPlayers()
if VISUALIZE_BULLETS then
local part = Instance.new("Part")
part.Anchored = true
part.CanCollide = false
part.Color = if raycastResult then Color3.fromRGB(0, 255, 0) else Color3.fromRGB(255, 0, 0)
if raycastResult then
part.Size = Vector3.new(0.1, 0.1, raycastResult.Distance)
part.CFrame = CFrame.new(origin, raycastResult.Position) * CFrame.new(0, 0, -(raycastResult.Distance / 2))
else
part.Size = Vector3.new(0.1, 0.1, self.MaxBulletDistance)
part.CFrame = CFrame.new((origin + hitPosition) / 2, hitPosition)
end
part.Parent = workspace
Debris:AddItem(part, VISUALIZED_BULLETS_LIFETIME)
end
if not self.HasScope then
self.Handle.GunFirePoint.Gas:Emit(1)
self.Handle.GunFirePoint.Sparkles:Emit(1)
end
if Remotes.Weapons.Fire:InvokeServer(hitPosition, nearbyplayers, origin, direction, self.Tool) then
print("hit character!")
end
self.LastShot = os.clock()
self.Animations.Shoot:Play()
--self:UpdateUI()
self.Crosshair:Shoot()
self:ApplyRecoil()
end
Server Fire Function
function Remotes.Fire.OnServerInvoke(player: Player, hitPosition: Vector3, nearbyplayers, origin: Vector3, direction: vector3, tool)
local profile = DataService:GetProfile(player)
local characterController = CharacterController.GetController(player)
if not profile or not characterController then
return false
end
local tool = getPlayerTool(player)
local toolHandle = tool and tool.Handle or nil
if not toolHandle or not profile then
return false
elseif tool:GetAttribute("Clip") < 1 then
return false
end
local toolData = ToolConfiguration:GetToolData(tool)
local weaponData = profile.Data.Weapons[tool.Name]
if not weaponData.Clip then
weaponData.Clip = toolData.ClipSize
end
if not weaponData.Ammo then
weaponData.Ammo = toolData.MaxAmmo
end
if not weaponData then
return false
elseif weaponData.Clip < 1 then
return false
end
raycastParams.FilterDescendantsInstances = RaycastFilters:GetRaycastFilter(player.Character)
local raycastResult = workspace:Raycast(
origin, direction * toolData.MaxMouseDistance, raycastParams
)
weaponData.Clip -= 1
tool:SetAttribute("Clip", weaponData.Clip)
if not raycastResult or not raycastResult.Instance then
--Remotes.BulletFired:FireAllClients(player, toolHandle, false, {
-- Position = hitPosition,
--})
for i, x in pairs(nearbyplayers) do
Remotes.BulletFired:FireClient(x, player, toolHandle, false, {
Position = hitPosition,
})
end
return false
end
local hitPart = raycastResult.Instance
local character = hitPart.Parent
print(hitPart.Name.." - ".. character.Name)
-- hitPosition = raycastResult.Position
if tool.Name == "HeavySniper" then
for i, x in pairs(nearbyplayers) do
if x == player then
continue
end
Remotes.BulletFired:FireClient(x, player, toolHandle, character:FindFirstChild("Humanoid") ~= nil, {
Position = hitPosition,
Normal = raycastResult.Normal,
Material = raycastResult.Material,
})
end
Remotes.SniperBulletFired:FireClient(player,player, toolHandle, character:FindFirstChild("Humanoid") ~= nil, {
Position = hitPosition,
Normal = raycastResult.Normal,
Material = raycastResult.Material,
})
else
for i, x in pairs(nearbyplayers) do
Remotes.BulletFired:FireClient(x, player, toolHandle, character:FindFirstChild("Humanoid") ~= nil, {
Position = hitPosition,
Normal = raycastResult.Normal,
Material = raycastResult.Material,
})
end
end
if not character then
return false
elseif not character:FindFirstChild("Humanoid") then
return false
end
local playerHit = Players:GetPlayerFromCharacter(character)
local damage = getRangeBasedDamage(player.Character, character, tool)
if hitPart.Name == "Head" then
damage *= 1.5
end
if playerHit then
print("Player hit")
characterController = CharacterController.GetController(playerHit)
if characterController then
if character.Humanoid.Health - damage < 2 then
character.Humanoid.Health = 100
if character.Name ~= "Dummy" then
character.HumanoidRootPart.CFrame = CFrame.new(-51.151, 1923.913, -345.991)
end
else
character.Humanoid:TakeDamage(damage)
end
end
else
if character.Humanoid.Health - damage < 2 then
character.Humanoid.Health = 100
if character.Name ~= "Dummy" then
character.HumanoidRootPart.CFrame = CFrame.new(-51.151, 1923.913, -345.991)
end
else
character.Humanoid:TakeDamage(damage)
end
end
bleedCharacter(hitPart)
DamageBillboardHandler.ShowDamageBillboard(player, damage, hitPart)
return true
end