Gun works in play mode but not in team test

I have a gun in my game.

local player = game.Players.LocalPlayer
local char = player.Character


function GetBullet()
	local p = Instance.new("Part")
	p.Parent = workspace
	p.Size = Vector3.new(.1, .1, .5)
	p.BrickColor = BrickColor.Yellow()
	p.CanCollide = false
	Instance.new("BodyVelocity", p)
	return p
end

script.Parent.Equipped:Connect(function(mouse)
	mouse.Button1Down:Connect(function()
		local mH = mouse.Hit
		local bullet = GetBullet()
		bullet.CFrame = script.Parent.Handle.CFrame * CFrame.new(0, 0, -1.5)
		bullet.CFrame = CFrame.new(bullet.Position, mH.p)
		bullet.BodyVelocity.Velocity = bullet.CFrame.LookVector * 120
		bullet.Touched:Connect(function(hit)
			local Humanoid = hit.Parent:FindFirstChild("Humanoid")
			if Humanoid then
				Humanoid:TakeDamage(40)
				bullet:Destroy()
			end
		end)
	end)
end)

You’re creating the bullet in a local script, which is probably the issue.

1 Like

First things first: I’m noticing a few bad practices.
You shouldn’t use game.ServiceName, always use game:GetService()

local Players = game:GetService("Players")
local Player = Players.LocalPlayer
local Character = Player.Character

The Parent property should always, ALWAYS be set last. Also, Instance.new("Object", Parent) should be avoid being used whenever possible. There are major performance issues with it.

function GetBullet()
	local p = Instance.new("Part")
	p.Size = Vector3.new(0.1, 0.1, 0.5) -- This isn't a big deal, but it is significantly easier to read 0.1 rather than .1
	p.BrickColor = BrickColor.Yellow()
	p.CanCollide = false
	local BodyVelocity = Instance.new("BodyVelocity")
	BodyVelocity.Parent = p
	p.Parent = workspace
	return p
end

And as @TheCreator1944 said, you are creating the bullet locally on the client. Meaning it does not replicate to the server. You’ll need to set up a RemoteEvent to tell a script on the server to create and fire the bullet.

1 Like

you creating everything in a local script including the damage you need to use Remote Event

so only the client will see it and its not visible to anyone

Script in ServerScriptService:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local BulletFired = Instance.new("RemoteEvent")
BulletFired.Name = "BulletFired"
BulletFired.Parent = ReplicatedStorage

function GetBullet()
	local p = Instance.new("Part")
	p.Size = Vector3.new(0.1, 0.1, 0.5)
	p.BrickColor = BrickColor.Yellow()
	p.CanCollide = false
	local BodyVelocity = Instance.new("BodyVelocity")
	BodyVelocity.Parent = p
	p.Parent = workspace
	return p
end

BulletFired.OnServerEvent:Connect(function(Player, Hit)
	local Bullet = GetBullet()
	local Gun = Player.Character:FindFirstChild("Gun") -- Or whatever the tool is called
	Bullet.CFrame = Gun.Handle * CFrame.new(0, 0, -1.5)
	Bullet.CFrame = CFrame.new(Bullet.Position, Hit)
	Bullet.BodyVelocity.Velocity = Bullet.CFrame * 120
	Bullet.Touched:Connect(function(hit)
		local Humanoid = hit.Parent:FindFirstChild("Humanoid")
		if Humanoid and Humanoid:IsA("Humanoid") then
			Humanoid:TakeDamage(40)
			Bullet:Destroy()
		end
	end)
end)

LocalScript in Gun:

local Players = game:GetService("Players")
local Player = Players.LocalPlayer
local Mouse = Player:GetMouse()
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local BulletFired = ReplicatedStorage:WaitForChild("BulletFired")
local COOLDOWN_TIME = 1
local Debounce = false --Add a debounce so it can't be spammed

script.Parent.Activated:Connect(function()
	if Debounce then return end
	Debounce = true
	
	BulletFired:FireServer(Mouse.Hit)
	
	wait(COOLDOWN_TIME)
	Debounce = false
end)

EDIT: I am currently tweaking this, as I just realized a security problem with this code. Do not use it in its current state!

EDIT 2: It is now corrected, sorry about that!