Jump to content

[Answered] Can KSP null out a reference I've made to a Vessel?


Recommended Posts

Summary: if you refer to a kerbalEVA vessel, then board said kerbal onto a craft, KSP appears to null out your reference on you.  How can that be?

k i'm pretty tired, and maybe my eyes are playing tricks....but I swear I just saw this happen in my Monobehavior.  Please forgive the pseudocode, typing from memory.

I have this field: Vessel m_shipRef = null;

in Awake() I have GameEvents.OnVesselSwitch.Add( MySwitchHandler );

in MySwitchHandler(), I have

Debug.Log(" ship was " + m_shipRef == null ? "null" : m_shipRef.ToString() );

m_shipRef = FlightGlobals.ActiveVessel;

Debug.Log(" ship is " + m_shipRef == null ? "null" : m_shipRef.ToString() );

Now the test case - spawn a ship with a kerb in it.  print will be "ship was null, ship is PartName (YourShipName) (Vessel)" - so far so good.

then, eva the kerbal.  print wlil be "ship was PartName (YourShipName) (Vessel), ship is kerbalEVA (Jebediah Kerman) (Vessel)" - again, all ok

then, board the kerbal back onto the ship...the print will be "ship was null, ship is PartName (YourShipName) (Vessel)"!  The "ship was x" section here should refer to jeb, not null.

 

I've racked my brain and for the life of me can't figure out how that happens.  nothing uses / refers to m_shipRef except the handler.  Intuitively, KSP is destroying the 'kerbalEVA' ship when I board him, so I can see KSP cleaning up after itself internally.  but how can KSP go null out my reference to the ship?  I don't expect it in the scene anymore, but I do expect my C# reference to keep kerbalEVA alive until I drop it.

Any ideas anyone?

 

Edited by SixHourDays
Link to comment
Share on other sites

Objects derived from UnityEngine.Object overload Equals and will act like they're null after their unmanaged side has been destroyed. You'll note that m_shipRef isn't actually null -- you can still access, say, m_shipRef.altitude just fine. The moment you try and touch the (destroyed) Unity engine representation through something like m_shipRef.transform/rigidbody etc, you'll see an exception.

[KSPAddon(KSPAddon.Startup.Instantly, true)]
public class NullTestExample : MonoBehaviour
{
    private void Start()
    {
        print("Hello, world! I am " + GetState());
        DestroyImmediate(this);
        print("Now I'm " + GetState());
        print("Let me just move myself now...");
        transform.Translate(Vector3.up);
    }

    private string GetState()
    {
        return this == null ? "UNDEAD!!!" : "fine"; // note nonsensical comparison: surely this can never be NULL?
    }
}
[LOG 00:56:41.430] Hello, world! I am fine
[LOG 00:56:41.431] Now I'm UNDEAD!!!
[LOG 00:56:41.432] Let me just move myself now...
[EXC 00:56:41.434] NullReferenceException
	UnityEngine.Component.get_transform ()
	TestBed.NullTestExample.Start () (at d:/For New Computer/KSPCustomMods/TestBed/TestBed/NullTestExample.cs:18)

Here's a link to the best explanation I could find

Edited by xEvilReeperx
Link
Link to comment
Share on other sites

I'm a dangerous amateur at programming, so I may make mistakes in this... but from the best of my knowledge:

Maybe you're running into one of those places where objects and variables don't behave alike.   

Vessel vessel1 = new vessel();

creates a vessel.

Vessel vessel2 = vessel1;

Points a new REFERENCE at the same vessel in memory essentially.  And vessels in memory are vessels in KSP space...  so, truly copying a vessel would spawn a second vessel right on top of the first one, and when you switched to one they'd collide and explode, I'd think?  You can point a dozen references at a vessel, and when the vessel ceases to exist, they'll all tell you that it's null.

 Without knowing what you want to accomplish exactly... I think the way I'd think about handling this is creating my own class of "VesselInfo."  Something like...  

 

 public class VesselInfo
    {
        public Guid id;
        public String name;
        public double launchtime;

        public VesselInfo(Guid i, string n, double l)
        {
            id = i;
            name = n;
            launchtime = l;  // example of storing other data...  you can store any variable in the Vessel class, but not objects... so you can store vessel1.parts[0].name, but not vessel1.parts[0]   
        }
    }

    [KSPAddon(KSPAddon.Startup.Flight, false)]
    public class KSPTest : MonoBehaviour
    {
        VesselInfo UsedToBe = null;

        void Awake()
        {
            GameEvents.onVesselChange.Add(MySwitchHandler);
        }

        private void MySwitchHandler(Vessel data)
        {
            
            Debug.Log(" ship was " + UsedToBe.name);
            UsedToBe = new VesselInfo(data.id, data.name, data.launchTime);
            Debug.Log(" ship is now " + UsedToBe.name);
        }

       
    }

 

Disclaimer - code compiled...  didn't check to make sure it worked as advertised though, but it should be CLOSE to working.  And someone smarter may come along with a better idea in a minute!  

 

For general reference, to copy an object:

Some C# classes implement an Iclonable interface, so something like this would work:

Vessel vessel2 =(vessel)vessel1.Clone();

Other C# classes have a copy constructor, which would make this work:

Vessel vessel2=new Vessel(vessel1);

But vessel gives you neither of these, for the above stated reasons - you don't actually WANT to copy a vessel.  In this instance you want to hang onto some data about it until you need it again...  which could be after that vessel ceased to exist.

Edited by artwhaley
Link to comment
Share on other sites

7 hours ago, xEvilReeperx said:

Objects derived from UnityEngine.Object overload Equals and will act like they're null after their unmanaged side has been destroyed.

aaaaaaaand the lightbulb goes on (also after a significant sleep).  Thanks for this, and the link - 'impossible' has now been explained into 'nefarious'.

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