App/game freezes completely while coroutine runs - unity3d

My Android ARCore Unity app/game freezes when a coroutine runs, and then resumes once the coroutine finishes. The coroutine is in a script attached to a gameobject, and the coroutine is called in the Start() function. I have tried inserting yield return null; into more parts of the coroutine, which reduces the time of the pauses, but adds more pauses, resulting in very choppy (basically nonexistent) gameplay for a second or two after the object is instantiated. Could this be happening because ARCore does not support multithreaded rendering? If that is the case (or isn't) how can I fix this, so my coroutine runs (I guess 'in the background') after the object is instantiated and so it does not affect gameplay FPS?
Here is my code:
void Start()
{
StartCoroutine(MyCoroutine());
}
IEnumerator MyCoroutine ()
{
yield return null;
Transform[] allChildren = GetComponentsInChildren<Transform>();
foreach (Transform child in allChildren)
{
if (child.gameObject.GetComponent<MeshFilter>())
{
if (!child.gameObject.GetComponent<MeshCollider>())
{
child.gameObject.AddComponent<MeshCollider>();
}
}
child.gameObject.tag = "CenterObject";
}
}

Coroutines seem to have an overhead when constructing them as discussed here: https://forum.unity.com/threads/startcoroutine-performance-cost.233623/
Given that you're instantiating objects I would suggest these paths:
Change the coroutine into a simple function call, since you don't seem to be requiring any delay between iterations of the loop which is the primary idea of using a coroutine in Unity. You are also adding colliders and expecting gameplay to continue, which can cause unexpected behaviour if you need collisions to be registered.
Instantiate prefabs which have colliders attached beforehand, if possible.
Use object pooling where you would create the objects before gameplay starts and activate them when required, and disable them when they are destroyed, if necessary.

It's because you are caught looping within the coroutine. You need to move the yield to inside the loop:
IEnumerator MyCoroutine ()
{
Transform[] allChildren = GetComponentsInChildren<Transform>();
foreach (Transform child in allChildren)
{
if (child.gameObject.GetComponent<MeshFilter>())
{
if (!child.gameObject.GetComponent<MeshCollider>())
{
child.gameObject.AddComponent<MeshCollider>();
}
}
child.gameObject.tag = "CenterObject";
yield return null;
}
}
Even so, if this is a large number of children you are looping through, it may simply be a performance issue.

In addition to the answers fixing your Coroutine:
Coroutines are not really multithreading! That's why your app freezes if there is a long task in the Coroutine.
The yield return of Coroutines just makes it easy/lazy to do a quick animation or something similar because the Coroutines kind of "remember" where they left and go on from this point (to say it in simple words) so you can run a lot of things apparently "parallel". But still it all runs in the same thread so actually it only seems to be executed parallel because everything is executed between two frames.
If you realy have a time consuming task you want to do in another thread than have a look into async await which is Unity's real multithreading since Unity 2017.
However Unity is not thread save meaning most of the API can only be used in the main thread...

Related

How to find the script that destroys my object?

I work on a physics-heavy project with a lot of rigid-bodies which is also code-heavy. I have a lot of scripts, that create forces, manage joints and so on.
For some reason, sometimes a randomly a certain Object is destroyed. It just disappears and is gone. I can't figure out which script causes that. Is there a way to find out which script called Ondestroy or something.
Thanks for you help.
Put a brakpoint in the OnDestroy() method of your monobehaviour and check the call stack.
To debug your project you can check Debugging C# code in Unity. Once you figure that out and check how to attack unity and stop execution at the set breakpoints you can do with Window->Debug->Callstack to see the call stack with the execution stopped at your breakpoint and see what is being called that leads to your object destruction.
Simply have a component like e.g.
public class DestroyDebug : MonoBehaviour
{
void OnDestroy ()
{
Debug.Log($"{name} was just destroyed");
}
}
Either put a breakpoint there while Debugging your code if you need the exact instances and circumstances or also in the console you already can at least see the entire stacktrace of which classes and calls exactly led to destroy of this object.
If this is still an issue for you (or if anyone else has this issue), I had the same issue and found the solution here, which is to check gameObject.activeInHierarchy in OnDisable like so:
void OnDisable()
{
// If object will destroy in the end of current frame...
if (gameObject.activeInHierarchy)
{
Debug.LogError("Log an error with a stack trace in debug mode");
}
// If object just deactivated..
else
{
}
}

Performance optimisation : null check in Update()

I'm currently working on a basic AI for enemies in my space shooter project.
In my EnemyAI script, I've a public Transform target that I set when I instantiate a enemy. In the Update loop, I'm looking at the target, then moving using transform.towards and everything works fine. The problem is, the target can die, so I need to check if it is not null before doing all that. Problem is : apparently doing a simple if(target == null) is really bad performance wise, and I need to do it in Update. What should be the best approach to achieve that without having performance problems (let say I want 500 enemies at once). Should I still do it every X frame, cache the position of the target till the next check and move toward that cached result ? That could work but it would introduce jitter if the time between two check if too long.
I couldn't find any "easy" way but I hope there is one, it looks like something really simple and it's causing a lot of troubles :/
Null checks are not that expensive.
Coroutines can help spread the load over multiple frames. But carefully read about their memory usage / garbage collection problems.
You could speed that up using the ECS system (Entity Component System) in combination with C# Jobs (multithreaded)
Use the Profiler (Window -> Profiler) or (Window -> Analysis -> Profiler in 2018.3) to analyse what's actually taking long.
A for-each is bad (garbage-collection wise) compared to a normal for.
If you set position and rotation, group the two calls by using SetPositionAndRotation
Note null check with UnityEngine.Object children are NOT the standard C# null checks. This description that Jetbrains provides in relation to the Rider IDE and analysis tool gets into the details. The basic idea is that the C# script hands off the null check to the underlying C++ engine structure.
I have not had the need for it but I have seen other's code that keeps a simple list of UnityEngine.Object references. They add a reference to the object to the list when it is created. Then remove it from the list on destruction. Update() can then use a faster test in the list. Where speed is critical, you just test the list not the object. Of course, an approach other than a list could be used.
I looked it up and tested it and yes you can do this with a callback function which will be registered to your target's OnDestroy method. Your Player script should access target script and delegate the method like this:
public GameObject target;
private TargetScript myTargetScript;
void Start () {
myTargetScript = target.GetComponent<TargetScript>();
myTargetScript.OnDestroyEvnt += OnDestroyListener;
}
private void OnDestroyListener(MonoBehaviour instance)
{
Debug.Log("Callback is called");
}
Also Target script should be like this:
public event OnDestroyDelegate OnDestroyEvnt;
public delegate void OnDestroyDelegate(MonoBehaviour instance);
void Start () {
StartCoroutine(DestroyCoroutine());
}
private void OnDestroy()
{
if (this.OnDestroyEvnt != null)
{
this.OnDestroyEvnt(this);
}
}
IEnumerator DestroyCoroutine()
{
yield return new WaitForSeconds(5);
Destroy(gameObject);
}
I used a coroutine to destroy the object after 5 secs. It is actually irrelevant in your case. I adopted this code from here.
You can avoid it logic-wise, make a coroutine that only runs when you assign the target, and if the target is null, end the coroutine, that coroutine should have a...
yield return new WaitForEndOfFrame();
that way it will act as a kind of LateUpdate.
And check every frame...
while (target != null)
You would be still checking every frame the null, but you will only check the target = null once.

Unity calling methods on new scene

I have a game with a bunch of scenes, I load them and then do DoNotDestroy so I keep them (awake/start get called the first time).
Let's say we have following state changes - menu -> game -> game over -> menu -> game...
I want to call a method when the scene is shown each time to reset/set some values.
What's the cleanest way to do this? Currently I'm doing it with the update method, but it takes a bunch of lines and it's wasteful to use Update() in every script when you don't need to.
As per the Unity documentation on Multiple Scene Editing, it's recommended that you avoid DontDestroyOnLoad.
It is recommended to avoid using DontDestroyOnLoad to persist manager
GameObjects that you want to survive across scene loads. Instead,
create a manager scene that has all your managers and use
SceneManager.LoadScene(<path>, LoadSceneMode.Additive) and
SceneManager.UnloadScene to manage your game progress.
Therefore, in your case, you could handle resetting data in a number of ways. But one simple way would be to check the name of the scene that was just loaded, from a component in your "Manager" scene. E.g. MySceneManager in BaseScene. In the code following, we're making use of the sceneLoaded delegate of SceneManager.
using UnityEngine;
using UnityEngine.SceneManagement;
public class MySceneManager : MonoBehaviour
{
void OnEnable ( ) => SceneManager.sceneLoaded += OnSceneLoaded;
void OnSceneLoaded ( Scene scene, LoadSceneMode mode )
{
switch ( scene.name.ToLower ( ) )
{
case "menu":
// Do some "menu" initialisation here...
break;
case "game":
// Do some "game" initialisation here...
break;
case "gameover":
// Do some "gameover" initialisation here...
break;
}
}
void OnDisable ( ) => SceneManager.sceneLoaded -= OnSceneLoaded;
}
N.B. This method unfortunately won't have compile-time checking of your scene names, so you'll have to be careful to make sure your scene names correspond to the switch cases.
But, another thing the remember is that any component in your newly loaded scene will have Awake() called anyway, so you could just offload all of your scene initialisation to a component in each scene. This would decouple MySceneManager from the data in each scene.
So, you've got quite a few options, these being just two of them. The "best" option will be the one you're comfortable with, and that suits your needs.

What is the difference between GetComponent<Image> ().enabled and .SetActive (false); in unity

I have been trying to use SetActive () to turn on and off GameObjects.
I couldn't figure it out and ended up using:
GameObject.Find ("ObjectName").GetComponent<Image> ().enabled = false;
to turn off an image.
I am not trying to use the same script to turn off a GameObject that has multiple animations nested inside it.
GameObject.Find ("ObjectName").GetComponent<???> ().enabled = false;
GameObject.Find ("ObjectName").SetActive (false);
I am not sure what goes in the <>, but I have read I can do it with SetActive (), but that doesn't seem to work and gives me an "Object Reference not set to object" error.
So what is the difference between these two and how would I use them properly?
Using GetComponent allows you to enable/disable and interact with specific components on a GameObject.
For example, you may need to disable a GameObject's rigidbody at some point, but you still want that object, and everything else on it to be active. So you could simply say:
GameObject.Find("MyObject").GetComponent<Rigidbody>().enabled = false;
Note that what goes inside the "<>" is the class name of the component you want to interact with.
For example, if you had a script you have written yourself on a gameobject called MyScript, you could grab hold of it like so:
MyScript script = GamesObject.Find("MyObject").GetComponent<MyScript>().enabled = true;
Additionally, another good use of GetComponent is reading information from a script on an object.
For example, if you had a script called Health with a public variable HitPoints on an object, another script could gain access to that information using GetComponent.
if( enemyGameObject.GetComponent<Health>().HitPoints < 0 )
{
enemyGameObject.SetActive(false);
}
Using SetActive will enable and disable a GameObject entirely. This is less expensive than deleting / making a new object, and is thus often used in techniques like Object Pooling.
For example, if you had a GameObject that you needed disabled, but you knew you were going to need it again soon, it is far less expensive to just call
MyGameObject.SetActive(false);
...
MyGameObject.SetActive(true);
Than it is to delete that object entirely, and then make a new one when you are ready for it again.
To add up to the other answers, when a component is disabled it means the MonoBehaviour callbacks are not called anymore. So no Update, FixedUpdate, OnCollisionXXX and so on.
Awake is called when the object is created so it is obviously enabled by default at that stage. Start is called on the first run after Awake. So if you set the component off in Awake, Start will wait until you set it back on from elsewhere.
OnEnable/OnDisable are called when you modify the enabled property.
SetActive works on the GO and is pretty much a shortcut to disable all components at once.
gameObject.SetActive(false);
foreach(var comp in GetComponentsInChildren<MonoBehaviour>()){
comp.enabled = false;
}
those are fairly similar in result (maybe not in efficiency). Actually, when you set a game object on/off, the OnEnable/OnDisable of each component is called. All MonoBehaviour callbacks are not called anymore if you set the object off.
So, the choice is dependent on what you are after, if you wish to disable movement but still see the object and other actions:
GetComponent<Movement>().enabled = false;
if you wish to kill an enemy:
enemy.gameObject.SetActive(false);
Note that even though a component is disable, does not mean you cannot interact with it. You can still manually call any method on it. Consider this:
AnyComponent ac = gameObject.GetComponent<AnyComponent>();
ac.enabled = false;
ac.AnyMethod();
Valid and will do what it is meant to do considering it does not require an Update or a FixedUpdate (Physics action).
A deactivated component cannot be found with GetComponent, you can get it with GetComponentInChildren(true) since it also searches the game object and its children. I am not sure whether it returns the first found or the first active found.
myGameObject.SetActive(false);
AnyComponent ac = myGameObject.GetComponent();
AnyComponent acic = myGameObject.GetComponentInChildren(true);
even though the GO has a AnyComponent attached, ac is null, acic is not (seems to be a 5.3 feature though).
http://docs.unity3d.com/ScriptReference/Component.GetComponentInChildren.html
Finally, for a component to expose the tick, it needs to have a Start method in the script (don't ask why...).
Setting .enabled turns one component on a GameObject on or off, e.g. an Image. Using SetActive() turns the whole GameObject on or off.
Choosing which to use should correspond with what you want to disable.

Awake() and Start()

I see that we can initialize Variable in Awake() or Start() and Awake() will be called before Start().
When should we initialize in Awake and Start to have the best performance?
Usually Awake() is used to initialize if certain values or script are dependent on each other and would cause errors if one of them is initialized too late (awake runs before the game starts).
Awake is also called only once for every script instance.
Let me quote the Documentation:
[...] Awake is called after all objects are initialized so you can safely speak to other objects or query them using eg. GameObject.FindWithTag. Each GameObject's Awake is called in a random order between objects. Because of this, you should use Awake to set up references between scripts, and use Start() to pass any information back and forth. Awake is always called before any Start functions. This allows you to order initialization of scripts. Awake can not act as a coroutine.
and about Start():
Start is called on the frame when a script is enabled just before any
of the Update methods is called the first time.
Like the Awake function, Start is called exactly once in the lifetime
of the script. However, Awake is called when the script object is
initialised, regardless of whether or not the script is enabled. Start
may not be called on the same frame as Awake if the script is not
enabled at initialisation time.
Where the last part makes one big difference
To get to your question:
If the script is NOT enabled at the beginning of your game, and you don't need the variables to be initialized, start would be saving performance as awake() would be called regardless...
every variable would be initialized at the very beginning. At least that's the logical assumption I make.
This topic is well described in the official docmentation (Awake and Start).
This section describes why you might need two functions:
The Awake function is called on all objects in the scene before any
object's Start function is called. This fact is useful in cases where
object A's initialisation code needs to rely on object B's already
being initialised; B's initialisation should be done in Awake while
A's should be done in Start.
The difference between Awake and Start is that Start is called only when a script is enabled.
These two functions are called before the first Update method and there is no performance difference between them. I would say that Awake is used to initialize all objects (like a constructor), and Start is used to link the objects or do something before a game starts.
Awake is the equivalent of the ctor. It is called when a MonoBehaviour is created, before any other method if the object is active.
Start is run the first time the MonoBehaviour is activated. This can be right after Awake or long after. This allows to perform actions that are related to the current state of the app or objects.
For instance, you create an enemy, in Awake, you place everything that is basic initialisation. Then, the enemy is deactivated at the end of Awake. Later on, the enemy is about to be activated but you want to make it red if player is having some specific weapon, then you do it in Start.
IMPORTANT: If a prefab is created and the game object is off by default in the prefab, the Awake is not called until set on. In the case of a pool creation where prefab may be off, the awake is happening first time the pooled object is activated.
OnEnable is similar to Start but happens on every SetActive(true) and on start if enabled. This can be a candidate for your enemy willing to change color over the level based on the player magna for instance.
There's not much difference in the performance. But I can tell you a difference between them.
Take a simple example. Say if you want to print "HELLO" in console even if you have not activated the script in inspector, using Awake() function, you can print it in the console. But if you had written the same thing in Start() function and the script wasn't activated, you don't get any output in the console. That's the difference.
Codes in Start() function get executed only if the script is activated while, codes in Awake() function get executed even if the script is not activated. Try it !
I'd claim there is no real performance difference at all.
What Minzkraut stated
If the script is NOT enabled at the beginning of your game, and you don't need the variables to be initialized, start would be saving performance as awake() would be called regardless...
every variable would be initialized at the very beginning. At least that's the logical assumption I make.
is only semi true. If you do everything only in Start the UX might be even worse since instead of one bigger lag when starting the app - which in my eyes is totally acceptable - it might lead to smaller but more lags during game play which I personally would avoid as much as possible.
In general it was already often explained in the other answers how and when Awake and Start are called and that basically it is "just" a timing difference.
For details refer to Execution Order of Events
Leaving disabled components and inactive GameObjects aside my personal thumb rule is
Use Awake for everything where you don't rely on any other component and references.
E.g. set default field values, populate things using GetComponent etc
Use Start for everything where you do rely on other components such as accessing the results of GetComponent
This way these other components supposedly did already receive their Awake call so they themselves are already linked up and ready to be used by others.
This solves timing and dependency issues in the most cases.
Where this is not enough you would start to tweak the Script execution order or use events.
And then there is another quite important difference in the use case of using Instantiate or AddComponent
Awake (and OnEnable except using Instantiate and the component is disabled) will be called right away during the instantiation and any code line after Instantiate will be executed after it is finished.
Start however will be delayed until the end of that frame (or until enabling if the component was disabled in Awake).
This allows you to have enough time to use Instantiate and modify some field values before Start is called and can now base its behavior on the modified field values.
For example this
public class Example : MonoBehaviour
{
private class X : MonoBehaviour
{
public int x = -1;
private void Awake()
{
Debug.Log($"Awake {x}");
x = 12;
}
private void OnEnable()
{
Debug.Log($"OnEnable {x}");
}
private void Start()
{
Debug.Log($"Start {x}");
}
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
Debug.Log("Instantiate");
var x = gameObject.AddComponent<X>();
Debug.Log("After instantiate");
x.x = 42;
}
}
}
will produce the output
Instantiate
Awake -1
OnEnable 12
After Instantiate
Start 42