Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 11 Next capture
2021 2022 2023
1 capture
11 Jun 22 - 11 Jun 22
sparklines
Close Help
  • 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
1
Question by Bitcoon · Jul 05, 2015 at 09:17 AM · referenceoutref

Long-term use of ref/out?

-question, in short, at the bottom-

I'm using C#, trying to implement achievements (which are tied directly into unlockables) into my mobile game. The problem is, I'm trying to store a reference to a boolean value for later use, and I'm starting to realize I've never had to do this before and I'm not sure how to make it work.

The way I've tried to set it up, I created a public class called Achiev, which contains all the relevant data. That's the achievement ID, name, boolean to determine if it's unlocked, a few other things, and finally, a reference to the boolean that determines if the unlockable is available to use in the game.

 public class Achiev //class for achievements
     {
         public int number; //amount of whatever thing you need to unlock this (if applicable)
         public string achID; //Achievement ID - Google Play
         public string name;
         public string description;
         public string itemType; //"pixel block style", "bubble background", etc
         public int level; //"rank" of tiered achievements. Can be 1, 2, or 3. Each one has its own overlaid sub-icon
         public Sprite icon;
         public bool unlocked; //has this achievement been unlocked?
         public bool unlockRef; //reference(?) to bool variable which actually determines if unlockable is available to player
 
         public Achiev(int num, string ID, string nam, string desc, string type, int lev, Sprite ico, bool unl, ref bool uRef)
         {
             number = num;
             achID = ID;
             name = nam;
             description = desc;
             itemType = type;
             level = lev;
             icon = ico;
             unlocked = unl;
             unlockRef = uRef;
         }
     }

Unlockables are all tied to boolean arrays - one 1-dimensional array for each type of unlockable. What I tried to do is have a ref boolean value on each instance of the Achiev class point to a bool in one of those various arrays, so when it comes time to unlock that achievement in the code, it can simply set that ref value to true and that thing will be shown as unlocked. It's not necessary, honestly, but it does put all that info together in one place in the code so it's easy to change.

Here's an example of one of the achievements in code:

 achievementList[i] = new Achiev(250000,"CgkInv_rlsMXEAIQDA","Adept Number Wizard","Earn a total of 250,000 points.","Blue blocks background",1,cst.sprNumberWiz,unlockAchievements[i],ref unlockBackground[1]);

It should be obvious why, because the variable declaration in the class itself isn't a reference (as far as I can tell, syntax won't let me do that), but when I later go on to change the value of unlockRef, it certainly doesn't reflect that change in the referenced variable. It seems ref and out keywords are only meant to work within the limited scope of a single function. Quick research says pointers might do the trick, but they're considered 'unsafe' code, so I would assume it would be better to go with plan B (hard-coding the boolean values into the function which unlocks variables) instead.

So, I'm not so much asking this question because I'm stuck and need help, but knowing a better way to handle this kind of thing will definitely help in the future when I'm coding more expansive and complex games, and it would help now so I can do this right the first time.

Is there a way to store a reference to another variable like this for later use, or simply a better way to handle what I'm trying to do here?

Thanks for your time~

Comment
Add comment
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

1 Reply

· Add your reply
  • Sort: 
avatar image
2
Best Answer

Answer by Bunny83 · Jul 05, 2015 at 01:14 PM

The short answer is No, there isn't a way to store a reference / pointer to a variable without an unsafe context.

"ref" and "out" are actually implemented as pointers, however due to the compiler restrictions it's ensured that no unsafe situation can occur. In a safe context you can't store pointers in a variable. The only "pointer like" type is a reference which only works for reference types.

If you want "reference access" to a valuetype variable you can use a wrapper class. This class could use either closure get / set methods which you setup accordingly for your variable, or use relfection.

Here's an example wrapper with the closure approach:

 public class ValueTypeWrapper<T>
 {
     private System.Func<T> getMethod;
     private System.Action<T> setMethod;
     public ValueTypeWrapper(System.Func<T> aGetMethod, System.Action<T> aSetMethod)
     {
         getMethod = aGetMethod;
         setMethod = aSetMethod;
     }
     public T Value
     {
         get{ return getMethod();}
         set{ setMethod(value); }
     }
 }

With this class you can create an instance of that class to get / set for example a boolean variable of another class:

 public class TargetClass
 {
     public bool targetVar;
 }
 
 public class SomeOtherClass : MonoBehaviour
 {
     ValueTypeWrapper<bool> boolRef;
     void Start()
     {
         TargetClass target = GetComponent<TargetClass>();
         boolRef = new ValueTypeWrapper<bool>( ()=>target.targetVar, v=>targetVar=v);
     }
 }

Since "boolRef" is a class you can pass it's reference around and store it somewhere if you like. You can use the "Value" property to read / write the bool variable in the target class.

 // this will turn the "targetVar" in the target class instance to "true".
 boolRef.Value = true;

A reflection based approach allows a more dynamical approach but it's way slower and might be even more difficult to use (and it's easier to introduce runtime errors if you're not careful).

However even a wrapper class (kind of adapter pattern) might be useful in some cases, it's usually better to use references to the class itself and just read / write the variables you need directly. You can abstract this a little bit with interfaces.

 public interface IGroundable
 {
     bool IsGrounded {get;}
 }
 
 public class TargetClass : MonoBehaviour, IGroundable
 {
     private bool m_IsGrounded;
     public bool IsGrounded {get {return m_IsGrounded; }}
 }

That way you can assign a reference to an instance of TargetClass to a "IGroundable" reference and use the "IsGrounded" property to check the state without knowing the actual type.

Directly accessing / referencing individual members of a class actually isn't possible without pointers. Such an approach also kind of "breaks out" of the OOP nature where you usually work with objects and accessing it's members and don't deal with the members seperately.

Comment
Add comment · Show 1 · 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 Bitcoon · Jul 06, 2015 at 06:18 AM 0
Share

Sounds like if I had a better reason to use this, it could be handy, but for my purposes I'm probably better going with the old Plan B. It's good to know there is a way to get this to work if I do need it in later projects, but given that I'd only need it for this one small thing, it's probably more trouble than help. Thanks for the answer~

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.

Follow this Question

Answers Answers and Comments

22 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 avatar image avatar image avatar image avatar image

Related Questions

Unity4, Unityscript added "ref" or "out" keyword? 1 Answer

Is it possible to pass a variable by reference in javascript 1 Answer

Getting a reference to a class created in a different gameObject (Javascript) 1 Answer

GUI problem: Lack of Events and Listeners. 1 Answer

Default References of a Script 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