Firstly: why would you want to cause a frame drop?

In many occasions developers need to make sure that all dynamics in their game are working properly and don’t brake too badly in case the renderer hangs for a short period of time. This is especially true when physics are calculated in the FixedUpdate but there are many other cases where developers want a simple method to test how the system behaves in case several frames are lost due, for example, to processors overload.

As an example, one project where I intensely used this tool is Deep Blue.

A quick, straight forward method (and likely the most common), is to take advantage of the Thread.Sleep function.

using UnityEngine; using System.Collections; using System; using System.Threading; // include this for the Thread class public class FrameDropSimulation : MonoBehaviour { public float seconds = 2f; // Expose in the inspector how long the system will hang. void Update () { if(Input.GetKeyDown(KeyCode.Alpha0)) // Bind a key to trigger the block Thread.Sleep((int)(seconds * 1000f)); // Make the monolitic Unity thread sleep for a short time } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 using UnityEngine ; using System . Collections ; using System ; using System . Threading ; // include this for the Thread class public class FrameDropSimulation : MonoBehaviour { public float seconds = 2f ; // Expose in the inspector how long the system will hang. void Update ( ) { if ( Input . GetKeyDown ( KeyCode . Alpha0 ) ) // Bind a key to trigger the block Thread . Sleep ( ( int ) ( seconds * 1000f ) ) ; // Make the monolitic Unity thread sleep for a short time } }

When you attach this script to a GameObject and hit Play, you’ll be able to freeze Unity for 2 seconds. Unity will then resume normally. Consequently, the FixedUpdate (if you are using it) will try to catch up and fill the time gap with all necessary iterations (if this confuses you it’s important that you read here: FixedUpdate).

If you are here to better understand what happens or just want a different method with a bit more control then you might like the following alternative approach.

As you may know the most obvious way to make any application hang is to code an infinite while loop. All developers learnt that at their own expenses but we can use the power of infinite while loop at our advantage; we only need a timeout that breaks the while loop and lets our application continue. The timeout should be as long as we want.

At this point, if you try to implement it yourself, I know you’d be tempted to say “Ok, let’s use Unity’s Time.deltaTime to countdown” inside the while. No. Looping in an infinite while will prevent Unity from proceeding with its internal updates and this makes the Time.deltaTime and the whole Unity environment not accessible. When we trigger the infinite loop, it’s a bit like entering a temporary room in a separate time/space bubble. Enough geekiness. What we can do though is to use the System.DateTime class to hit our goal. In fact, despite we are temporary locked out of UnityEngine, we can still access the System classes; after all our program is still running.

using UnityEngine; using System.Collections; using System; public class FrameDropSimulation : MonoBehaviour { public float seconds = 2f; // Expose in the inspector how long the system will hang. void Update() { if (Input.GetKeyDown(KeyCode.Alpha0)) // Trigger by pushing alphanumeric 0 { long startingTicks = DateTime.Now.Ticks; // Get the current time in ticks while (true) { long currentTicks = DateTime.Now.Ticks - startingTicks; // find ticks since the loop started TimeSpan elapsedSpan = new TimeSpan(currentTicks); // We use TimeSpan to convert to seconds if (elapsedSpan.TotalSeconds > seconds) // If the time runs out we break the loop. break; } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 using UnityEngine ; using System . Collections ; using System ; public class FrameDropSimulation : MonoBehaviour { public float seconds = 2f ; // Expose in the inspector how long the system will hang. void Update ( ) { if ( Input . GetKeyDown ( KeyCode . Alpha0 ) ) // Trigger by pushing alphanumeric 0 { long startingTicks = DateTime . Now . Ticks ; // Get the current time in ticks while ( true ) { long currentTicks = DateTime . Now . Ticks - startingTicks ; // find ticks since the loop started TimeSpan elapsedSpan = new TimeSpan ( currentTicks ) ; // We use TimeSpan to convert to seconds if ( elapsedSpan . TotalSeconds > seconds ) // If the time runs out we break the loop. break ; } } } }

These methods are as simple and effective as they are essential to deliver solid dynamics as well as a properly tested game.

Greetings

R

Contributors: User NickWalker12 on reddit.com