What is the best way to have the part replicated before receiving a RemoteEvent?

I made a server script that creates a part and parents it to the workspace. After that, the script fires a remote to a client with an instance as a parameter:

Server

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local DataRelatedToThePart = {}

-- The instance
local Part = Instance.new("Part", workspace)

-- Firing the remote
ReplicatedStorage.RemoteEvent:FireAllClients(Part, DataRelatedToThePart)

The problem is the part is nil when the client receives the event.

Client

local ReplicatedStorage = game:GetService("ReplicatedStorage")

-- Receiving the event
ReplicatedStorage.RemoteEvent.OnClientEvent:Connect(function(Part:Part, DataRelatedToThePart:{any})
	print(Part, DataRelatedToThePart) -- nil, {}
end)

If I use task.wait(4), the part will not be nil. But I don’t want the event to be called as soon as it can.

What is the best way to have the part replicated before receiving a RemoteEvent?

Where do you add the task.wait so it would work and you want it to work without it, correct?

Here is where you would add task.wait() for it to work.
Server

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local DataRelatedToThePart = {}

-- The instance
local Part = Instance.new("Part", workspace)

-- Leave time for replication to complete
task.wait(4)

-- Firing the remote
ReplicatedStorage.RemoteEvent:FireAllClients(Part, DataRelatedToThePart)

Yes.

Here I do not want:

  • Leaving time for replication and hoping it’s done.
  • Repetitive remote firing between the client and server to check for replication.
  • Using :WaitForChild()

The replicated part must be in the parameter when the client receives the event.

Where are your scripts located?
I don’t understand how the server is able to fire the event ‘AFTER’ the player has joined, unless you use a wait

Why? That’s stupid, It’s the most efficient and the best way to do it

The code you are seeing is a recreation of a section in my scripts.

The code runs during the game after certain in game events.

1 Like

Do you have streaming enabled? If not, there’s no problem with using WaitForChild() while specifying the name and place to wait.

  • When streaming is disabled, the part will be sent if it was successfully parented to workspace on the server by the engine beforehand (because of the replication order).

  • When streaming is enabled, there are no guarantees. In some cases it might never stream in. There’s a trick with object values and ObjectValue.Changed:Wait(), but it’s best to avoid sending parts in the first place.

Ok, assuming the player is already joined and the client script loaded by the time the server script runs, then your original post, should contain the part data.

There must be something else going on with your scripts.

EDIT : I forgot about streaming, I was assuming the part was near the player.
@fellow_meerkat has a good suggestion.

I’ve stated I do not wish to use these methods and I would like to know if I can allow the client to replicate the part before it receives the event.

If you are unsure on how to accomplish this then please do not respond.

So in the Server after creating the part you could try WaitForChild(workspace.Part) but idk if that would work. What would work is giving the Part on the Server a Name and then you can search it on the client and use waitForChild on it

image
Yes, streaming is enabled.

Thank you, this is a solution.

Although I would prefer to keep streaming and for my case specifically I’ve thought of a solution.

That sounds like exactly what I need for my project.

Can I make a model behave as if ‘streaming was disabled’ but for an individual player or is .ModelStreamingMode for all players?

I wrote that, then I went and read the docs on it, and I am not sure it works for things created past a certain point during the server loading.

I have never used it, and not sure exactly how it works, thats why I deleted my comment.

You would have to research it.

Okay thanks, I’ll look into it!

Better to find some workaround then disable streaming - although I believe it still needs some more development to equip us with better control for cases like this.

Just to elaborate, an object has to be scheduled for replication before the remote is fired in order to exist in the same frame when the signal is received.

So we’re left with workarounds:

  • If we’re certain that the object is going to be in player’s replication radius, it’s alright to send its name and the place to look (that already exists locally).

  • The ObjectValue trick involves setting its value to the part and parenting both to a replicated place before sending the ObjectValue. It should be available to the client immediately, and the part 1) should be referred by Object.Value right away or 2) referred once .Changed fires.

  • For multiple parts we can use CollectionService.

  • I think @SelDraken’s idea is great. It’s definitely a reliable approach. And yes, you can also make it persistent for individuals (model:AddPersistentPlayer(player))


Looks like it is designed to be for all players.

@fellow_meerkat showed a :AddPersistentPlayer() method that allows you to set the players the model will stream as ‘Enum.ModelStreamingMode.Persistent’ to.

This is what I tried:

local Player -- Player instance
local Model -- Model instance

Model.ModelStreamingMode = Enum.ModelStreamingMode.PersistentPerPlayer
Model:AddPersistentPlayer(Player)

Is this expected to have the same result as disabling streaming in workspace, except it is for the model’s descendants?

Disabling streaming fixed the replication issue but setting ModelStreamingMode to Enum.ModelStreamingMode.PersistentPerPlayer does not fix it.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.