I currently have a system that detects when the player activates a proximity prompt, after that unanchor parts inside of a model. How do I make it so that the physics is less laggy when the parts are unachored?
--local script
OpenLootCrate.OnClientEvent:Connect(function(itemName, crate: Model)
local ItemConfigs = require(game.ReplicatedStorage.Configs.Accessories)[itemName]
local model = ItemConfigs.Model:Clone()
model:PivotTo(crate.ItemSpawn.CFrame)
crate:WaitForChild("InteractBox").ProximityPrompt.Enabled = false
local position = crate:GetPivot()
model.Parent = crate
for _,v in crate:GetDescendants() do
if not v:IsA("BasePart") or v.Name == "ItemSpawn" then continue end
v.Anchored = false
end
end)
-- server script
LootCrateEvent.OnServerEvent:Connect(function(player, CrateInQuestion)
local CrateConfigs = require(RepS.Configs.Crates)
if DM.GetData(player).money < CrateConfigs[CrateInQuestion.Name].Price then return false end
DM.SubtractValue(player,"money",CrateConfigs[CrateInQuestion.Name].Price)
local item = RandomizeChance(CrateConfigs[CrateInQuestion.Name].LootPool)
LootCrateEvent:FireClient(player,item, CrateInQuestion)
for _,v in CrateInQuestion:GetDescendants() do
if not v:IsA("BasePart") or v.Name == "ItemSpawn" then continue end
v:SetNetworkOwner(player)
end
end)
This is incorrect, nothing should ever be done from the server if it’s a client-sided effect.
OP should not clone all the parts and then unanchor them on the client. The crate should be created on the client in the first place, which then you can unanchor the parts. Anything that is a strictly client sided effect, should only be done on the client side if only one client is affected.
OpenLootCrate.OnClientEvent:Connect(function(itemName, crate: Model)
local ClientCrate = crate:Clone()
ClientCrate:PivotTo(crate:GetPivot())
for _,v in crate:GetDescendants() do
if v.Name == "InteractBox" then v:Destroy() continue end
if not v:IsA("BasePart") then continue end
v.Transparency = 1
end
local ItemConfigs = require(game.ReplicatedStorage.Configs.Accessories)[itemName]
local model = ItemConfigs.Model:Clone()
model:PivotTo(crate.ItemSpawn.CFrame)
model.Parent = ClientCrate
ClientCrate.Parent = workspace.ClonedCrates
for _,v in ClientCrate:GetDescendants() do
if not v:IsA("BasePart") or v.Name == "ItemSpawn" or v.Name == itemName then continue end
v.Anchored = false
end
end)
I rewrote the client script according to this, the server script remains unchanged except I removed the setownership. Is this a good implementation?
No, do not clone the crate on the client. Add in a system to spawn the crates where they need to spawn on the client.
Naturally if the crate is spawned on each client individually they will all see the crates, it’s just not a server-sided crate. Cloning the crate and hiding the server crate just adds unnecessary parts. There’s no point in doing that and it’s bad practice.
Create the crates initially on the client, at run-time, not on the server. This way the crate is always owned by the client and will most likely never lag.
If I’m following you correctly here, I would have to write a module script, and every crate function should be inside that crate, and then when a player joins the game, the crate will spawn only for that player. The server should only retain information about the crate configs, am I right?
Easy replication that is also eligible for instance streaming.
If you re-use the crate a lot, then it would be better to store it in ReplicatedStorage and have the client create them, and parent it to an object that is eligible for streaming. But for a majority of cases, it doesn’t really matter that much.
Yes, exactly, always develop in a way that you would if you expect the game to be big. If you miss out on important optimizations early on, you’re going to run into issues in the future.
I decided to follow tannnxr’s way here since I thought some OOP practice could do some good. Really, many thanks to you both though, because of you, I got this working in a short time. Many thanks, once again.