[Solved] Don't tween parts under a roblox characters HumanoidRootPart

My issue was resolved.
Thx to the people who helped me out : )

Maybe because you have everything in a Heartbeat loop and running the function every frame

For the functionality I’m looking for I don’t see another way to go about it. Do you have anything in mind?

First it’s probably important to note that this won’t function as you intend it to:

Feel free to test it yourself with a simple loop when removing elements, you’ll notice that it skips elements.

The pairs method increments the iterator i.e. i + 1. By calling table.remove on the current element index the next element in the list - in this case i + 1 - will now be indexed at i. This means that you’ll skip the following element once pairs increments the iterator.

You either need to iterate from back-to-front or iterate it yourself, e.g. …

Example code
--[!] back to front example
for i = #particlesWithMarkers, 1, -1 do -- i.e. from the length of particles to 1
  local particleWithMarker = particlesWithMarkers[i]
  if particleWithMarker.Marker.Parent.Time <= elapsed then
    table.remove(particlesWithMarkers, i)
    onMarkerReached(particleWithMarker.Particle, particleWithMarker.Marker.Value, extraParams)
  end
end

--[!] example of manually iterating
local i = 1
while i <= #particlesWithMarkers do
  local particleWithMarker = particlesWithMarkers[i]
  if particleWithMarker.Marker.Parent.Time <= elapsed then
    -- do stuff
    table.remove(particlesWithMarkers, i)
    onMarkerReached(particleWithMarker.Particle, particleWithMarker.Marker.Value, extraParams)

    -- continue to next iteration instead of incrementing i++
    continue
  end

  -- increment iterator since we didn't remove the value
  i += 1
end

Looking at your code it seems that you’re using the value property of the AnimationMarker to describe the desired property/value for each particle.

Instead of iterating through each marker yourself you could just name all of these tween-related markers as something like "EffectMarker" and then listen to a single animationTrack:GetMarkerReachedSignal("EffectMarker").

Finally, to get the names, you could just parse it from the value as you’ve been doing anyway e.g. …

Example code
-- some example marker
local marker = {
  -- where value = "<markerName>#<propertyName>:<propertyValue"
  --
  Value = 'SomeSpecialName#SomePropertyColor:175,205,50'
}

-- parse the values
local markerName, propertyName, propertyValue = marker.Value:match('^(%w+)#(%w+):(.+)$')
print(markerName, propertyName, propertyValue)

-- i.e.
animationTrack:GetMarkerReachedSignal('EffectMarker'):Connect(function (paramString)
  local markerName, propertyName, propertyValue = paramString:match('^(%w+)#(%w+):(.+)$')
  -- do stuff ...

end)

To answer your performance questions though will require a little bit more information:

  1. How are you defining “particles” - are these BasePart instances that you’re moving around via CFrame or are these ParticleEmitter instances that you’re calling ::Emit() on etc?

  2. If you’re doing this for approx. 100 particles:

    • How many markers are there in total?
    • How many tweens are you creating per particle?
  3. I noticed you also call a secondary method for each of the particles if it’s present in the marker value - are you sure it’s not the methodModule calls that are causing frame drops instead of the tweens?

Thank you for pointing out the skipping of elemts when doing table.remove(). I totally overlooked it since I was so determined to find a solution to the performance issue.

As said :GetMarkerReachedSignal() Gives same performance and my original system included it. I tried Heartbeat instead and they are basically similiar performance vise.

Answer to 1) The particles are mixed between different instances so yeah they can be Baseparts or Particles. Most of my issues are with baseparts since those are the ones I want to tween.

  1. There are around 120 markers in this case. In this case one marker represents one tween. But most markers include a time value so small that most of them I just set the property directly. So for most of the markers they aren’t tweened. I would say maybe around 15 - 18 are actually tweened once.

  2. I doubt that the issue has to do with the methodModule. The modules are already required and in a table so I just check if the table has a key of the modules name. I don’t really see why that would impact performance.

After doing another read through of your post I agree it would be beneficial to try having the same marker name on all markers. That could maybe be the solution to my problem. I’m gonna try doing that and then get back to you. I would need to rewrite so the particles name is in the markers value instead though.

Thank you for the response btw, I appreciate it.

If the majority of them are BasePart instances and you’re updating their CFrame property, you might want to consider adding them to a list of objects that need to be updated and then having a separate thread that updates them - this would allow you to utilise workspace:BulkMoveTo, seen here.

e.g. …

-- some var accessible to both the runtime thread & the marker thread
local targets = { }

-- in your marker code...
animationTrack:GetMarkerReachedSignal('EffectMarker'):Connect(function (paramString)
  -- get the data

  -- if we're updating a BasePart's CFrame then ...
  local tweenDuration = 1 -- or some tween duration
  table.insert(targets, { StartTime = os.clock(), Duration = tweenDuration, Object = ..., Goal = CFrame.new(someTargetCFrame), Initial = CFrame.new(someInitialCFrame) }
end)

-- later ...
local coords = { }
local objects = { }
RunService.Heartbeat:Connect(function (dt)
  local now = os.clock()
  for i = #targets, 1, -1 do
     local target = targets[i]
     local startTime = target.StartTime
     local elapsed = now - startTime

     local alpha = elapsed / target.Duration
     if alpha > 1 then
        -- could set to final cframe here if we wanted
        table.remove(targets, i)
        continue
     end

     -- if you want access to different interpolation methods
     -- then you could take a look at Tween libraries in #Community-Resources
     -- or implement your own using easing methods e.g. an example here: https://github.com/EmmanuelOga/easing/blob/master/lib/easing.lua
     local newCFrame = target.Initial:Lerp(target.Goal, alpha)
     table.insert(coords, newCFrame)
     table.insert(objects, target.Object)
  end

  workspace:BulkMoveTo(coords, objects)
  table.clear(coords)
  table.clear(objects)
end)

Sorry for the confusion here but my question was more to do with what the “methodModule” functions were actually doing. I had assumed they were doing extra things alongside the other parts, e.g. spawn some n number of parts etc


Let me know if the changes you implement don’t make any difference and we can try to take another look

This is the weirdest thing ever…
I tried out only having one marker name and performance didn’t get better.
What I discovered is that there is a certain part/parts that are extra performance taxing to tween. It’s super weird because on this one specific part when tweening it makes the game drop from 60 - 40fps immediatly. I was able to tween basically hundreds off parts without any performance issues but there is this one in particular that just eats up frame time. There was nothing wrong with tweenInfo. The property tweened is a Vector3 size. This probably doesn’t say a lot but have you ever come across anything like this? Because this is so bizarre to me right now.

It’s fixed. The parts were parented to the character. When tweening size of a part under a part of a character that causes enourmous lag. Thx Roblox : (

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.