Hello there,
I found out my shield I made apparently only works for the client, nobody else can see it. Does anyone know how to fix it? I have no clue what is causing this as it works normally. I have this UI which lets you select your tool and shield and it’ll clone what you choose and put it in your Backpack. The shield is actually a model, would that have anything to do with why it’s not showing for everyone else? Any help is appreciated.
What's occuring
Shield File
Shield.rbxm (32.1 KB)
2 Likes
Just make sure that the shield is being equipped via the server rather than through the client. (i.e not a localscript - or at least use a remote event to signal the server to commence equipping of the shield)
1 Like
It is a local script inside a server.
The code then has to be run from the server script rather than the localscript. Just having one inside the other doesn’t affect the environment that the code is ran in (either client or server).
1 Like
Would changing it to a server fix it or do I have to fire an event and put the code outside the shield model.
Having looked at the provided model file, the way I would solve this is by having the core_client script use remote events to signal when the shield should be equipped and raised.
-- core_client
local equip_event = script.Parent.Equip_Event
local raise_event = script.Parent.Raise_Event
player:GetMouse().KeyDown:connect(function(k)
if not character:findFirstChild("Left Arm") then return end
if not character:findFirstChild("Torso") then return end
if not character.Torso:findFirstChild("Left Shoulder") then return end
if k == "v" then --Spawns the Shield to the Left Arm
equip_event:FireServer() -- requesting the server to equip
elseif k == "x" and equipped then --Raise Shield
raise_event:FireServer() -- requesting the server to raise
end
end)
-- core
script.Equip_Event.OnServerEvent:Connect(function(player, ...)
-- run code to equip shield to player
end)
-- same for raising
All of this code is literally just off the top of my head, and probably isn’t the best solution either, but this is how I would do it.
The scripts can remain where they are. Just two new remote events need to be created and placed under the core script (or just wherever, as long as both the client and server can see and access them - i.e not in serverstorage).
Hope this helped
1 Like
I am having a bit of trouble, do you know if I set this up right?
LocalScript
local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:wait()
local equipped = false
local up = false
local baseShield = script.Parent.Parent
local shield
local UserInputService = game:GetService('UserInputService')
local equip_event = game.ReplicatedStorage.Events:WaitForChild("Equip_Event")
local raise_event = game.ReplicatedStorage.Events:WaitForChild("Raise_Event")
player:GetMouse().KeyDown:connect(function(k)
if not character:findFirstChild("Left Arm") then return end
if not character:findFirstChild("Torso") then return end
if not character.Torso:findFirstChild("Left Shoulder") then return end
if k == "v" then --Spawns the Shield to the Left Arm
equip_event:FireServer() -- requesting the server to equip
elseif k == "x" and equipped then --Raise Shield
raise_event:FireServer() -- requesting the server to raise
end
end)
I have this in the LocalScript
ServerScript
game.ReplicatedStorage.Events:WaitForChild("Equip_Event").OnServerEvent:Connect(function(player, ...)
equipped = not equipped
lsh.Part1 = character["Left Arm"]
print("Step1")
if equipped then
shield = baseShield:clone()
local handle = shield:findFirstChild("Handle")
for n,i in pairs(shield:GetChildren()) do
if i.Name ~= "Handle" and i:IsA("BasePart") then
local nw = Instance.new("Weld",i)
nw.Part0 = handle
nw.Part1 = handle
nw.C0 = handle.CFrame:inverse()
nw.C1 = i.CFrame:inverse()
elseif (i:IsA("Script") or i:IsA("LocalScript")) then
i:remove()
end
end
handle.Anchored = false
print("Step2")
shield.Parent = character
shield:MakeJoints()
local nw = Instance.new("Weld",character["Left Arm"])
nw.Part0 = character["Left Arm"]
nw.Part1 = handle
nw.C1 = CFrame.new()
nw.Name = "LeftGrip"
else
if character["Left Arm"]:FindFirstChild("LeftGrip") then
character["Left Arm"].LeftGrip:remove()
end
if shield then
shield:remove()
end
print("Step3")
end
end)
game.ReplicatedStorage.Events:WaitForChild("Raise_Event").OnServerEvent:Connect(function(player, ...)
up = not up
if up then
lsh.Part1 = nil
local w = Instance.new("Weld",shield)
w.Part0 = character.Torso
w.Part1 = character["Left Arm"]
w.C1 = CFrame.new(1.2,-.25,0.05) * CFrame.fromEulerAnglesXYZ(math.rad(-75),math.rad(55),0)
else
for n,i in pairs(shield:GetChildren()) do
if i.ClassName == "Weld" then
if i.Part0 == character.Torso then
i.Parent = nil
end
end
end
lsh.Part1 = character["Left Arm"]
end
end)
And this in a ServerScript in the Workspace. The events are in a folder called “Events” in the ReplicatedStorage.
Didn’t seem to work for me though
From a glance, I can see that the the code in the serverscript won’t know what the character is, the shield, baseshield etc. because as far as I can see, they haven’t been passed as parameters or haven’t been created as variables within the same script.
Also, any errors?
1 Like
I redefined the same variables in the localscript to the serverscript.
The only error I got was in the ServerScript on line 7
the character variable should be defined within the event functions. Like this:
event.OnServerEvent:Connect(function(player)
local character = player.Character or player.CharacterAdded:Wait()
end)
instead of outside of the function, since the server hasn’t got access to any specific player outside of the events.
1 Like
I fixed that then got another error saying the shield couldn’t clone on line 13.
Would that need to be in the LocalScript
Does the server have baseShield defined? Or passed to it from the localscript? If not, that needs to be done too.
1 Like
Baseshield is defined as
local baseShield = script.Parent.Parent
Which is inside the ServerScript and LocalScript
Can I see the hierarchy of each script?
1 Like
Sure.
ServerScript in ServerScriptStorage
game.ReplicatedStorage.Events:WaitForChild("Equip_Event").OnServerEvent:Connect(function(player, ...)
local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:wait()
local equipped = false
local up = false
local baseShield = script.Parent.Parent
local shield
local UserInputService = game:GetService('UserInputService')
local lsh = character.Torso:findFirstChild("Left Shoulder")
equipped = not equipped
lsh.Part1 = character["Left Arm"]
print("Step1")
if equipped then
shield = baseShield:clone()
local handle = shield:findFirstChild("Handle")
for n,i in pairs(shield:GetChildren()) do
if i.Name ~= "Handle" and i:IsA("BasePart") then
local nw = Instance.new("Weld",i)
nw.Part0 = handle
nw.Part1 = handle
nw.C0 = handle.CFrame:inverse()
nw.C1 = i.CFrame:inverse()
elseif (i:IsA("Script") or i:IsA("LocalScript")) then
i:remove()
end
end
handle.Anchored = false
print("Step2")
shield.Parent = character
shield:MakeJoints()
local nw = Instance.new("Weld",character["Left Arm"])
nw.Part0 = character["Left Arm"]
nw.Part1 = handle
nw.C1 = CFrame.new()
nw.Name = "LeftGrip"
else
if character["Left Arm"]:FindFirstChild("LeftGrip") then
character["Left Arm"].LeftGrip:remove()
end
if shield then
shield:remove()
end
print("Step3")
end
end)
game.ReplicatedStorage.Events:WaitForChild("Raise_Event").OnServerEvent:Connect(function(player, ...)
local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:wait()
local equipped = false
local up = false
local baseShield = script.Parent.Parent
local shield
local lsh = character.Torso:findFirstChild("Left Shoulder")
local UserInputService = game:GetService('UserInputService')
up = not up
if up then
lsh.Part1 = nil
local w = Instance.new("Weld",shield)
w.Part0 = character.Torso
w.Part1 = character["Left Arm"]
w.C1 = CFrame.new(1.2,-.25,0.05) * CFrame.fromEulerAnglesXYZ(math.rad(-75),math.rad(55),0)
else
for n,i in pairs(shield:GetChildren()) do
if i.ClassName == "Weld" then
if i.Part0 == character.Torso then
i.Parent = nil
end
end
end
lsh.Part1 = character["Left Arm"]
end
end)
LocalScript inside the Shield
local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:wait()
local equipped = false
local up = false
local baseShield = script.Parent.Parent
local shield
local UserInputService = game:GetService('UserInputService')
local equip_event = game.ReplicatedStorage.Events:WaitForChild("Equip_Event")
local raise_event = game.ReplicatedStorage.Events:WaitForChild("Raise_Event")
player:GetMouse().KeyDown:connect(function(k)
if not character:findFirstChild("Left Arm") then return end
if not character:findFirstChild("Torso") then return end
if not character.Torso:findFirstChild("Left Shoulder") then return end
if k == "v" then
equip_event:FireServer()
-- requesting the server to equip
elseif k == "x" and equipped then --Raise Shield
raise_event:FireServer() -- requesting the server to raise
end
end)
And both Events are inside a folder called “Events” in the ReplicatedStorage and are labled “Equip_Event” and “Raise_Event”
I think the reason it’s not working is that in the ServerScript baseShield is defined as local baseShield = script.Parent.Parent
But is not a member of the Script since it’s inside the Backpack. Is there a way across that?
Okay so in the serverscript, you’ll need to change the
local baseShield = script.Parent.Parent
to point to where the actual shield is. Currently it’s pointing to the DataModel which is why you can’t clone it.
For example, if the shield was in the workspace and named Basic_Shield, this would be your code in the serverscript:
local baseShield = game.Workspace.Basic_Shield
As you say it is in the backpack, you will have to point it to there.
local baseShield = player.Backpack.Basic_Shield
1 Like
What if I have 37 different shields. Would I do game.Workspace.Shield1 or game.Workspace.Shield2 etc
What you should do instead then, is send the baseShield as a parameter through the remote event from the localscript.
1 Like
How would I do that? I am a bit confused by what that means.
So in the local script, when firing the event to the server, add in the parameter for the baseShield.
— local script
Event:FireServer(baseShield)
— server script
Event.OnServerEvent:Connect(function(player,baseShield)
end)
(Now on mobile, hence the lack of code formatting, sorry!)
1 Like