• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by Exalia · Sep 18, 2013 at 10:35 AM · androidaccessglobalglobal variableglobal script

Global Scripts/Variables

Hi, I'm creating a game with multiple levels. I'm trying to grab the native Resolution of the screen my game is running on and store it. Then use this native resolution value and divide by the current resolution to get a ratio. (This way I can scale things, mainly my GUI for different resolutions)

(Feel free to suggest other ways to do this but ultimately I would like to learn how/if it's possible to have global scripts that work on every level)

Thanks in advance

EDIT :

The way I'm currently doing this is creating an Empty game object and attaching a script, on Start() I use DontDestroyOnLoad(gameObject); However this causes some issues with null values in my script :(

Comment
Add comment · Show 15
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image syclamoth · Sep 18, 2013 at 10:54 AM 1
Share

Obviously, you have the option of just using static classes for this, but from a software design perspective that's pretty stinky.

avatar image ArkaneX · Sep 18, 2013 at 11:02 AM 0
Share

Why do you think it's stinky? I would do it as static without hesitation. $$anonymous$$aybe not the whole class, but as static property:

 public static Vector2 Ratio
 {
     get { return ratio_calculation_expression; }
 }
avatar image syclamoth · Sep 18, 2013 at 11:06 AM 1
Share

I think it's stinky because it breaks the rules of object oriented program$$anonymous$$g. There's pretty widespread discussion on this subject elsewhere, but this page pretty well sums up my feelings on the matter.

avatar image Exalia · Sep 18, 2013 at 11:07 AM 0
Share

Interesting, so what are my less stinky options?

avatar image syclamoth · Sep 18, 2013 at 11:11 AM 1
Share

Well, initially I would have suggested that 'empty gameobject/DontDestroyOnLoad()' thing, but you say that causes problems for you. Care to elaborate? It's what I've always done, and it's never given me any trouble.

avatar image ArkaneX · Sep 18, 2013 at 11:17 AM 0
Share

I took a look at the page you linked. I haven't read this one before, but you're right - there are many other articles/posts/questions related to this subject (as well as to statics vs singletons, which are sometimes similar).

In my opinion, using statics is still very good option for specific situations. Especially if you just need a read only variable. Without this, we would not have Vector3.zero, Camera.main, Int32.$$anonymous$$axValue etc. For these values, it is perfectly ok to use them without creating class instance. It's not only performance wise - it's just logical.

avatar image Exalia · Sep 18, 2013 at 11:22 AM 0
Share

That's cool sycla I expected as much.

Basically I have a script that grabs the Res when it starts (This object is in the first scene that is loaded.)

 using UnityEngine;
 using System.Collections;
 
 public class ScreenResolutionScript : $$anonymous$$onoBehaviour 
 {
     //Public Variables
 
 
     //Private Variables
     private int nativeResH;
     private int nativeResW;
     private int resRatio;
 
     void Start () 
     {
         DontDestroyOnLoad(gameObject);
         SetResH(Screen.currentResolution.height);
         SetResW(Screen.currentResolution.width);
         resRatio = Screen.currentResolution.height / nativeResH;
     }
 
     public void SetResW(int res)
     {
         nativeResW = res;
     }
 
     public void SetResH(int res)
     {
         nativeResH = res;
     }
 
     public void SetResRatio(int res)
     {
         resRatio = res;
     }
 
     public int GetResH()
     {
         return nativeResH;
     }
 
     public int GetResW()
     {
         return nativeResW;
     }
 
     public int GetResRatio()
     {
         print(resRatio);
         return resRatio;
     }
 }

This works perfectly fine in the first scene, however when I load to the next scene none of my Gets work they all produce 0 values. I get a divide by 0 when trying to find the ratio and printing the values also showed a 0. I set my private variables to public so I could see them in the Editor and the values were correct.

I assume I'm missing something very basic :(

avatar image Hoeloe · Sep 18, 2013 at 11:30 AM 0
Share

@syclamoth: Static variables and classes are fine - they are in fact extremely useful, and more efficient in places. You do have to be careful how you use them, but that's true of just about any feature. You of course should only use them when really necessary, but saying they are on the whole useless is laughable. Yes, you can write code without them, but you can also write code without arrays, or else blocks: it doesn't mean you shouldn't. In this case, a static variable is the correct approach, as the game will only be rendering to one screen.

Have a look at this page, it explains why actually, static methods and members are GOOD practice, where appropriate: http://www.velocityreviews.com/forums/t117353-advantages-of-static-vs-instance-methods.html

avatar image syclamoth · Sep 18, 2013 at 11:35 AM 1
Share

On an unrelated note, are you sure resRatio should be an int? That looks wrong, unless it does something different from what I think it does.

As for the invalid values thing, I can think of 3 things that might be happening:

1: the object is being serialised and deserialised, like what happens when you reload your assemblies at runtime. I can't really tell why that would be happening, but the symptoms are the same.

2: there is a version of the object in the newly loaded scene that is confusing other parts of the system? Now that I think about it this seems unlikely, as it's a pretty obvious mistake to make, but still worth checking. How are you accessing this object elsewhere?

3: Start is being called more than once. Again, this is something that shouldn't happen.

avatar image Exalia · Sep 18, 2013 at 11:39 AM 0
Share

You are completely correct it should be a float.

 public GameObject globalScripts;
 
 //...
 
 ScreenResolutionScript reScript = globalScripts.GetComponent<ScreenResolutionScript>();
 
 
avatar image syclamoth · Sep 18, 2013 at 11:41 AM 1
Share

@Hoeloe 'executes faster' and 'good practice' are not always the same thing. Unless performance is your number 1 priority it is generally better to adhere to OOP principles where possible. That link of yours explains that static functions are faster (which, for that matter, is fairly implementation-specific and may not even apply to C#), not that they are better.

avatar image syclamoth · Sep 18, 2013 at 11:43 AM 1
Share

Where do you set 'globalScripts'? Is it a game object that gets loaded with the scene, or does it get set after the scene has laoded?

avatar image Exalia · Sep 18, 2013 at 11:47 AM 0
Share

I'm afraid to answer this because it's kind of amature but I just drag it into the public variable box in the inspector.

I guess I could define it at runtime by using

 globalScripts = GameObject.FindGameObjectWithTag("Global");
avatar image Exalia · Sep 18, 2013 at 11:51 AM 0
Share

Haha It works now, it's printing 1s :) and although it wasn't the major issue I wont run into the issue of trying to put a float into an int ^^ cheers syclamoth <3 thanks for the help

avatar image Hoeloe · Sep 18, 2013 at 11:55 AM 0
Share

@Syclamoth That is true, but in general terms, static variables are also easier to understand and maintain than some of their more roundabout alternatives. While it may not be "strict OOP", I'm a believer in using the tools available to you where appropriate, and not trying to circumvent them simply because it's not strictly part of this type of language. There are a lot of things like this in most OOP languages. Hell, Java has even added lambda notation in Java 8. I do not believe that it is better practice to try and circumvent the tool than to use it in an appropriate manner.

1 Reply

· Add your reply
  • Sort: 
avatar image
1

Answer by Bampf · Sep 18, 2013 at 11:41 AM

Yes, it is possible to have global scripts that work on every level.

You can add static methods to any class that you define. These methods don't need an instance of the object to be called. You would call something like "MyClass.getScreenRatio" instead of someObject.getScreenRatio.

The trick there is that you want it to work regardless of which scene is loaded first. But this isn't hard, you just need to initialize it the first time it is used if it hasn't been initialized yet.

 private static Vector2 screenRatio = null;
 public static Vector2 getScreenRatio()
 {
     if (screenRatio == null) {
         screenRatio = // do calculation here
     }
     return screenRatio;
 }


As for your original trick (empty game object, DontDestroyOnLoad) that can be made to work. You were getting null errors but I suspect those could be solved with a similar trick to the one I showed above, to guarantee that something is initialized the first time it is accessed.

This game object approach has a very compelling feature, which is that the object will get all the Unity calls (OnUpdate, etc.) However there is a major problem with that strategy, which is that it requires you always have to run your game starting from the level that defines the empty game object. You couldn't debug a different scene in the Unity editor, for instance. So then you end up adding the same empty game object to multiple levels, but then every time you switch scenes you get another one.

What you'd want is a game object that always is around, but there is always exactly one of them, no more, no less. This problem is called a Singleton. Here's a good discussion of ways to do them in Unity: http://redframe-game.com/blog/global-managers-with-generic-singletons/

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image ArkaneX · Sep 18, 2013 at 11:53 AM 0
Share

@Bampf - if the code you posted is supposed to be a method, add parentheses. If it is property, add a getter.

avatar image Bampf · Sep 20, 2013 at 06:19 PM 0
Share

Thanks. I had intended it as an outline/pseudocode (note it's still incomplete, the commented line won't compile). But I agree with you that it was misleading and have added them.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

18 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Control Permition Access 1 Answer

Global variables questions 5 Answers

Create a persistent GameObject using Singleton 3 Answers

Access variable in another object 1 Answer

Creating a unit/library/module and accessing globally without instantiation 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges