Is there a way to have a workspace object only be visible to the server?

Quick question I had, and I am uncertain when I would need this.

But I was wondering, is it possible to have something such as parts or well… Any physical object to ONLY be visible to the server?

And I know there is a way to do this, simply just by removing the object clientside and it still exists serverside.

But I mean, if I wanted a object to be in the workspace specifically (so physics objects can touch it) but it is ONLY visible to the server and doesn’t even get replicated to the client.
Even when joining the game should no client-script be required to delete it.
As soon as the player joins, I don’t want the object to ever replicate to the client, it has to remain always invisible, unrendered, unreferencable by local scripts, no data send about it to the client ever.

How would I do this? Is there a way to script this?

6 Likes

No, you can’t. This is currently impossible. You can simulate the effect it would have, but you can’t have something just not replicate as far as I’m aware.

4 Likes

You could make it so that when the player joins, it fires a remoteEvent which makes it invisible and non-collidable meaning its still there but to the player it isn’t.

You can look up some remote event uses here.

It’s currently impossible to make a workspace object never replicate to the client without having a client-script delete it?

If you want a reason/use where I could use it for, basically customized streaming I guess?

I want maps to unload for players but stay loaded for NPCs so they won’t fall through if network ownership would be set back to server (nil).
Like, have a massive map partially unload but NPCs must stay on it (in case another player is nearby with higher render distance).

No, it is sadly not currently possible to do that.

However, you could do a simple work around and just anchor the NPCs torso (I believe) or save their position. This way, you’ll get the answer you’re looking for without lag.

There’s probably a better way to do this, but you can use simplified geometry on the server to put minimal stress when replicating it, and then have the client load the “full” version of whatever chunks you want.

1 Like

Unfortunately no, you cannot manually stream (replicate) parts in/out. The only way to do this is with Workspace.StreamingEnabled, although it automatically streams them, which isn’t what you’re looking for.

There is a feature request for this, however. Although it doesn’t mention streaming parts out, the most recent reply bumps it suggesting that developers should have more control over what is/isn’t replicated.

2 Likes

Oh alright, then I know that.

What about always making sure the NPCs network owner is on the player?
(And I actually take this in consideration so I can have about 100 NPCs, maybe zombies chase the player around on a open world map? Each player can have 100 zombies chase them or so.)

Well to answer your question, if you use a remote event from the server that only fires when a player joins that simply calls to a local script, to delete the part, and the local script and remote event afterwards. What security risks do you forsee with this method?

And you could loop through all enemies during map regen and lock their position so they don’t fall.

you cant do that, but you can do like this: game.workspace.PartName.Transparency = 0

You can make block unvisible for player and visible for server. Just destroy a block in LocalScript in StarterGui.

It’s not really for security reasons but just perfomance.

Have a map load on the server so NPCs don’t fall through (they have no network owner if no player is targetted).

The generated map may be larger than the player’s average render distance (players on potato pcs will set it very low, lower than the server) and NPCs still able to walk around randomly without a target, etc.

Let each client and server have it’s own version of the map (maybe for lowering/higher detail too?).

For things like that I basically want a map in the workspace that the client can’t see, the client will have to generate/load it’s own.

If you’re doing this for performance, then I’m assuming you want the physics etc. to be calculated on the server? In this case, use part:SetNetworkOwner(). This is equivalent to part:SetNetworkOwner(nil) and will set the part’s network ownership to the server.
To make the part invisible, you can use the option that other people have already suggested - simply set the transparency of the part to 1.

2 Likes

I actually already know all of that, that’s like basics to me.
But I’m specifically looking for a way to absolutely hide objects in workspace from the client, not just invisible but actually gone-for-real, no local script ever should be able to refer to it.

https://developer.roblox.com/en-us/api-reference/property/BasePart/LocalTransparencyModifier

This will not delete the object on clients, it will make it invisible to the client (which you can have happen to all clients) and then mark CanCollide as false.

Selective replication doesn’t exist. You either need to delete the items on the client or find another way to resolve your problem. A barebones skeleton of the map with a transparency of 1, as suggested earlier, sounds like the best workaround.

3 Likes

Oh, I guess I’ll have to delete object then when the player joins until Roblox someday makes this a feature.
Thanks for all the help though.

1 Like

My solution is to use a naming convention. In my workspace I have a folder for ServerProjectiles. On my server script when I clone my projectiles, I set their parent set to this folder.

Now, in my client in a LocalScript, I make the following simple code to listen for DescendantAdded of that ServerProjectiles folder, and immediately destroy it. Since it is LocalScript, it is affected only on the Client.

game.Workspace.ServerProjectiles.DescendantAdded:Connect(function(d)
    Debris:AddItem(d, 0)
end)

CC this feature request

1 Like

Sorry I posted a bit earlier with a wrong solution, but here’s a working one!
Also i am very late to this post but i was bored and had the solution in my head.

So, what you want to do is work with remote events. They can send server information (part paths for example), which means you can get that information in a local script.

Here’s the code I used:

-Script

local rs = game:GetService("ReplicatedStorage")
local getPart = rs:WaitForChild("getPart")
local players = game:GetService("Players")
local part = workspace.tester

players.PlayerAdded:Connect(function(player)
	
	getPart:FireClient(player, part)
	
end)

-Local script

local rs = game:GetService("ReplicatedStorage")
local remote = rs:WaitForChild("getPart")

remote.OnClientEvent:Connect(function(part)
	
	part.Transparency = 1
	
end)

I named the remote event “getPart”, but feel free to name it as whatever you’d like!

I hope I gave you some useful information still, as I’m quite late to this post.

1 Like