- Home /
 
ArgumentException: NameToLayer can only be called from the main thread
I was hoping to cache the response of the NameToLayer function as I suspect it will offer better performance (even if only minimal). Whilst the following source does in fact work, I would like to avoid the warning/error.
 public class MyObject : MonoBehaviour {
 
     public static readonly int LAYER_PROJECTILE;
     static MyObject() {
         LAYER_PROJECTILE = LayerMask.NameToLayer("Projectile");
     }
     ...
     void OnTriggerEnter(Collider collider) {
         if (collider.gameObject.layer == LAYER_PROJECTILE) {
             ...
         }
         else { ... }
     }
 }
 
               Is there a better approach to this (that doesn't involve storing the layer number in every single object instance?
Note: Error message is only logged when loading scene in editor, there are no problems when compiled.
Answer by syclamoth · Feb 29, 2012 at 01:41 AM
Well, since you are using C#, I can give you plenty of better ways!
For starters, you shouldn't be using the constructor in a MonoBehaviour-derived class, for any reason. Any functionality you put in there should be invoked in the
 void Awake()
 {
 }
 
               method, instead.
If you want to make a lazily-evaluated constant int for the layer, try doing it like this:
 int _projectileLayer = -1;
 int projectileLayer{
     get {
         if(_projectileLayer == -1)
         {
             _projectileLayer = LayerMask.NameToLayer("Projectile");
         }
         return _projectileLayer;
     }
 }
 
               Then, you can use 'projectileLayer', and it will only ever calculate the value once per run.
You should avoid using static variables, just on principle- after all, it is possible that you'll want to use the same script to shoot projectiles from several different layers at one point, so storing it in a static variable will limit you in the indeterminite future.
In any case, you're right to try to speed things up- although keep in mind that in the timeless words of Donald Knuth: "premature optimisation is the root of all evil".
I have been using Start to construct my objects, I will have to look into the difference between Awake and Start! I will take that approach, cheers!
First, static constructors are okay as long as you don't use Unity functions. Second, usually you want to perform expensive operations at the start of a scene to reduce hiccups, i.e. avoid lazy loading. Third, the questioner was trying to avoid storing the data separately in each instance.
Your answer