Search Unity

Resouces.Load call from constructor

Discussion in 'Scripting' started by dunloip, Aug 21, 2018.

  1. dunloip

    dunloip

    Joined:
    Aug 8, 2018
    Posts:
    15
    I'm trying to define a static variable in order not to have to declare it in every instance of the class Module:

    Code (CSharp):
    1. public class Module : MonoBehaviour {
    2.  
    3.     private static readonly Sprite buttonInactive = Resources.Load<Sprite>("Sprites/ButtonInactive");
    4.     // ...
    5. }

    But apparently, Load can not be called from there, since I get the following exception:

    Load is not allowed to be called from a MonoBehaviour constructor (or instance field initializer), call it in Awake or Start instead.


    Is there a simple way to work this around? If I do what Unity suggests and define this variable in Awake, I would have to load the image from Resources for every instance, which seems inefficient. I could also link the sprite from the inspector, I guess, but I'm trying to avoid working with it as much as I can. Any other ideas?
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,686
    Yes, put it in Awake();, as they say. :)

    I dunno how many frazillions of objects you contemplating having, but since a Resources.Load<>() call on something that has already been Resource.Load<>()'ed once is likely just a Dictionary lookup, I think you'll be just fine.

    Besides, if you're sticking it in a static ANYWAY, just guard it with a null check first!
     
  3. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    5,358
    Code (CSharp):
    1. protected void Awake()
    2. {
    3.    buttonInactive = buttonInactive ?? Resources.Load<Sprite>("Sprites/ButtonInactive");
    4. }
     
  4. dunloip

    dunloip

    Joined:
    Aug 8, 2018
    Posts:
    15
    Yes, but this way I have to get rid of the const/readonly access.

    Are you sure about that? I've seen some discussion in the forum about it I can't find any documentation from Unity about it either.
     
  5. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    5,358
    Yeah I know, its really sad.
     
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,686
    Possibly because it may turn out to be platform and/or implementation dependent, but more likely because it is NOT something you should even be remotely agonizing about.

    I can't help you with language mumbo jumbo, but if I were you, I would do it the way I outlined in the above post, loading it only as null.

    Or alternately, this way. I assure you, it won't make any measurable difference.

    Code (csharp):
    1. static Sprite _buttonInactive;
    2. static Sprite buttonInactive
    3. {
    4.   get
    5.   {
    6.     if (!Sprite) buttonInactive = Resources.Load<Sprite>("Sprites/ButtonInactive");
    7.     return buttonInactive;
    8.   }
    9. }
     
  7. Madgvox

    Madgvox

    Joined:
    Apr 13, 2014
    Posts:
    1,317
    You can also use a static constructor:

    Code (CSharp):
    1. public class Module : MonoBehaviour {
    2.  
    3.     private static readonly Sprite buttonInactive;
    4.  
    5.     static Module () {
    6.         buttonInactive = Resources.Load<Sprite>("Sprites/ButtonInactive");
    7.     }
    8.     // ...
    9. }
    The constructor will run on the first call to a static field.
     
    erenaydin likes this.