Jump to content

What Is The Preferred Method For Passing Variables Between Two Classes?


Recommended Posts

Hi guys,

I've been tearing my hair out for days on this one. 

I have two scripts. One inherits from the other. I simply want to pass a variable bool between them. I know it must be simple but I've tried every method and example i've found online and i can't get any to work. The closest I've got is with the below code but this only manages to grab the value once. Once the value is changed in Mission list it is never updated in AddMissionWindow and vice versa. This confuses me even more. So do any of you clever people know why the below code doesn't work and what is the actual preferred method?

namespace MissionList
{
    [KSPAddon(KSPAddon.Startup.MainMenu, true)]
    public class MissionList : MonoBehaviourExtended
    {
      public bool drawaddmission = false;
      
      public bool Drawaddmission
      {
      get
      {
          return drawaddmission;
      }
      set
      {
          drawaddmission = value;
      }
      

    }

    [KSPAddon(KSPAddon.Startup.MainMenu, true)]
    public class AddMissionWindow : MissionList
    {
      if (Drawaddmission)
            {
            ///some code and then i want it to change drawaddmission back to false
            Drawadmission = false;
            }
  }

 

Link to comment
Share on other sites

Slight correction to your understanding of inheritance, the extended class is the base class with some more stuff wrapped around it. The functions, variables, and properties of the base class are still a part of the new extended class so "drawadmission" is completely owned by the extending class. There is no passing between two classes because you only have one (it just "inherits" the property and variable)

Some basic notes

  • Since you have a property to get/set drawadmission, it should really be protected or private instead of public (private => no other class can see it, protected => inheriting classes can see it, public => any class can use it. I would be using protected and skipping the property for inherited classes. )
  • The "AddMissionWindow" class above is very incomplete and doesn't help much. From what you've shown it should only be able to run once because there's nothing to set DrawAdmission true again.

tl;dr

I see no reason for the property access to break. I'm more inclined to believe there's a logic error around it thats preventing you resetting it from what you've shown here

Edited by Crzyrndm
Link to comment
Share on other sites

@Crzyrndm Thanks for your Help. I'll elaborate on the code a little more so you can see the logic it's following. I'm opening another window, taking a string input and on a button press closing the window.

namespace MissionList
{
    [KSPAddon(KSPAddon.Startup.MainMenu, true)]
    public class MissionList : MonoBehaviourExtended
    {
      public bool drawaddmission = false;
      
      public bool Drawaddmission
      {
      get
      {
          return drawaddmission;
      }
      set
      {
          drawaddmission = value;
      }

	void OnGUI()
        {
            /// gui code that wraps the button
            if (GUILayout.Button("Add Mission"))
            {
                drawaddmission = true;
            }
        }
      

    }

    [KSPAddon(KSPAddon.Startup.MainMenu, true)]
    public class AddMissionWindow : MissionList
    {
	void OnGUI()
        {
         	if (Drawaddmission)
			{
            ///gui with a string input and wraps a button
			if (GUILayout.Button("Add Mission"))
            	{
               		Drawaddmission = false;
            	}
            }
        }
	}
  }

I can make the AddMissionWindow show when the plugin launches by setting the value to true to start with in MissionList. so that tells me it's at least taking a value from MissionList to begin with. But then when i change the value in AddMissionWindow with the button the window closes but the value is not updated in MissionList. If i start with the value in MissionList false, the AddMissionWindow doesn't show and when i press the button to change the value In MissionList to true the window still doesn't show. I have a log printout on both classes printing the values and i can see them change on button presses but they never copy across to the other class. So when the plug in starts it copies the values, but once it is running it is if it becomes two separate values, one attached to each class that i can change independently.

Link to comment
Share on other sites

I think, what you're looking for is static.  It essentially sets a variable to global.  Like this

public static bool drawaddmission = false;

In AddMissionWindow, you'd change it like this:

MissionList.drawaddmission = true;

That what you're wanting?

Link to comment
Share on other sites

I think Fengist is on the correct path. My understanding now is that you have two seperate instances, one of the base class, and one of the extended class. The extended class inherits the default value of the base class (true) but that is a seperate instance of the "show" variable than the one in missionList.

Static might work, but seems like it could introduce more complication than its worth (3+ windows). I would prefer to have a reference that could be used to say "extended.show = true". However, with all classes being instanced by KSPAddon, it makes that approach more than a little difficult (I prefer to have a root object in a scene that creates and calls functions in other classes for exactly this reason)

Following example being my preferred approach

[KSPAddon(...)]
public class Root : MonoBehaviourExtended
{
  public BaseClass baseInstance;
  public ExtendedClass exInstance;
  
  public void Start()
  {
    baseInstance = new BaseClass();
    baseInstance.Start();
    
    exInstance = new ExtendedClass();
    exInstance.Start();
    
    baseInstance.exList.add(exInstance); // give the base class knowledge of the extended class. I've used a list since it sounds like something I'd use more than one of
  }
  
  public void OnGUI()
  {
    baseInstance.OnGUI();
    exInstance.OnGUI();
  }
}

Another alternative being something very similar where baseclass is the root and creates the instance of the extended class.

In short: Minimise use of KSPAddon where you need objects to know about each other. 

Link to comment
Share on other sites

3 hours ago, Crzyrndm said:

My understanding now is that you have two seperate instances, one of the base class, and one of the extended class. The extended class inherits the default value of the base class (true) but that is a seperate instance of the "show" variable than the one in missionList.

That makes sense and certainly matches my experiences.

I think i'm understanding the code you've supplied but i'm a little unsure which parts of it are aribitrarilly named and which aren't. Would you mind using my own Class names so i can understand it a little better? Also why is .OnGUI used when calling baseInstance and exInstance?

Cheers

Link to comment
Share on other sites

@Crzyrndm Sorry, that might have come across as a little lazy. I've rejigged my code based on how I've understood your example. Am i understanding and implementing this correctly?

namespace CareerManager
{
    [KSPAddon(KSPAddon.Startup.MainMenu, true)]
    public class CareerManager : MonoBehaviourExtended
    {
        public MissionList missionInstance;
        public AddMissionWindow addmissionInstance;
  
        public void Start()
        {
            missionInstance = new MissionList();
            missionInstance.Start();
    
            addmissionInstance = new AddMissionWindow();
            addmissionInstance.Start();
    
        missionInstance.exList.add(addmissionInstance); // give the base class knowledge of the extended class. I've used a list since it sounds like something I'd use more than one of
    }
  
  public void OnGUI()
  {
    missionInstance.OnGUI();
    addmissionInstance.OnGUI();
  }
}
    

namespace MissionList
{
    
    public class MissionList : MonoBehaviourExtended
    {
      public bool drawaddmission = false;
      
      void OnGUI()
        {
            /// gui code that wraps the button
            if (GUILayout.Button("Add Mission"))
            {
                drawaddmission = true;
            }
        }
    }

    public class AddMissionWindow : MissionList
    {
        void OnGUI()
        {
         	if (MissionList.drawaddmission)
			{
            ///gui with a string input and wraps a button
			if (GUILayout.Button("Add Mission"))
            	{
               		MissionList.drawaddmission = false;
            	}
            }
        }
  }

Ok I've got home and tried implementing this and it's not working at all.

Edited by dboi88
Link to comment
Share on other sites

13 hours ago, Fengist said:

I think, what you're looking for is static.  It essentially sets a variable to global.  Like this

public static bool drawaddmission = false;

In AddMissionWindow, you'd change it like this:

MissionList.drawaddmission = true;

That what you're wanting?

That's actually exactly what i was looking for! I've just gone back to my master branch and added this and now it's all working as i had originally planned.

What is the best way to initialize and destroy the addmissionwindow and other temporary classes so i'm only using [KSPAddon(KSPAddon...)] on the main script?

Link to comment
Share on other sites

11 minutes ago, dboi88 said:

That's actually exactly what i was looking for! I've just gone back to my master branch and added this and now it's all working as i had originally planned.

What is the best way to initialize and destroy the addmissionwindow and other temporary classes so i'm only using [KSPAddon(KSPAddon...)] on the main script?

Glad that worked for ya.

I never have to destroy a class in my coding so I can't help ya there.

Link to comment
Share on other sites

You can add instances of classes as components to gameobjects in Unity and destroy them again.
so for example if CareerManager is your KSPAddOn class you can add classes to it's gameobject as components and remove them again.
EG:

where you want to add a class instance:
var child = gameObject.AddComponent<ChildClassName>();

where you want to destroy a class instance:
var child = gameObject.GetComponentInChildren<ChildClassName>();
Destroy(child);
  

Hmm, CareerManager huh? sounds somewhat similar to my and @Papa_Joe's RosterManager mod, Maybe you should consider joining together?

Link to comment
Share on other sites

15 minutes ago, JPLRepo said:

You can add instances of classes as components to gameobjects in Unity and destroy them again.
so for example if CareerManager is your KSPAddOn class you can add classes to it's gameobject as components and remove them again.
EG:


where you want to add a class instance:
var child = gameObject.AddComponent<ChildClassName>();

where you want to destroy a class instance:
var child = gameObject.GetComponentInChildren<ChildClassName>();
Destroy(child);
  

Hmm, CareerManager huh? sounds somewhat similar to my and @Papa_Joe's RosterManager mod, Maybe you should consider joining together?

Cheers, I actually use your Mod, it's great! i hadn't noticed you were the dev. I decided to have a go making my own plugin because i got fed up with using spreadsheets to manage funds, in career mode i always collect contracts to pay for my own bigger missions and i like to be able to see that i'm making a profit on each mission and easily monitor them. I'm going for a much more finance oriented management tool. Maybe once i get some thing that actually functions you could take a look at it? If it's the sort of thing you might want to be involved in i'd be glad to collaborate with someone.

With the learning curve i'm currently going through i really doubt anything i make is going to be suitable for sharing without starting again from scratch at some point! 

Link to comment
Share on other sites

This thread is quite old. Please consider starting a new thread rather than reviving this one.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...