简体   繁体   中英

Efficient For Loops Unity C#

I'm running a robot simulation in unity where each of the 300 robots runs the same script and I'm using RayCast for communication between robots. Each robot cast 36 Rays in 10 degree increments to cover all 360 degree every 0.02s. This is done using the RaycastCommand so its done in parallel and isn't causing any performance issues. The issue comes when trying to process the RayCast Data.

I need to loop over every result and compare the tags and ID in each robot script as such:

for(int k =0; k< results.Length; k++) // For every result
{
    if(results[k].collider !=null) // Check if RayCast collision happened
    {

        if(results[k].collider.tag == "Robot") // Check that collision is with robot 
        {
            var ID = results[k].collider.GetComponent<RobotControl>().ID;  // Get The robot ID  
            if(!listID.Contains(ID))   // Check that it hasnt comunicated with that robot yet 
            {
                listID.Add(ID);
                Debug.DrawRay(origin + (0.55f* Directions[k]), Directions[k] * results[k].distance , new Color(Directions[k].x, Directions[k].y, Directions[k].z, 1));
                // Grab important info here 
            }
        }
    }
}

The main problem being I cant use IJobParallelFor since I'm accessing the collider and trying to read the tag, and this is the part of the code tanking my performance since everything else is done using Parallel Jobs. The real issue is accessing the components is expensive.

Any Ideas on how to make it more efficient or somehow parallelize it?

Is there a way to access GameObject specific data, like ID, without accessing their components?

In general instead of 36 casts per robot can't you just use a Physics.OverlapSphere would probably already reduce it a lot since an overlap sphere is pretty easy to compute for the physics engine ( if(distance < sphereRadius) )


Then one thing costing a lot performance in your case is probably that Contains on a List . There you should rather use a HashSet . See Performance List vs HashSet for your 300 objects that would probably be worth it.


Or further to me it sounds like you would want to know which other robots are close to that one... you could give each robot a SphereCollider on a certain layer so they only collide with each other, make it Triggers and store them in OnTriggerEnter andremove them in OnTriggerExit .


Is there a way to access GameObject specific data, like ID, without accessing their components?

Well, yes, you can access GameObject specific data like eg .name . But that ID is clearly not something GameObject specific but in your RobotControl class so, no, there is not really a way around GetComponent .

However, in newer Unity versions the GetComponent isn't that expensive anymore since the references are hashed and serialized on edit time.

Question is do you really need that ID list or would it be enough to simply save the collider/GameObject references and access the specific component only when really needed?


In your specific case here also the Debug.DrawRay is something extremely expensive and you should not do it too often and for possible 300 * 299 times;)

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