Need help with simple JS popup menu

Here is my script:


// loads menu prefab when player enters the trigger

// Instantiates prefab (menu GUIs)

var prefab : Transform;

function OnTriggerEnter (other : Collider) {
Instantiate (prefab);
}

// Destroy prefab when player leaves the trigger

function OnTriggerExit (other : Collider) {
Object.Destroy (prefab);
}


When the player enters the trigger, the popup menu prefab pops up. When the player leaves the trigger, the menu doesn’t destroy and remains on the screen.

What am I doing wrong?

You should assign the return value of Instantiate to a variable, so you can destroy the instance. You’re trying to destroy the actual prefab. Please use code tags when posting code.

–Eric

I changed it to this:

// load menu when player enters the trigger

// Instantiates prefab (menu GUIs)

var prefab : Transform;


function OnTriggerEnter (other : Collider) {
	Instantiate (prefab);
	}

// Destroy menu when player leaves the trigger

function OnTriggerExit (other : Collider) {
    Destroy (gameObject);
}

Still doesn’t work. When I attach a destroy over time using gameObject it works fine:

var lifeTime = 3.0;

function Awake ()
{
	Destroy (gameObject, lifeTime);
}

Is that interfering somehow? Even if it’s a separate script that loads in the prefab.

As I said, you need to assign Instantiate to a variable, so you can destroy the instance. Right now you’re just destroying the GameObject that the script is attached to.

–Eric

So I have to add something like:

var prefabToInstantiate : NameOfMyScript

and then

Destroy (prefabToInstantiate)

??

Sorry, I guess I don’t know how to assign Instantiate to a variable.

Shouldn’t I be able to change this from a lifeTime to a OnTriggerExit?

var lifeTime = 3.0;

function Awake ()

{
    Destroy (gameObject, lifeTime);
}

No, it should be “var prefabInstance : GameObject”. Also the “prefab” variable should be GameObject, not Transform. (Technically it can be Transform, but that makes things slightly more complicated and you’re not actually referencing the Transform component, so there’s no reason for it to be Transform.)

–Eric

So this is now my script:

// load menu when player enters the trigger

// Instantiates prefab (menu GUIs)

var prefab : GameObject;


function OnTriggerEnter (other : Collider) {
	Instantiate (prefab);
	}

// Destroy menu when player leaves the trigger

function OnTriggerExit (other : Collider) {
    Destroy (gameObject);
}

But what do I put after Destroy? Because as it stands now, Destroy removes the object this script is attached to and not the prefab it calls. And if I put the prefab name, it does nothing.

So this script is attached to a game object that needs to stay in the game and it calls a popup menu when the player enters the trigger. I can’t attach an OnTriggerExit to the called prefab object because it doesn’t know it was called by a trigger event. Only that it exists, right?

I kind of hate to repeat this yet again, but you really need to assign Instantiate to a variable, so you can destroy the instance. You do that the same way you assign the return value of any function to a variable; the docs for Instantiate have examples showing exactly this.

–Eric

I know, I’m sorry, Eric. I don’t have a lot of programming experience, as you can see. So I’m digging around trying to figure this out as I go. I’ll research Instantiate. Thank you!

// load menu when player enters the trigger
// Instantiates prefab (menu GUIs)

var popupMenu : GameObject;

function OnTriggerEnter (other : Collider) {
	Instantiate (popupMenu);
	}

// Destroy menu when player leaves the trigger

function OnTriggerExit (other : Collider) {
    Destroy (popupMenu.gameObject);
}

Nope, you’re not assigning the return value of Instantiate to a variable. :wink: Doing so involves using the “=” sign; that’s how you assign results to variables. See code examples #2 and #3 in the docs for Instantiate.

–Eric

That doesn’t seem to help me. There’s a lot about clones in that doc and how to instantiate an object but nothing I can make out on how to access that object once it exists. I can see that they call objects and send them on a vector which I can do. When the doc says clone = Instantiate, that seems to pull nothing from nothing - The Instantiate creates a clone but it IS the clone? It doesn’t seem to rename it to anything useful to the Destroy command.

And the var they use doesn’t reference anything in the clone = line so I don’t know how to incorporate that into my script.

The Instantiate function will return an object (which is the object that you have instantiated). What Eric meant was that you pass over that returned object into the created variable inside the script so you can destroy it later. Because you did not pass over the returned object, you are destroying a null game object. You can pass over the object using the = sign.

More info here: Unity - Scripting API: Object.Instantiate
Especially this part here:
Clones the object original and returns the clone.

What you want is the returned clone.

“Clones the object original and returns the clone”:

var foo = Instantiate(something);

or

foo = Instantiate(something);

if the variable was defined elsewhere. Although the docs are a little misleading/incomplete about what Instantiate returns when it comes to Unityscript. It says it returns Object, but that’s only really true in C#, in which case you’d manually cast Instantiate to the correct type. In Unityscript, the type of the object that Instantiate returns is whatever the type of the prefab that you’re instantiating. So if “something” in the above examples is a GameObject, then Instantiate returns GameObject. If it’s Rigidbody, then Instantiate returns Rigidbody. Etc. In any case the important thing is that the type of the variable to which you’re assigning the result of Instantiate has to match the type of the variable that you’re instantiating.

–Eric

I finally got it to work. Here is the completed script:

// Load menu when player enters the trigger

var popupMenu:GameObject;

function OnTriggerEnter(other:Collider) {
	cloneMenu=Instantiate(popupMenu);
	}

	var cloneMenu:GameObject;
	
// Destroy menu when player leaves the trigger
function OnTriggerExit(other:Collider) {
    Destroy(cloneMenu);
}

Thank you guys! Much appreciated.

Thanks for sharing, I’ve used it in this way:

var popupMenu:GameObject;
var cloneMenu:GameObject;
private var popupClicked = false;
    
function OnMouseDown () {

if (popupClicked == false) {
			popupClicked = true;
				cloneMenu=Instantiate(popupMenu, Vector3(transform.position.x, transform.position.y + 1.25, transform.position.z), transform.rotation);
	} else {
			popupClicked = false;
			Destroy(cloneMenu);
			
	}	
}