[SEEKING EXPERTISE] Developing a SuperHot-like Slow Motion Effect

I have been trying and have successfully implemented a slow-motion effect similar to that of the popular game SuperHot, but I have encountered some obstacles that I am struggling to overcome efficiently. Keep in mind that the provided solutions do work, but I’m trying to work on possible optimizations.

To provide some context, my objective is to create a dynamic system where time appears to slow down dramatically when certain events occur such as bullets fired by enemies. I have realized that the approaches I have attempted, involving iteration, recursion, and conditional rendering, might not be the most optimal solutions due to the potential over-time performance impact on the script and the server itself.

Considering the complexity of the problem, I am here for advice on how to approach this challenge effectively. My current approach involves using loops to update the positions of individual bullets, but this approach quickly becomes computationally expensive as the number of bullets and enemies increases. E.g. with just two enemies shooting at the player each releasing at least two bullets every 5 seconds, the number of loops and iterations becomes substantial very quickly. When one bullet enters “slow time,” others should follow suit, leading to even more loops and iterations.

I am fully aware that repeatedly rendering and updating the positions of numerous bullets each frame is (most probably) not the most efficient way to achieve the desired slow-motion effect. Therefore, I am in need of guidance on alternative methods that could help me optimize the process.

I humbly request your advice:

1. Are there alternative approaches or algorithms I could use to minimize the computational burden of rendering and updating bullet positions while maintaining a convincing slow-motion effect?

2. Could you recommend any existing Roblox libraries or resources that specialize in time manipulation effects or provide efficient solutions for similar challenges?

3. Is there a more efficient way to handle the cascading effect of entering slow-motion for multiple bullets once one bullet triggers the time slowdown?

4. Are there any specific Roblox scripting techniques or best practices I should consider when dealing with performance-intensive tasks like this?

I would greatly appreciate any help, advice, or insights you can provide on this matter. I am sorry if I posted in the wrong section, but I saw it fit for here.

Thank you for taking the time to read my request. I look forward to your responses and suggestions. Please feel free to ask for any additional information or clarification if needed.

5 Likes

I would attempt making the game predict the next position using points instead of making loops.you could probably also use tweens for the bullet to end up in the position its probably not the best option but the only one i could think of

If you dont know how to make points that the game is predicting you should watch this video he shows somewhere in the video how he makes the arm predict where the ball is going to be

6 Likes

For optimization from my knowledge at the moment these are some ideas:

  1. Reduce the number of uneeded operations (Spatial hashing/Octrees example occlusion culling)
  2. Cache it in memory (use Partcache to reuse projectiles)
  3. Using more optimal functions such as :BulkMoveTo for cframing a lot of projectiles.

For the actual problem, what are you actually doing and where is the code?

What is substancially quicker?
How did you measure it, fps drops, os.clock benchmarking?
Do you actually need optimization?

Are you sure this isnt just a memory leak related issue and such?

From my knowledge changing CFrame is pretty fast in a heartbeat loop every frame. Not sure about changing .Position might be different due to a weird engine quirk.

2 Likes

I recall part.Velocity which slows down physics. I do have a freeze time script that I can open source and you could modify to make it time slow.

4 Likes

slow down the client entirely using runservice (effective and funny)

3 Likes

Assuming gravity is the only force involved, you can implement slow motion by (a). reducing the velocity by a factor x, and (b). reducing gravity by a factor of of x^2. (a). can be achieved by manually editing the velocity, and slowing down Humanoid walkspeeds. (b). can be achieved by adding an upward force of magnitude m * g * (1 - 1/x^2), where m is the mass of the assembly and g is standard gravity. This will allow you to offload work to the physics engine, which is substantially more efficient than anything you can write in Lua.

3 Likes

Simulating bullets should be handled on the client. Then you can fire an event from the server letting the clients know that they should slow the bullets down.

For hit detection / verification, handle that on the server.

2 Likes

Thank you for your response and for providing the video illustrating how to create predictions using trigonometry. I appreciate your efforts in offering extra materials to help me optimize and write better code for this problem.

I obtained a better grasp of how points can be utilized to anticipate the trajectory of an object, such as the arm-ball you stated, after watching the video and the time length you specified. The ideas presented in the video are valuable and can be used in certain areas of my slow-motion effect implementation. I would thus also like to explore predictions and points and make a beta version to see how it would look like in practice, specifically with multiple bullets and many on-going predictions. I’d assume it would take more calculations to predict, but would be less performance-heavy on iterations and loops.

I want to express my upmost respect for your input and for sharing the video resource. It has provided insights that I can incorporate into my development process (if not in all aspects, then some of them).

1 Like

Thank you for also sharing your optimization ideas. I value your perspectives and would like to respond to each of your questions and recommendations.

The major goal I want to achieve is to reduce unnecessary operations. To avoid needless operations, you suggested spatial hashing, octrees, and occlusion culling. According to my understanding, and based on my lack of prior research into these techniques, these strategies can be helpful in optimizing the computing burden by limiting calculations for things that are not visible or relevant at the time. I’ll look into it further because I feel unqualified to appraise any of those strategies at this time.

Caching in memory is something I’ve never given much thought to. Using Partcache to reuse projectiles is a clever way to save memory allocation while improving performance. By recycling old projectiles rather than constantly producing new ones, I can reduce memory usage and potentially improve overall efficiency (I hope that is what you thought).

Using more efficient routines such as :BulkMoveTo for CFraming a huge number of projectiles is a great idea, and it is by far my favorite. To be honest and admit rather embarassingly, I’ve never even heard of :BulkMoveTo, but I’ve read up on it now. These built-in functions are specifically designed for bulk operations and can considerably enhance speed when manipulating several objects at the same time, which appears to be a ’ oh… duh!’ moment for optimization.

In response to some of your questions,

“substantially quicker”

refers to the rapid increase in the number of loops and iterations necessary as the number of bullets and opponents increases. I tested the impact on performance using some most commonly found ways, including FPS drops, which revealed a large increase in computational load and potential strain. While addressing optimization concerns is necessary, it is also critical to determine whether optimization is a critical requirement for my project. Given the potential performance impact of rendering and updating bullet positions for the slow-motion effect in this situation, and the potential large amount of bullets that could be flying toward the player at once due to the slow-motion effect, optimization is indeed required to ensure a smooth and engaging gameplay experience. I, first and foremost, want to use this as a learning opportunity to widen my grips on scripting and ideas. I never take one option and say “Oh, that’s the only option I can use for this script!”. I like to explore all possibilities. I have not yet attempted to determine if a memory leak is contributing to the performance issues, I will conduct some review and testing later (I guess thats bad on my end, but a great suggestion from your side).

The comment you made about the engine quirk regarding altering CFrame versus changing Position is most probably correct. In terms of prior knowledge and reading up on some properties articles, updating CFrame properties is often more efficient than directly modifying Position as a result of internal engine optimizations. However, to the best of my knowledge, this may no longer be used, thus this is all speculative.

Thank you once more for your useful advice and for raising these crucial points. Your knowledge and insights are greatly valued. If you have any more suggestions or recommendations based on my response, please let me know.

2 Likes

I think what I’ve seen some games on Roblox do is lower gravity and decrease the amount of force applied to objects.

For objects that are already moving you could divide or decrease their velocity when time slows down and multiply it again when at normal speed.

You could set gravity to 0 so everything becomes “weightless” and manually apply force or adjust velocities so objects fall and move with the desired speed.

3 Likes

Another idea I have is that when slow motion is enabled its only enabled on the client while everything else is in real time then on the client then you can switch the positions based on the positions before
because were frames behind in the realtime, I dont really know how you could really implement that since things are still happening in realtime so you could appear dead from nothing in slow-mo so you should just experiment with it

2 Likes