Help with client animations

Greetings everyone! Today I want to ask how I would go about making localscripts that tween locally, etc. on parts.
Let’s talk about “parts”.
I have a building system in my game, and once a player places a “interactable” part, scripts, and etc. will be put inside the “interactable” part, it will set itself up, and execute a loop, and halts once the part is destroyed by a player, like normal behavior with scripts, once scripts get deleted, they stop. “interactable” parts are just parts that “work”, and does something than nothing.

What do you want to achieve?

I want to achieve client sided animations on placed “interactable” parts, by using localscripts.
I’m not sure how, though. I want everything to have ZERO memory leaks, whatsoever.

What’s the issue?

The issue is, as normally, a player places a part, a script gets put inside that model, but what about localscripts?
Oh no! They won’t execute anywhere other than PlayerScripts, PlayerGui, Backpack, Character, and ReplicatedFirst!
What should I do to work my way around this?

What solutions have I tried so far?

I don’t think there are any solutions anywhere on the internet, so I’ve come here to ask you all how I would go about this. I’m one of the people who doesn’t know how to search properly with well-described words, and etc.

1 Like

if you’re talking about about this

you could use a remote event and fire all clients

edit: i might be wrong

1 Like

Hmm, there are actually multiple methods to handle this issue, if you research deep enough by looking in the toolbox and the community resources page.

The simplest way to do it which I find really creative is what the default-free model jeep this laggy thing which is really unoptimized because of the while true do loop.

In fact, the solution is similar to placing a server script inside a BasePart. For a local script, you just have to insert a local script into the places that you mentioned.

The jeep does this by giving the local script in players that detect the player input and controls the vehicle locally. No need to use an old drive tool like in some old Roblox games.

localScriptToClone = --path to the script in replicated storage

playerLocalScript = localScriptToClone:Clone()
playerLocalScript.Parent = player.PlayerGui
playerLocalScript.Disabled = false

Moreover, a huge benefit to this method is what you required with zero memory leaks because upon leaving the seat the script will automatically destroy itself removing all of its connections.

The downsides of this method are that you have to rely on the server to give you the script upon a seat which of course due to latency means there is a gap in time where you can’t control the car.

Otherwise, another option is to use remote events and I think you can figure it out from the dev reference API with the same methods. However, I believe the same cons still exist with latency.

There is even a third option to do it all locally which is what this IK procedural animation does to handle the expensive IK maths required to animate the legs, using workspace:DescendentAdded event to check if a humanoid exists or is spawned and if so then animate the legs locally in an animation queue.

Yeah lots of options, hope you look through them or even find another method suitable for your goals.

2 Likes

Yes, that’s what I thought, removing the localscript once the part is destroyed.

Perhaps I could use the Place and Destroy events to link up / disconnect a localscript.

Yeah making a localscript once a client has been called, sounds like a good idea, I hope.

I’ll update you all with new problems, etc. soon.

Thanks for the advice!

Edit: I have a new problem. What if the client joins AFTER another player has placed an item?
I could replace the events with a ChildAdded, with a for loop at the beginning to make sure everything is loaded and ChildRemoving, but I don’t fully trust ChildRemoving just because I think it might fail sometimes.

Hmm, good catch if you don’t trust ChildRemoving you can just check it locally every HeartBeat or Renderstep. Perhaps, you check if only when the player is able to see the part like what the above resource does using camera:WorldToViewportPoint(pos) to see if something is on screen then animate it?

		local pos = x[2].HumanoidRootPart.Position
		local mag = (pos-camera.CFrame.Position).Magnitude
		local _,onScreen = camera:WorldToViewportPoint(pos)
		
		if mag <= 150 and onScreen == true then
			x[1](dt)
		end
1 Like

Sorry, forgot to mention in my edit that I could include a for loop, that iterates through all previously placed parts, to make sure everything has loaded properly.

Yeah doing a distance and onScreen check is efficient, but doing that for like 1000 parts will end up in a slideshow.
Perhaps even doing the same thing separately in localscripts will also end up in a slideshow. I’ll try to avoid as much loops as possible.

Okay, now this brings me to the next question:
How would every “portable” localscript know if they work for that part? My idea is to make a localscript that sets up the other localscripts to load parts. In that script there is a for loop, a ChildAdded event, and a ChildRemoving event. And once ChildRemoving is fired, the localscript must destroy the “portable” localscript, perhaps I should store every Instance in a table that is linked to each script, I’m not sure how.

local t = {
    ThatInstance = ThatScript -- Index will be nil if ThatInstance gets destroyed :(
}

local t = {
    {ThatInstance, ThatScript} -- Index 1 will be nil if ThatInstance gets destroyed.
}

Hopefully the 1st method works because ChildRemoving fires a connected function with an argument which defines which instance gets removed, so it can quickly iterate through the table and find the Instance and remove the localscript.

This is how it’s currently, server sided, for each “interactable” part:
image

Oh when I see that model tree, I wonder have you considered the collection services?

Normally, we use this to give scripts to common instances like doors, or in your case conveyor belts since well-copying scripts Instances can of course be really laggy like having 1000 kill bricks with a personal server script in each of them.

Anyways, currently, it’s really hard to know the answer because of how abstract it is.

For example, is the conveyor for something like a tycoon? If so then you can use a region check like what Miners Haven does for when you enter another person’s plot to render the mining machine animation.

Personally when I first join yeah it’s still really laggy IDK why

Are you able to find opportunities to load and unload animations so that in your scenario instead of checking for 1000 parts you would only really need to check 200 parts instead?

Are there tricks like that for your scenario to know the working condition as you put it?

Edit: even if there are no tricks are there other ways to optimize the script? like completely removing animations if a person has a really bad computer through a graphical setting?

1 Like

I haven’t considered CollectionService, but that seems like a good idea to tag whether to animate or not.
I’ve set up a folder with modules that gets required once a part is placed, perhaps I could edit them to have 2 contents in a table to be returned, a initialize function (called once placed), and a update function (called every frame step, but if it has “animate” tags on the part, I don’t know, something that decides if part should be animated.).
Seems like a good idea to me, thanks a lot for the advice! :slightly_smiling_face:

1 Like