How to attain Client-Sided Models to preserve memory?

I have a folder filled with hundreds of tree meshes. These meshes take up a lot of server memory. However, I came up with the idea of them only being visible by the client, and not the server, so the client memory is only affected but not the server’s.

I can’t clone it from ReplicatedStorage because the server can still see it, thus taking up memory.

How could I achieve this? Any ideas?

2 Likes

InsertService is great for this.

InsertService can also load in models from the client if I’m not mistaken, provided that they’re from the game owner’s inventory.

Now this does pose a slight security risk since it is technically possibly to load in other models in your inventory as well but only your models, exploiters cannot insert custom models/scripts from their own inventory.

Using InsertService you can essentially let the client load in models that you own in your Roblox account which is a great way to get around Roblox memory limits.

I recall games like Phantom Forces use InsertService for loading maps as it allows them to practically have infinite maps without it ever taking up server space.

If you want to make sure it’s 100% secure though, load models in on the server, let the client clone it and then delete the model on the server so only the client has their own local copy of it.

This way you could theoretically have infinite content in a game if you implemented it the right way.

1 Like

I’ve already looked into this, however you can not use InsertService on the client.

1 Like

image

You have to set this to true to do that.

Though you can also insert a model on the sever, parent it in a player’s GUI (does not replicate to other clients if I recall) and then Destroy() it after the client has Clone()'d it from a localscript.

(The latter is more secure.)

How could you turn this on? It says it’s not scriptable and it’s not a service object in the explorer.

You can through the commandbar, I recall there’s an option in Studio settings to show all hidden services as well.

For starters, you can’t really hide the models from the server to see to begin with when storing them, (unless you decide to have a module to use to construct different types of tree meshes. [More info on that later]) and you don’t have any places that only the client can see that allows for any prefabs. So, either way, the server will see and have to render these models just like how the client is going to render those models.

One method I could think of is using a module to load the trees. I would use a table for these meshes, the keys being the name of the tree and the value being the table with the MeshId and TextureId. Then, I would just have a function that loads the trees with using a SpecialMesh. (Since you can’t use MeshParts) You would be using the client to run the module, the client will be rendering the tree while the server is unaware of its existence. However, knowing that you have

it would be more tedious to set the table up. You could also use a folder parented to the module to store the data of each tree mesh, by use of StringValues, using a function to do just that. It would depend though on how your trees are structured, if they’re going to have separated parts or not.

You could do that by enabling the visibility of services, but I don’t think you should be doing that because of these changes back 6 years ago.

Even with it enabled, I don’t believe it works anymore since they have made a change that stopped allowing clients to load in assets several years ago, unfortunately.

I was thinking about using a custom loader yesterday. It could work, however as you said it would be tedious. I’m trying to discover other methods that are less tedious and get the job done.

You still could make a custom loader based on your layout. How is your tree meshes laid out? I could suggest what you could do to make it work.

Weird that I missed that.
Well, you’ll have to use the server approach in that case.

Loading in a model on the server for 5 seconds is not going to hit the memory limit I can almost guarantee you.

Load model on the server > parent to player’s GUI > let local script clone it > delete server copy > keep client copy of model.

This should prevent the server for running out of memory.
You’ll only have to do this once for each player joining likely and the model will only temporarily exist on the server before being unloaded.

Each tree (model) has 2 meshes, the trunk and the leaves. They are both MeshParts. They’re laid out in an irregular pattern across the map including orientation and position.

Would it be optimal to call LoadAsset on a folder with hundreds of trees every time a player joins though?

1 Like

Just thought of this:

What about keeping the trees on the server side but minimizing its memory usage individually on runtime with CanCollide = false, Box collisions, CanTouch = false, CanQuery = false, etc., and on the client, I can turn CanCollide on, since it’s trees that need to be collided with.

It would still be memory on the server, but it would be less on the client itself.

1 Like

I would load in perhaps 20 trees at a time, keep the model on the server for a limited time (in case multiple players join within a minute).

When there’s no player joins for a while you can remove the trees.

Though to be fair, I would only load in the trees when you actually NEED them.

100s of trees is even going to cause problems for some players who play on low-end hardware.
And having so many unique models is going to cause a agonizing amount of drawcalls which not even the strongest computers can handle at some point.

There’s around like 10 different tree models we use. They aren’t all unique fortunately for the engine.

The suggestion given by @edozune above may work, it would just be very, very tedious to set up considering the mass.

Reusing meshes and textures already saves up on a lot of memory (and drawcalls).

If all those trees use recycled meshes I’d honestly just write a script to randomize rotation and whatnot and create variations on their own.

10 trees is more than enough and probably won’t hit the server memory limit as fast as you might think.

What about this?

On server runtime, loop through all the trees and get the tree type, position, orientation, etc., and store it in a table. Then, everytime a player joins, I send this information to the client, and the client can then load the trees based on the given data?

Visual:
Server runs → Loop through all trees and store its data → Send to joining players

Table:

{
[1] = {
   Type = "Tree7",
   Position = Vector3.new(10,20,30),
   Orientation = Vectoe3.new(0,0,0)
}
}

Could also use CFrames but you get the point

1 Like