views:

228

answers:

6

Hello,

The C# scripting environement in Unity3D (runned under Mono) has a nice behavior when detroying objects. All the references that point to the destroyed object gets automaticly null :

    GameObject ref1 = (GameObject)Instantiate(obj);
    GameObject ref2 = ref1;

    if (ref1 != null)
        Debug.Log("ref1 is not null");

    DestroyImmediate(ref1);

    if (ref1 == null)
        Debug.Log("ref1 is null");

    if (ref2 == null)
        Debug.Log("ref2 is null");    

Output :

    ref1 is not null
    ref1 is null
    ref2 is null

Any ideas on how to acheive this ?

Thanks

+1  A: 

You can't do this in C# with call by value parameters. You'll have to use ref parameters which require ref keyword at call site too.

In fact, there's no useful notion of a reachable but destroyed (i.e. deallocated) managed object in .NET (well, ignoring WeakReference which doesn't really count). Either the object is not reachable or it can't be destroyed.

Mehrdad Afshari
and he'd have to pass all variables referencing the object to his Destroy method... yeuch.
x0n
A: 

This is not possible in "regular" .NET, it's just not how the CLR works.

Richard Szalay
Unity is still C#, they run on Mono. Do you think they changed some of the Mono behavior for their purpose ?
noon
I'm quite certain that while unity3d is based on Mono, they modified it significantly. After all, unity3d supported iPhone long before mono-touch.
Richard Szalay
A: 

While an interesting academic challenge, it's not worth pursuing from a technical standpoint. You're looking at this from the wrong angle - the CLR manages the lifetime of objects for you. The only way you could set all "variables" to null is if you passed all of the variables using the "ref" parameter modifier to your destroy method. Unless you plan on writing your whole program inside a single method, you're barking up the wrong tree. Properly structured classes and methods will ensure variables going out of scope get "nulled out," releasing the targeted object for garbage collection.

x0n
I understand your point, but my goal was not to argue wether this is a good design or not. I'm just cursious about how they do it.
noon
ok, i think i misunderstood unity3d - i thought it was a scripting language that looks like c#, but I see now it _is_ c#. I'm as interested as you then :)
x0n
+2  A: 

Maybe the equality operator has been overridden? That'd explain your comment: "Just find out that if ref1 and ref2 were not a GameObject but instead a System.Object, then it wouldn't work."

just-a-random-name
Would it mean they have a "Destroyed" flag set to true when calling DestroyImmediate. Then in the == operator, they would check this flag when comparing to null ?
noon
+1  A: 

It is possible that Unity3D (ab)uses operator overloading + some a kind of internal flag like bool isDeleted; so that when isDeleted is set to true in the DestroyImmediate function then the equality test against null yields true.

arul
I thinks so too.Thanks
noon
By the way, why did you say "yields" and not just "return" ?
noon
He did not mean the `yield` keyword, but it's the correct use of the word :)
Richard Szalay
A: 

You could add an intermediary class (proxy) that holds the reference to the actual class.

All your refs would be to this new GameObjectProxy. This would provide the same API as the GameObject, and just forward any calls on it to the underlying GameObject object.

The GameObjectProxy would also offer extra methods - to destroy the underlying GameObject, and to query if the GameObject is null. (And these could possibly be built into operator= and operator== if you want to be really evil)

Bear in mind that this approach may reduce performance, as every call to the GameObject has to be redirected through the proxy. It is also somewhat evil - it will confuse programmers who expect their references to behave "normally".

Jason Williams