luaroblox

Passing a Model through a Remote Function


I am having trouble passing a model through a remote event

the model (tower) is stored originally in replicated storage before being cloned and moved a folder in the workspace (local script)

tower = game.ReplicatedStorage.Towers.Boxer:Clone()
        
tower.Parent = workspace.Map.TowersToPlace

Then I pass it through the remote event.

print(tower)    replicatedStorage.SpawnTowerEvent:FireServer(tower, mouse.Hit.Position)
end)

The print line is printing the tower correctly but the server script is erroring saying the tower variable is nil (server script)

game.ReplicatedStorage.SpawnTowerEvent.OnServerEvent:Connect(function(plr, towerToPlace, pos)
    print(towerToPlace)
end)

-- returns nil

Anyone know why the variable is not being passed despite being defined correctly in the local script.


Solution

  • Something to keep in mind is that objects created in LocalScripts only exist on the client and are not replicated, and Scripts execute on the server.

    So when you pass the Model reference with the RemoteEvent, the server has no idea what you are talking about because you are referencing a non-existing object in its eyes. And according to the docs regarding the limitations of RemoteEvent arguments :

    Non-Replicated Instances

    If a RemoteEvent or RemoteFunction passes a value that's only visible to the sender, Roblox doesn't replicate it across the client-server boundary and passes nil instead of the value. For example, if a Script passes a descendant of ServerStorage, the client listening to the event will receive a nil value because that object isn't replicable for the client.

    That's why you are seeing nil when you try to print it out.

    So unless creating things on the client is a specific design decision, a better way to structure your code is to have the server create your tower for you, and your LocalScript just tells the server which tower to create and where.

    So in your LocalScript :

    -- tell the server to create a tower
    local tower = "Boxer"
    game.ReplicatedStorage.SpawnTowerEvent:FireServer(tower, mouse.Hit.Position)
    

    Then your Script finds which tower the client is talking about and creates it :

    game.ReplicatedStorage.SpawnTowerEvent.OnServerEvent:Connect(function(plr, towerName, pos)
        -- make sure that the requested tower actually exists
        local towerTemplate = game.ReplicatedStorage.Towers[towerName]
        if not towerTemplate then
            warn(string.format("Could not find a tower named %s", tostring(towerName))
            return
        end
    
        -- TO DO : make sure the player can create this kind of tower
    
        -- clone the tower into the workspace
        local towerToPlace = towerTemplate:Clone()
        towerToPlace:PivotTo(CFrame.new(pos))
        towerToPlace.Parent = workspace.Map.TowersToPlace
        print(towerName, " created at ", pos)
    end)