Shield only shows for the client

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.

image

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 :slight_smile:

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
image
image

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.

image
image

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