- Home /
Does This Coroutine Make Sense?
I'm new to the concept of coroutines. Within one of my scripts I check to see if a variety of different objects are close enough to the camera to enable them. If they are not, they remain disabled. The script checks the distances every X seconds.
I was noticing within Profiler that the script was taking about 2.5ms-3.5ms to process and would like to cut it down, so I modified my code (below).
Can anyone tell me if doing it this way is a good idea or not? I guess I'm specifically referring to the way the conditional statements "yield" within CheckShowOrDontShow(). From what I understand, yield will basically exit the coroutine, then next frame return to where it left off. The result is that the Profiler shows it as taking 0.15ms-0.3ms now. Great! Just not sure if I'm missing something or causing problems elsewhere.
function Start () {
cachedVisibleDistance = visibleDistance;
player = GameObject.Find("Player/Ship/Ship");
for (var child : Transform in transform) {
// Lets us specify which child to enable/disable based on distance.
child.transform.gameObject.SetActiveRecursively(false);
theObject.Push(child.gameObject);
theLocation.Push(child.position);
theStatus.Push(false);
}
arrLength = theObject.length;
}
function LateUpdate () {
if(tempTime <= Time.time) {
// Cache the player's position so we don't have to access it every loop in CheckShowOrDontShow(). Saves CPU (Profiler)
cachedPlayerPosition = player.transform.position;
CheckShowOrDontShow();
tempTime = distanceCheck + Time.time;
}
}
function CheckShowOrDontShow() {
// Get the distance to all the objects which enable or disable based on distance
for (i=0;i<arrLength;i++) {
if (player && theObject) {
if(theStatus[i] == false) {
if(Vector3.Distance(cachedPlayerPosition, theLocation[i]) <= visibleDistance) {
/* Then we tell it to enable.
Alternatively, we could just enable and disable materials, but I
feel like completely disabling the objects may save resources. */
theObject[i].SetActiveRecursively(true);
theStatus[i] = true;
}
yield; // Check Profiler to see if this helps with processing time
} else {
// We should also disable currently enabled objects if they're farther than visibleDistance
if (Vector3.Distance(cachedPlayerPosition, theLocation[i]) > visibleDistance) {
theObject[i].SetActiveRecursively(false);
theStatus[i] = false;
}
yield; // Check Profiler to see if this helps with processing time
}
}
}
}
Answer by whydoidoit · Nov 14, 2012 at 09:32 AM
That's a great use of coroutines. Perfect multi-frame shifting of effort is a very good idea.
I would suggest that you square visibleDistance at the start and then check (cachedPlayerPosition - theLocation[i]).sqrMagnitude because square roots are recursive and expensive. There's some more advanced info on coroutines available on Unity Gems
Thanks a bunch, $$anonymous$$ike!
Just to clarify on your suggestion, are you suggesting the following revisions?
function Start () {
visibleDistance = visibleDistance*visibleDistance;
cachedVisibleDistance = visibleDistance;
and then swapping out
if(Vector3.Distance(cachedPlayerPosition, theLocation[i]) <= visibleDistance) {
with this?
if((cachedPlayerPosition - theLocation[i]).sqr$$anonymous$$agnitude <= visibleDistance) {
I'll be sure to check out Unity Gems. Thanks for the tip.
Yeah that's what I was thinking... I normally have a visibleDistanceSquared kind of variable myself.
Oh I see. According to the Unity docs, Vector3.Distance(a,b) is the same as (a-b).magnitude and that "calculating the squared magnitude ins$$anonymous$$d of the magnitude is much faster." I didn't realize either one of those so thanks for bringing that to my attention, $$anonymous$$ike.
Cheers, will mark this as answered. :)