This is an intresting problem. And I never played undertale.
I assume you mean each player move a heart? What I would do would be that each player spawn their character still, and the gui just shows the positions of the players…
nobody would be wiser since gui should cover whole screen right?
using remotevents will definitely work, inside a serverscript that will control the guis create a table for each player starting with some UDim2 value from which you will use FireClient to send the table to all players, from a localscript everytime the player wants to move you will fire the remote event with the direction (or key) the player wants to move then just change the players value in the table and everytime the client recieves the table from the server it will just position the guis to that UDim2 position.
You don’t need to put anything in replicated storage, considering each client can see any data held by the server.
So all you need to do is set an Attribute on the player instance for each player from the server
All clients can either loop through the player list, reading the attribute for position,
or have events checking if an attribute has changed
The real issue I think is how will the server know when the player has moved. You need to use a remote event to tell the server when you are moving the player. So it can update your attribute, and all other clients can know you moved.
while wait() do
if #game.Players:GetChildren() > 1 then
spawn(function()
for _, Players in pairs(game.Players:GetChildren()) do
if Players ~= nil then
for _, Dec in pairs(Players.PlayerGui:GetDescendants()) do
if typeof(Dec) == 'Instance' and Dec:IsA("GuiObject") then
if Dec:IsA("ImageLabel") then
local base = game.Players:GetChildren[1]:GetDescendants()
for _, data in pairs(base) do
if data.Name == Dec.Name then
base = data
end
end
Dec.Image = base.Image
end
for _, Dec in pairs(Players.PlayerGui:GetDescendants()) do
if typeof(Dec) == 'Instance' and Dec:IsA("GuiObject") then
if Dec:IsA("TextButton") then
local base = game.Players:GetChildren[1]:GetDescendants()
for _, data in pairs(base) do
if data.Name == Dec.Name then
base = data
end
end
Dec.Text = base.Text
end
end
end
end
end
end
end
Add any properties you want, and any more GuiObjects you want.
What this will do is it will get a base, which is off the first player that joined the server, then it will get all of the guis and properties off of the base, and make sure that everything else is exactly those properties.
-- Client-side script
local player = game.Players.LocalPlayer
local userInputService = game:GetService("UserInputService")
local remoteFunction = game.ReplicatedStorage.MoveRemoteFunction
local function onInput(input)
remoteFunction:InvokeServer(input)
end
userInputService.InputBegan:Connect(function(input, gameProcessedEvent)
if not gameProcessedEvent then
onInput(input.KeyCode)
end
end)
-- Server-side script
local remoteFunction = Instance.new("RemoteFunction")
remoteFunction.Name = "MoveRemoteFunction"
remoteFunction.Parent = game.ReplicatedStorage
remoteFunction.OnServerInvoke = function(player, input)
-- Process the input and update player position
-- You might need to handle player movement logic, collision detection, etc.
-- Update the player's position and return the new position
return newPosition
end
-- Server-side script
local remoteEvent = Instance.new("RemoteEvent")
remoteEvent.Name = "PlayerPositionUpdate"
remoteEvent.Parent = game.ReplicatedStorage
-- Inside the part where you update the player's position on the server
remoteEvent:FireAllClients(player, newPosition)
-- Client-side script
local remoteEvent = game.ReplicatedStorage.PlayerPositionUpdate
remoteEvent.OnClientEvent:Connect(function(player, newPosition)
-- Update the player's position on the screen
end)