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. Dismiss Notice

User defined get / set functions

Discussion in 'Scripting' started by boylesg, Jun 17, 2016.

  1. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    If I want to fetch the state of my controls, e.g. autotumbler on or off, before sending them off to Bingo game manager, then it appears that the only way to do so is to write a specific function that accesses the specific script attached to that specific control. As in the code excerpt below.

    Code (CSharp):
    1.     protected bool GetAutoTumbler()
    2.     {
    3.         GameObject gameobj = FindGO("AutoTumbler");
    4.         AutoTumblerButtonManager script = gameobj.GetComponent<AutoTumblerButtonManager>();
    5.         return (bool)script.IsChecked();
    6.     }

    This is a direct result of the separation, in Unity, between user defined data/functions and Unity defined data/functions.

    In contrast with windows MFC, a user defined dialog box would have the following inheritance hierarchy: CMyDialogBox: CDialogEx : CWnd

    In class CWnd you have the function GetDlgItem(UINT) where UINT is the unique integer ID of a control contained within your dialog box.

    So if you want to get the checked state of a check box control then you would simply do
    Code (CSharp):
    1. ((CCheckBox*)GetDialogItem(IDC_CHECK_AUTO_TUMBLER))->GetCheckState()
    This would be the same function call for any check box control in any dialog box – the only thing that would vary would be the control ID you pass to GetDialogItem(...)

    Code (CSharp):
    1. ((CCheckBox*)GetDialogItem(IDC_CHECK_AUTO_TUMBLER))->GetCheckState()
    2.  
    3. ((CCheckBox*)GetDialogItem(IDC_CHECK_TUMBLER_ON))->GetCheckState()
    4.  
    5. ((CCheckBox*)GetDialogItem(IDC_CHECK_SOMETHING_ELSE))->GetCheckState()

    However in Unity I would need to define a specific ‘get’ function for every check box I define in every dialog box script/class I create whose game object contains that check box as a child.

    It is OK if you don’t have too many instances where you need to immediately get the state of a check box and you don’t have too many ‘dialog’ boxes that contain check boxes.

    But if your app was a lot more complicated and did contain a lot of check boxes and many dialog boxes, then having to do this is a monumental pain in the ar$e.

    So my question is this. Are there any ways of doing this better with code that is more generic and re-usable?

    Code (CSharp):
    1.     protected bool GetAutoTumbler()
    2.     {
    3.         GameObject gameobj = FindGO("AutoTumbler");
    4.         AutoTumblerButtonManager script = gameobj.GetComponent<AutoTumblerButtonManager>();
    5.         return (bool)script.IsChecked();
    6.     }
    7.  
    8.     protected bool GetTumblerOn()
    9.     {
    10.         GameObject gameobj = FindGO("TumblerOn");
    11.         TumblerButtonManager script = gameobj.GetComponent<TumblerButtonManager>();
    12.         return (bool)script.IsChecked();
    13.     }
    14.  
    15.     protected void GetPattern(ref PatternEnum enPattern, ref ulong nBits)
    16.     {
    17.         GameObject gameobj = FindGO("ToggleButtonGroupManager");
    18.         ToggleButtonGroupManager script1 = gameobj.GetComponent<ToggleButtonGroupManager>();
    19.         enPattern = (PatternEnum)script1.GetVal();
    20.  
    21.         gameobj = FindGO("CustomToggleButton");
    22.         CustomPatternButtonManager script2 = gameobj.GetComponent<CustomPatternButtonManager>();
    23.         nBits = script2.GetBits();
    24.     }
    25.  
    26.     protected VoiceEnum GetVoice()
    27.     {
    28.         GameObject gameobj = FindGO("Voice");
    29.         VoiceButtonManager script = gameobj.GetComponent<VoiceButtonManager>();
    30.         return (VoiceEnum)script.GetValue();
    31.     }
    32.  
    33.     protected override void DoReceiveMessage(Parameters p)
    34.     {
    35.         if (p.m_nMsgID == BingoMessageIDEnum.MSGID_CHANGE_PATTERN)
    36.         {
    37.             m_enPattern = (PatternEnum)p.m_objParam1;
    38.             ulong nBits = (ulong)p.m_objParam2;
    39.             m_objCustomPattern.SetBits(nBits);
    40.             SendMessage("CustomPatternManager", p);
    41.         }
    42.         else if (p.m_nMsgID == BingoMessageIDEnum.MSGID_SAVE_BUTTON_CLICKED)
    43.         {
    44.             m_bAutoTumbler = GetAutoTumbler();
    45.             m_bTumblerOn = GetTumblerOn();
    46.             m_enVoice = GetVoice();
    47.             ulong nBits = 0;
    48.             GetPattern(ref m_enPattern, ref nBits);
    49.             m_objCustomPattern.SetBits(nBits);
    50.  
    51.             m_parameters1.New(BingoMessageIDEnum.MSGID_SAVE_OPTIONS, m_bAutoTumbler, m_bTumblerOn, m_enPattern, m_enVoice, m_objCustomPattern.GetBits());
    52.             SendMessage("BingoManager", m_parameters1);
    53.             SendMessage("BingoManager", BingoMessageIDEnum.MSGID_SET_FOCUS);
    54.         }
    55.         else if (p.m_nMsgID == BingoMessageIDEnum.MSGID_SHOW_OPTIONS)
    56.         {
    57.             m_bAutoTumbler = (bool)p.m_objParam1;
    58.             m_bTumblerOn = (bool)p.m_objParam2;
    59.             m_enPattern = (PatternEnum)p.m_objParam3;
    60.             ulong nBits = (ulong)p.m_objParam4;
    61.             m_enVoice = (VoiceEnum)p.m_objParam5;
    62.             m_objCustomPattern.SetBits(nBits);
    63.  
    64.             m_parameters1.New(BingoMessageIDEnum.MSGID_SET_BUTTON_STATE, "AutoTumbler", m_bAutoTumbler);
    65.             SendMessage("AutoTumbler", m_parameters1);
    66.  
    67.             m_parameters1.New(BingoMessageIDEnum.MSGID_SET_BUTTON_STATE, "TumblerOn", m_bTumblerOn);
    68.             SendMessage("TumblerOn", m_parameters1);
    69.  
    70.             m_parameters1.New(BingoMessageIDEnum.MSGID_SET_BUTTON_STATE, "Voice", (int)m_enVoice);
    71.             SendMessage("Voice", m_parameters1);
    72.  
    73.             m_parameters1.New(BingoMessageIDEnum.MSGID_NOTIFY_TOGGLE_BUTTON_CHECKED, GetToggleButtonGameObject(m_enPattern), m_enPattern);
    74.             SendMessage("ToggleButtonGroupManager", m_parameters1);
    75.  
    76.             m_parameters1.New(BingoMessageIDEnum.MSGID_SAVE_PATTERN, PatternEnum.CUSTOM, m_objCustomPattern.GetBits());
    77.             SendMessage("CustomPatternManager", m_parameters1);
    78.  
    79.             m_parameters1.New(BingoMessageIDEnum.MSGID_CHANGE_PATTERN, m_enPattern, nBits);
    80.             SendMessage("CustomPatternManager", m_parameters1);
    81.             SendMessage("CustomToggleButton", m_parameters1);
    82.  
    83.             SetFocus();
    84.         }
    85.         else if (p.m_nMsgID == BingoMessageIDEnum.MSGID_CANCEL_BUTTON_CLICKED)
    86.         {
    87.             SendMessage("BingoManager", BingoMessageIDEnum.MSGID_SET_FOCUS);
    88.         }
    89.         base.DoReceiveMessage(p);
    90.     }
    91.  
     
  2. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    Just reading a few threads about how others have gone about it and I suppose I could do this sort of thing:
    Code (CSharp):
    1. Find("CheckBox").GetComponent<AutoTumblerButtonManager>().GetCheckState();
    And if GetCheckState is defined in a base class which all check box game objects are derived from.

    I guess it is not all that different from:
    Code (CSharp):
    1. ((CCheckBox*)GetDialogItem(IDC_CHECK_AUTO_TUMBLER))->GetCheckState()
    And then I suppose I could always define a function GetCheckState(string strGameObjName) to shorten the above code.
     
  3. jimroberts

    jimroberts

    Joined:
    Sep 4, 2014
    Posts:
    560
    What you should be doing is storing a reference to the components somewhere in your class.

    P.S. It seems like your classes might not be following the single responsibility principle. I can probably help you write re-usable code if you explain your object hierarchy.
     
    Last edited: Jun 17, 2016
  4. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    I guess it depends on your interpretation of single responsibility.

    Mine currently follows the Visual Studio / MFC model where a dialog box controls all the input elements that it contains and collates the data encoded by them.

    In this case my hierarchy it is relatively simple and again follows the Visual Studio / MFC model.
    h.jpg
    I have an empty game object (as in no visible components) that I call BingoManager and is the parent of and controls the various parts of the bingo game including a 'settings' button that pops up my Settings/Options dialog box (excuse the MFC terminology but it best describes the functionality of the window). You folks no doubt have your own term for such game elements.

    Then I have another empty game object that I call OptionsManager. Again excuse the Windows/MFC terminology but I don't have better names to describe the purpose of these elements. OptionsManager contains my two on/off or true/false check boxes similar to those in windows, a 3 way toggle button similar to a windows check box but with 3 possible states rather than 2 and and some Bingo pattern button that work in the same way as a windows radio button group (one button is selectable at a time)

    When the user hits the 'save' button OptionsManager script gets the state of all the above buttons and send them to BingoManager script to change the way the game operates (bingo tumbler turned on or off, automatic tumbler turned on or off....etc)
     
  5. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    This sort of things seems like a reasonable approach to simplying access to data contained in the scripts of child game object that are acting as user input controls. But I am open to alternative suggestions.

    Code (CSharp):
    1.     protected bool GetToggleChecked(string strGameObjName)
    2.     {
    3.         GameObject gameobj = FindGO(strGameObjName);
    4.         bool bIsChecked = false;
    5.  
    6.         if (gameobj)
    7.         {
    8.             BaseToggleButtonManager script = gameobj.GetComponent<BaseToggleButtonManager>();
    9.             if (script)
    10.                 bIsChecked = script.IsChecked();
    11.             else
    12.                 Debug.Log("McCormickMonoBehaviourBase.GetToggleChecked(string strGameObjName) - no script attached to game object '" + strGameObjName + "'...");
    13.         }
    14.         else
    15.             Debug.Log("McCormickMonoBehaviourBase.GetToggleChecked(string strGameObjName) - game object '" + strGameObjName + "' not found...");
    16.    
    17.         return bIsChecked;
    18.     }
    19.  
     
  6. jimroberts

    jimroberts

    Joined:
    Sep 4, 2014
    Posts:
    560
    It seems like you are overcomplicating things. Are you using the newer unity UI?
     
  7. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    UI? I assume you are referring to the canvas thing.

    I was warned off using the canvas thing but I have not tried it myself as yet.

    Apart from the fact we want to eventually create a completely 3D version of it...at present most of it is sprite based.

    So basically, for this particular app, I pretty much have to build all my own input controls from standard game objects and scripts.

    And I have been trying to build some generic input control base classes so that I don't have to do it all over again for any other apps.

    I have also arranged my control base classes so that you can implement them with either sprites or 3D objects.

    If sprite based then you just swap between different sprites representing the different states of the the control, e.g. pressed, unpressed and disabled

    If 3D object based then you swap between different sets of vectDeltaPos, vectDeltaRot and material that similar represent the different states of the control.
     
    Last edited: Jun 17, 2016
  8. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
    why?
     
  9. jimroberts

    jimroberts

    Joined:
    Sep 4, 2014
    Posts:
    560
    I'm not sure why you were warned off using the Unity canvas GUI to build your controls. I would spend a little bit of time learning how to use it. You're wasting more time re-inventing the wheel. The rest of your implementations could be done significantly faster/simpler as well as being encapsulated completely in their own classes for reusability. The way you're implementing things now seems to completely contradict Unity's component based design scheme.
     
    passerbycmc and Fajlworks like this.
  10. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    I have looked at it briefly but you certainly could not describe it as being rich in user input control options.

    No where near as rich as Visual Studio anyway.

    Re-inventing the wheel...yes......

    But doing so does give us the option of making full 3D input controls and dialog boxes.

    For example we have recently implemented the autotumbler, tumbleron and voice buttons as hex 'wheels', with the options embedded on the sides, and the hex wheels spin in their vertical axes when you touch it.
    Such that the option/side facing you is the one currently selected.

    And they also give us the option of implementing the dialog boxes in a 3D 'fly around' mode when you 'open' them.