Reputation: 11
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?
Upvotes: 1
Views: 395
Reputation: 90679
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 e.g. .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 ;)
Upvotes: 1