简体   繁体   中英

c# Unity 3D - 1000 cube instantiation script

Why does the following script make Unity run very slowly and unusable?

public Transform brick;
public int gridWidth=10;
public int gridDepth=10;
public int gridHeight=10;
void Start() {
    for (int y = 0; y < gridHeight; y=y+2) 
    {
        for (int z = 0; z < gridDepth; z=z+2) 
        {
            for (int x = 0; x < gridWidth; x=x+2) 
            {
                Instantiate (brick, new Vector3 (x, y, z), Quaternion.identity);
            }
        }
    }
}

In the transform I place a prefab that is basically a rigid body cube.

If I remove the For-Loop containing the z int, it runs OK (so a 10x10 grid / 100 cubes is fine). However, with the z int loop in place it breaks ( a 10x10x10 grid / 1000 cubes)

How could I get this to actually work sensibly without making Unity unusable?

I think the best solution would be to use Oclussion Culling. It's a system that "doesnt render" the objects that are not visible by the active cam.

Here is the Unity information about it.

Oclussion Culling at Unity Manual (PRO ONLY)

This function, however, is only available for the Unity Pro users, and if you have the Free version you should look for a custom Oclussion Culling script like this one:

Oclussion Culling

Keep in mind that this is only a script I found online, and there might be much better ones out there. Anyways, in words of the creator of that script:

In my test scene the script delivered a >80% reduction in draw calls/tris/verts and >85% faster renderer loop, at the cost of a 12% reduction of frame rate (from 75 to 66 FPS). While this is great for scenes that are being bogged down by draw calls, I'm interested in any feedback that can reduce the script's overhead to make it suitable for general use.

It may be worth to check it out.

I suppose you may remove rigid body from prefab; leave it only with box collider and make it static . First of all this will allow Unity to effectively batch draw calls . And PhysX will be able to utilize broad phase and improve performance of collision detection.

I might be looking too far into this example, but it seems like you're trying to emulate "block-ily" rendered voxels.

While for a very simple example cubes might work, there is a definite limit to how many you can instantiate, render, and have the physics system keep track off, even with culling.

You should use an approach to rendering voxels that generates singular meshes of a areas of a predefined size (often called "chunks"). This allows for a single draw call for each material, inherent culling that's faster than anything that could automatically be generated (since it's a "free" side-effect of generating the mesh), a removal of the overhead of multiple colliders, and much much more .

It's a task that sounds much more daunting than it actually is. There are numerous tutorials that will go over what you need. I also found these three sources to be particularly well written.

I personally wouldn't recommend trying to get your current approach to work using occlusion culling and batching alone, since it's still an extremely inefficient approach to this. Also note that Unity Pro's occlusion culling is designed to be pre-computated, so it won't work in your case.

SPAWN A CUBE OF CUBES .

public Transform cubePrefab;

public int rows,columns,depth;
public float padding;

// Use this for initialization
void Start () {
    for(int i =0; i < depth; i ++) {
        for(int j=0;j< columns;j++){
            for(int k=0; k < rows;k++){
                Vector3 pos = new Vector3(k * padding,j * padding,i * padding);
                //print(pos);
                Transform foo = (Transform) Instantiate(cubePrefab,pos,Quaternion.identity);
            }
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM