Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Globally accessible constant?

Discussion in 'Scripting' started by Marscaleb, Feb 29, 2016.

  1. Marscaleb

    Marscaleb

    Joined:
    Jan 7, 2014
    Posts:
    992
    I have a number of functions that check for collisions, and these require using a layermask to check between certain types of objects. I found out the int value of these layermasks, and I have been supplying that number to my functions so that I don't need any extra variables or cycles at run-time.

    But writing out four-digit arbitrary numbers is a little confusing to keep track of, so I think I want to just make a const so that I can type an easy-to-remember name. And I might want to be able to use these in several classes, so I believe that means they ought to be global.

    But the only global variables I have done before are enums, and there seems to be something wrong with my syntax, because monodevelop keeps underlining stuff.

    To be very clear, in case I have some terms wrong, I am trying to declare a variable at the very top of my script, between the "using" and "Public class MyScript : monobehavior" so that any script can access this variable. And it is not a variable, it is a constant, because its value is never going to change. I just want to write a name for some otherwise arbitrary int values that will be used a lot.

    What is the proper syntax for that?

    I tried writing "public const int WorldCollLayer = 4097;" but monospace underlines the const and I get a parsing error if I try to compile.
     
  2. bdev

    bdev

    Joined:
    Jan 4, 2011
    Posts:
    656
    you cannot do this in c#. Your best bet is to instead make a static class that defines them.
    Code (csharp):
    1.  
    2. public static class Const {
    3. public const int WorldCollLayer = 4096;
    4. }
    5.  
    then accessing it in your scripts as Const.WorldCollLayer

    an heavy alternative would be to have a base class for everything you inherit from, but that ultimately isnt very optimal and pretty much impossible to maintain unless everything extends what your base does.
     
  3. Marscaleb

    Marscaleb

    Joined:
    Jan 7, 2014
    Posts:
    992
    Hmm. Not what I was hoping to hear.

    Oh the other hand, most classes that will be needing this const will be extended from a single base class. Possibly all of them, but I am not certain if I won't need some extra behavior that will need this value.

    ...why would using a base class not be optimal? I mean, I assume that you are referring to creating an all-new base class with only these constants defined, and having pretty much all of my scripts extend from that class if they want to use the consts. (As opposed to how I am already creating a base class that is utilizing many features that other classes will need.) And I can see that it would be a little more effort since I would need to extend a bunch of scripts. But are you saying it would be more taxing on the system than using a static class?
     
  4. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    Extending from a common base class simply to inherit constants isn't a justifiable design decision.

    We have a static class called GameConstants.
    Code (csharp):
    1.  
    2. public static class GameConstants
    3. {
    4.     public const int EnemyLayer = 10;
    5.     public const int EnemyMask = 1 << EnemyLayer;
    6. }
    7.  
    8. if (Physics.Raycast(ray, GameConstants.EnemyMask)
    9.  
    Not sure how you could get more clear than that....
     
    Kiwasi likes this.
  5. bdev

    bdev

    Joined:
    Jan 4, 2011
    Posts:
    656
    The ultimate reason it wouldn't work comes down to you'd need to extend your base from monobehaviour, which means if you were to ever write ScriptableObject 's (either directly, or through the Animator controller behaviour stuff.. which do not extend monobehaviour at all) or plain old classes not extending monobehaviour you'd be out of luck because C# also does not support multiple inheritance beyond interfaces (which you may not store constants or utility methods in anyways).

    Performance wise, having inheritance with only the goal of sharing constants is (or any type of constraint to benefit you as a developer over performance of the end user) is over kill. When the compiler does stuff like casting, it provides it with an unnecessary rung to climb up or down. many would argue that it would be insignificant amount of performance loss however its a slippery slope in my opinon.

    One last thing about performance with const fields, at runtime there is actually no constant lookups at all. The moment your code gets compiled, all references to const fields are replaced inline. So it wouldn't make your code any slower or faster to have a base or static class in regards to constant access. The thing that makes runtime slower is having long chains of inheritance (expressly if you utilize virtual) for no good reason (besides less typing).
     
    Last edited: Feb 29, 2016
  6. Marscaleb

    Marscaleb

    Joined:
    Jan 7, 2014
    Posts:
    992
    Thank makes sense.
    Thank you for the clarification!