I just made a little test how fast Update is.
Test setup:
Graphic quality set on fastest
50,000 cubes with a script that causes the cube to bob (y position = Sin(Time.time))
Than I recorded Time.unscaledDeltatime for 500 frames and saved it into a csv file.
Loaded the data into google docs and made a chart.
What the labels mean
Empty
Empty project without cubes
Cubes only
Only the [Cube Count] cubes loaded without scripts added
Empty Behaviour
Cube has empty script → Script : MonoBehaviour { }
Empty Update
Cube has script with only an Update method whitout statements
SinBob
Cube has A piece of code in Update method →
Vector3 v = transform.position;
v.y = Mathf.Sin(Time.time);
transform.position = v;
SinBobCached
Cube has same code as SinBob only the transform is cached →
private Transform m_transform;
public new Transform transform { get { return m_transform ?? (m_transform = base.transform); } }
SinBobGetComponent
Cube has same code as SinBob only transform has been replaced with GetComponent()
PooledSinBob
Update is beiing called from the manager where the script is cached
PooledCallback
Update is beiing called from the manager where the method is cached with delegate
PooledInterface
Script included IUpdate interface with update method called from the manager same way as PooledCallback
Full Quality setup
Quality:
Pixel light count 0
Texture quality Half Res
Anisotropic textures Disabled
Anti aliasing Disabled
Soft particles Off
Real reflection prones Off
Billboards face camera Off
Shadows Disabled
Shadow resolution Low
Shadow projection Stable Fit
Shadow distance 15
Shadow newr plane offet 2
Shadow cascades No
Blend weight 1
V sync cont Disabled
LOD bvias 0.3
Maximum lod level 0
Particle ratycast budget 4
Async upload time slice 2
Async upl;oad buffer size 4
Time:
Fixed timestep 0.2
Maximum allowed timestep 10
Timescale 1
Empty:
No other scripts running
Manager Settings:
Max frames 500
Cube count 50000
Cube info:
Size 1
Cast shadows Off
Receive shadows Off
Use light probes Off
Reflection probes Off
using UnityEngine;
using System.Collections.Generic;
using System.IO;
public class Manager : MonoBehaviour
{
private const string NEW_LINE = "\n";
private const string PATH = "Assets/Data/";
private const string EXTENTION = ".csv";
[Header("Test Settings")]
[SerializeField] private string fileName = "Update";
[SerializeField] private int maxFrames = 500;
[Header("Object Settings")]
[SerializeField] private GameObject testObject;
[SerializeField] private int cubeCount = 50000;
[SerializeField] private float start = 5.0f;
[SerializeField] private float space = 1.5f;
private int m_currentFrame;
private float[] m_timeHistory;
private void Awake()
{
m_currentFrame = 0;
m_timeHistory = new float[maxFrames];
if (testObject != null) { CreateCubes(); }
}
private void Update()
{
if (m_currentFrame >= m_timeHistory.Length) { return; }
m_timeHistory[m_currentFrame] = Time.unscaledDeltaTime;
m_currentFrame++;
if (m_currentFrame >= m_timeHistory.Length) { ExportCSV(); }
UpdateObject();
}
private void ExportCSV()
{
// Format to CSV
string o = "Deltatime" + NEW_LINE;
for (int i = 0; i < m_timeHistory.Length; i++)
{
if (i >= m_timeHistory.Length - 1)
{
o += m_timeHistory[i];
continue;
}
o += m_timeHistory[i] + NEW_LINE;
}
// Create file
string path = PATH + fileName + EXTENTION;
StreamWriter sw = File.CreateText(path);
sw.Write(o);
sw.Flush();
sw.Close();
// Notify
Debug.Log("File saved in: \"" + path + "\"");
}
#region [OnlyCubes, EmptyBehaviour, EmptyUpdate, SinBob(No)Cache]
/*private void CreateCubes()
{
for (int i = 0; i < cubeCount; i++)
{
Instantiate(testObject, new Vector3(0.0f, 0.0f, start + space * i), Quaternion.identity);
}
}
private void UpdateObject()
{
// empty
}*/
#endregion
#region [Managed]
/*
private List<PooledSinBob> m_pool;
private void CreateCubes()
{
m_pool = new List<PooledSinBob>();
for (int i = 0; i < cubeCount; i++)
{
GameObject o = Instantiate(testObject);
o.transform.position = new Vector3(0.0f, 0.0f, start + space * i);
m_pool.Add(o.GetComponent<PooledSinBob>());
}
}
private void UpdateObject()
{
// empty
for (int i = m_pool.Count - 1; i >= 0; i--)
{
if (m_pool[i] == null) { m_pool.RemoveAt(i); continue; }
m_pool[i].MyUpdate();
}
}
*/
#endregion
#region [Managed]
/*
private List<System.Action> m_pool;
private void CreateCubes()
{
m_pool = new List<System.Action>();
for (int i = 0; i < cubeCount; i++)
{
GameObject o = Instantiate(testObject);
o.transform.position = new Vector3(0.0f, 0.0f, start + space * i);
m_pool.Add(o.GetComponent<PooledSinBob>().MyUpdate);
}
}
private void UpdateObject()
{
// empty
for (int i = m_pool.Count - 1; i >= 0; i--)
{
if (m_pool[i] == null) { m_pool.RemoveAt(i); continue; }
m_pool[i]();
}
}
*/
#endregion
#region [Managed]
private List<IUpdate> m_pool;
private void CreateCubes()
{
m_pool = new List<IUpdate>();
for (int i = 0; i < cubeCount; i++)
{
GameObject o = Instantiate(testObject);
o.transform.position = new Vector3(0.0f, 0.0f, start + space * i);
m_pool.Add(o.GetComponent<InterfacePooledSinBob>());
}
}
private void UpdateObject()
{
// empty
for (int i = m_pool.Count - 1; i >= 0; i--)
{
if (m_pool[i] == null) { m_pool.RemoveAt(i); continue; }
m_pool[i].MyUpdate();
}
}
#endregion
}
The code (manager only)
You can view the data Here. (Google Drive)