I’m trying to script a teleport effect that creates and then fades out a particle system when the character does a teleport.
How it works right now:
Server side script listens to Tool.Activated and triggers teleport
Server side script clones TeleportEffect object from ReplicatedStorage to the character’s location
Server side script in TeleportEffect object runs this code (White and Green are particle systems):
This is bad because I’m spamming property updates over the network.
I’d much rather this be a LocalScript, but I can’t just clone a LocalScript into the Workspace and have it start running. There’s not really an obvious way to create a LocalScript for each player from the server script that wants to create this effect (or a subset of nearby players!)
This got me wondering why LocalScripts don’t just run wherever?
Am I using an anti-pattern? What’s the right way to do this in Roblox?
If there’s only one LocalScript, like if it’s in Workspace, it seems to give the impression that each client is running the same script and will view the same effects. I personally think that leaving it to its current limitations makes it clearer that each player is running their own copy of the LocalScript, and it’s more intuitive (in my opinion).
Maybe some kind of container you could Parent to places like the workspace that clones a LocalScript for each player could work? That would probably be a lot more messy, though.
As for your issue, what you could do is identify the objects you want to attach your script to and then do a externally-handling-stuff-in-bulk pattern. You could create a miniscript or something inside of a function, because it’s called each time a specific kind of object is added to the game.
function TryBindToBrick(target)
if target:IsA("Part") and target.Name == "ExplodingBrick" then
-- Do exploding script stuff here.
end
end
workspace.DescendantAdded:Connect(TryBindToBrick)
Also, can you post your code blocks as code instead of screenshots? You can simply tab the entire script and then copy-paste it into your post.
Are you suggesting a giant script watching the Workspace for parts entering to handle all of my effects?
I really like to keep all my code for a game object in one place if possible (it’s often not).
I also don’t like connecting to chatty events if I can avoid it, i.e. subscribing to Workspace.DescendantAdded when I’m interested in maybe .1% of instances that will get added here. Might be more efficient than replicating scripts around. I’ll have to test it.
At least a while ago interop was expensive in Roblox, so running a little piece of Lua code on each instance added could be expensive, even if it’s just checking the name of a part.
I’ve had issues in the past, I was initially confused as to why LocalScripts only worked in certain places. However, I believe that currently it makes sense that they only work in certain places in the game. As previously mentioned, each client has it’s own LocalScripts, so it wouldn’t make sense for multiple client to be using what is meant to be a localscript. Therefore, limiting where the scripts function to certain places makes sense.
For example, when you place something into Workspace then it’s sort’ve like theres one copy of the instance that all the clients see. If there was only one copy of a LocalScript, then what client would use it?
If I put a LocalScript in the Workspace, I would expect all clients to start running it locally.
Would be great for effects like Night/Day transitions, where you don’t want to spam network updates for purely visual effects.
Right now I think I would have to put that LocalScript in PlayerScripts. But I don’t know how to replicate a LocalScript from the server => client at runtime and put a LocalScript in each Player’s PlayerScripts. And because I was even considering that I started to think I was probably doing it wrong.
Having LocalScripts like this makes it obvious they’re ran by each client, if you plan on doing this, either do it in a ServerScript so every player can see the same (though if you plan on destroying it ofc that isn’t going to work well unless you want every user to see it removed, unless you make removing only happen on the client w/ events or waits then use while loops/RunService to change the colours), or do it from the client in StarterPlayerScripts and just switch script.Parent to workspace.PartPath.
It’s something to do with FE iirc, not entirely sure of the reasoning, though. It’s an easy fix though.
For other stuff, it’s much easier to write one LocalScript to handle the lifetime of one particle effect than it is to write 1 LocalScript that handles all particle effects.
For things with more state than a particle effect, it gets even harder. For instance, I was considering creating local animation effects for all my power-ups in my game, but if those are dynamically created at runtime (for instance, when you respawn them), it gets really messy really fast.
Does cloning a disabled localscript to playerscripts and then enabling it work? Haven’t tested it myself yet.
It appears that you may be able to achieve what you want to do by cloning a disabled localscript from wherever you have it stored to the player’s character and then enabling it.
This results in the client running the localscript. Hopefully it works for you, unless you want the script to be in playerscripts. Since the server doesn’t see player’s playerscripts, you would have to use remote events to access playerscripts.
This code clones a disabled localscript from workspace to the player’s character upon them joining, and then disables it. This appears to work, in studio at least. You should be able to edit the code to run whenever you want it to.
Have you tried using CollectionService? You can get an RBXScriptSignal for when a specific tag is added to an instance (GetInstanceAddedSignal). Then all you need to do is add the tag to the instance after creating it on the server.
Also don’t forget you still want to destroy the parts at some point on the server. And consider the behaviour of when clients just join the game (potentially using GetTagged to get all the current effects and either do the effect or hide the part.
Why don’t you just FireAllClients from a RemoteEvent, give it some rules like ignore the request if the teleport effect is not in the camera viewport or just far away. That will just decrease the load on the script. And it will be easier to catch the request instead of relying on loops.