I've been experimenting with Unity for the past few weeks; I'm still new. I have dove slightly into ECS, compute shaders, and so forth, but I really don't want to implement these solutions if it isn't necessary due to the complexity.
Can default Unity physics engine really not handle moving 500 cube instances with RigidBodies at once? Or is the way I am doing things particularly bad for performance?
Here is the code I'm using; it's just one script on an empty GameObject. It slows to 16FPS when instantiating the 500 cubes, and then slows to 0.3 FPS when moving them all at once via Rigidbody MoveTowards.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpawnAndMove : MonoBehaviour
{
public TargetCube TargetCube;
public GameObject CubePrefab;
public Vector3 brickPosition = new Vector3(10, 0, 0);
GameObject[] objects;
int moveCubeInstances;
// Start is called before the first frame update
void Start()
{
StartCoroutine(Countdown());
}
IEnumerator Countdown()
{
yield return new WaitForSeconds(3f);
for (int i = 0; i < 500; i++)
{
var cubeClone = Instantiate(CubePrefab, transform.position + brickPosition, transform.rotation);
cubeClone.tag = "CubeInstance";
}
objects = GameObject.FindGameObjectsWithTag("CubeInstance");
yield return new WaitForSeconds(3f);
moveCubeInstances = 1;
while (moveCubeInstances == 1)
{
for (int i = 0; i < 500; i++)
{
objects[i].GetComponent<Rigidbody>().transform.position =
Vector3.MoveTowards(objects[i].GetComponent<Rigidbody>().transform.position, TargetCube.transform.position, 12f);
}
yield return new WaitForFixedUpdate();
}
print("exited while loop");
}
}
Thank you for any help here.
FindGameObjectsWithTag
does an extra search, not only for the new 500 objects but also for all other objects on this scenetransform
is already cached field and to call it you do not need to do GetComponent<>
Instantiate
is a very difficult operation and it is better to do it in advance, and you can even break it into several calls per frame, for example, 50 each, but definitely not 500 in one frame, but rather use Pooling (https://docs.unity3d.com/Manual/MobileOptimizationPracticalScriptingOptimizations.html)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpawnAndMove : MonoBehaviour
{
public TargetCube TargetCube;
public Rigidbody CubePrefab;
public Vector3 brickPosition = new Vector3(10, 0, 0);
Rigidbody[] objects;
int moveCubeInstances;
void Start()
{
StartCoroutine(Countdown());
}
IEnumerator Countdown()
{
yield return new WaitForSeconds(3f);
objects = new Rigidbody[500];
for (int i = 0 ; i < 500 ; i++)
{
Rigidbody cubeClone = Instantiate(CubePrefab, transform.position + brickPosition, transform.rotation);
cubeClone.tag = "CubeInstance";
objects[i] = cubeClone;
if (i % 50 == 0)
{
yield return new WaitForFixedUpdate();
}
}
yield return new WaitForSeconds(3f);
moveCubeInstances = 1;
while (moveCubeInstances == 1)
{
for (int i = 0 ; i < 500 ; i++)
{
objects[i].transform.position =
Vector3.MoveTowards(objects[i].transform.position, TargetCube.transform.position, 12f);
}
yield return new WaitForFixedUpdate();
}
print("exited while loop");
}
}