Triggering a GUI based on proximity (and also just a click of a button)

I've been working on an educational Unity project for a while now, and I feel like I know quite a bit about design and GUI, but when it comes to coding, I'm up the creek. I would appreciate any help I can get because right now I feel like I have a nicely designed project, but if it doesn't function, there's no point.

Bottom line, I need to be able to approach an object in 3D space, then based on proximity to that object, two GUI buttons appear that then can be clicked to bring up separate GUI content windows with video.

Any suggestions for how I can trigger the GUI based on proximity? And then once that GUI appears (two buttons), they can control the visibility of a GUI window?

Thank you so much for any help you can provide!

Unity has nicely designed built in functionality for triggers. You probably want a sphereCollider, marked as a trigger. See sphere collider docs

Then, assuming you are using a characterController or other rigidbody to move, when that object enters the sphere trigger, a message will be sent calling OnTriggerEnter on all scripts attached to the characterController, and the trigger.

As for controlling the opacity, you can set the color of GUI by calling GUI.color

You can use the Update() function in a script, which is called every frame, to compare the object's distance to the player with an amount you specify.

The easiest way is to just add the script to each object that could trigger the buttons (it is not the most efficient way, but if there are not that many objects running the script it won't matter).

Here's a rough idea. Add this to any of the 'approachable' objects, make sure you Tag your player object "Player", and give it a whirl.

using UnityEngine;
using System;
using System.Collections;

public class Approachable : MonoBehaviour 
{
    public float approachDistance = 5;
    public float buttonDrawOffsetHeight = 1.0f;

    [Serializable]
    public class MovieButton
    {
    	public string buttonText = "Play Movie";
    	public string movieName = "movie.mpg";
    }
    public MovieButton[] movieButtons = new MovieButton[1];

    private Transform playerTransform;
    private Transform myTransform;
    private bool drawButtons = false;

    void Start () 
    {
    	// find the player object - just do this once when we start up - assumes you've Tagged your player object "Player"
    	GameObject playerOb = GameObject.FindWithTag( "Player" );
    	if( playerOb != null )
    	{
    		playerTransform = playerOb.transform;
    	}
    	else
    	{
    		Debug.LogWarning("Could not find player object!  Turning off!");
    		this.enabled = false;
    	}

    	myTransform = transform;
    }

    // Update is called once per frame
    void Update () 
    {
    	if( !playerTransform )
    	{
    		this.enabled = false;
    		return;
    	}

    	// can compare squared magnitudes - a bit faster
    	float sqrDist = (playerTransform.position - myTransform.position).sqrMagnitude;
    	// square the distance we compare with

    	drawButtons = ( sqrDist < approachDistance*approachDistance );
    }

    void OnGUI()
    {
    	if( !drawButtons )
    		return;

    	// only draw if we're on screen
    	Vector3 buttonPos = myTransform.position + new Vector3(0, buttonDrawOffsetHeight, 0);  // adjust world Y position 
    	Vector3 screenPos = Camera.main.WorldToScreenPoint(buttonPos);

    	// render only if it's in the screen view port	
    	if (screenPos.x >= 0 && screenPos.x <= Screen.width && screenPos.y >= 0 && screenPos.y <= Screen.height && screenPos.z >= 0 ) 
    	{
    		Vector2 pos = GUIUtility.ScreenToGUIPoint(new Vector2(screenPos.x, Screen.height - screenPos.y));

    		GUILayout.BeginArea( new Rect(pos.x, pos.y, 100, 300) );
    		GUILayout.BeginVertical();
    		foreach( MovieButton mb in movieButtons )
    		{
    			if( GUILayout.Button( mb.buttonText ) )
    			{
    				Debug.Log("Play this movie: " + mb.movieName);
    			}
    		}
    		GUILayout.FlexibleSpace();
    		GUILayout.EndVertical();
    		GUILayout.EndArea();
    	}
    }

}

I'm rather new to scripting, so it might not be optimized or clean, but it should give you an idea of what you could do. It works for me. Attach the script to your first person controller and drag a target GameObject on it in your editor.

//attach this script to your first person controller

var targetObj : GameObject;//drag your target into this slot in the editor
var proximity : float = 3;//change trigger proximity here or in editor
private var buttonOn : boolean;
private var windowOn : boolean;
private var windowRect : Rect = Rect (150, 150, 120, 50);//window parameters

function Update() {

    	var dist = Vector3.Distance(targetObj.transform.position, transform.position);

    	//check whether you are within target proximity
    	if (dist < proximity) {
    		buttonOn = true;
    	}
    	else {
    		buttonOn = false;
    	}	
    }

function OnGUI () {

    	if (buttonOn ==true) {

    		if (GUI.Button (Rect (25, 25, 100, 30), "WindowOn")) {
    			windowOn = true;
    		}

    		if (GUI.Button (Rect (25, 100, 100, 30), "WindowOff")) {
    			windowOn = false;
    		}

    		if (windowOn == true) {
    			windowRect = GUI.Window (0, windowRect, WindowFunction, "My Window");
    		}
    	}	
    	//take this "else-statement out if you want the activation of the window to be remembered, even if you leave the proximity of the object
    	else {
    		windowOn = false;
    	}

    }

function WindowFunction (windowID : int) {
    	// Draw any Controls inside the window here
    }

It seems like triggering the buttons based on Brian's answer seems to work for you. So I modified my script to reflect the trigger functionality. I basically replaced the Update function with OnTriggerEnter and OnTriggerExit functions. Rest stays the same.

//attach this script to your first person controller
//make sure your target has a sphere collider attached which is set to "isTrigger"
//set the radius of the sphere collider to the distance which you want as your proximity-check

private var buttonOn : boolean;
private var windowOn : boolean;
private var windowRect : Rect = Rect (150, 150, 120, 50);//window parameters

function OnTriggerEnter (other : Collider) {
    	buttonOn = true;
    }

function OnTriggerExit (other : Collider) {
    	buttonOn = false;
    }

function OnGUI () {

        if (buttonOn == true) {

                if (GUI.Button (Rect (25, 25, 100, 30), "WindowOn")) {
                        windowOn = true;
                }

                if (GUI.Button (Rect (25, 100, 100, 30), "WindowOff")) {
                        windowOn = false;
                }

                if (windowOn == true) {
                        windowRect = GUI.Window (0, windowRect, WindowFunction, "My Window");
                }
        }       
        //take this "else-statement out if you want the activation of the window to be remembered, even if you leave the proximity of the object
        else {
                windowOn = false;
        }

    }

function WindowFunction (windowID : int) {
        // Draw any Controls inside the window here
    }

var mySkin : GUISkin;

//attach this script to your first person controller

private var buttonOn : boolean;

private var windowOn1 : boolean;

private var windowOn2 : boolean;

private var windowOn3 : boolean;

private var windowRect1 : Rect = Rect (20, 200, 620, 470);

private var windowRect2 : Rect = Rect (340, 217, 595, 415);

private var windowRect3 : Rect = Rect (340, 217, 595, 415);//window parameters

var picture1: Texture2D;

var picture2: Texture2D;

var customButton : GUIStyle;

var customBox : GUIStyle;

var videoTexture1: MovieTexture;

var videoTexture2: Texture2D;

function OnTriggerEnter (other : Collider) {
        buttonOn = true;
    }

function OnTriggerExit (other : Collider) {
        buttonOn = false;
    }

function OnGUI () {
GUI.skin = mySkin;
        if (buttonOn ==true) {

 if (GUI.Button (Rect (360, 25, 100, 30), picture1, customButton)) {
                         windowOn2 = false;
                         windowOn3 = false;
                }

               if (GUI.Button (Rect (342,168,283,30), "THEN")) {
                        windowOn3 = true;
                        windowOn2 = false;
                }

                 if (GUI.Button (Rect (625,168,283,30), "NOW")) {
                        windowOn2 = true;
                        windowOn3 = false;
                }

   if (GUI.Button (Rect (340,20,570,150), picture2, customBox))  

                if (windowOn2 == true) {
                        windowRect2 = GUI.Window (0, windowRect2, WindowFunction, videoTexture1);

                }

             if (windowOn3 == true) {
                        windowRect3 = GUI.Window (0, windowRect3, WindowFunction, videoTexture2);
                } 

        }       
        //take this "else-statement out if you want the activation of the window to be remembered, even if you leave the proximity of the object
        else {

        }

}
function WindowFunction (windowID : int) {
        // Draw any Controls inside the window here

    }

I can't test this solution, because I don't have Pro to use movie textures. Whatever you want to be displayed in teh window belongs in the WindowFunction. Thus, your button controls belong there as well (unless you want them to be drawn besides the window). I'd add the buttons to control the movie texture within the appropriate window function like this (add this excerpt into the code above):

function WindowFunction (windowID : int) {

   if (GUI.Button (Rect (10,20,100,20), "Play"))
      renderer.material.mainTexture.Play ();
   }
   if (GUI.Button (Rect (10,100,100,20), "Stop"))
      renderer.material.mainTexture.Stop ();
   }
}

I had the same problem and the second code work for me, but i need to put a 2d image inside a button that will apear inside the window but i cant

i start setting the var

var icon = Texture2D

then inside the window put the button

if (GUI.Button (Rect (10,50, 500, 447),icon)) {
    print ("you clicked the icon");
}

and in the console i get this message "Assets/Player.js(43,23): BCE0023: No appropriate version of 'UnityEngine.GUI.Button' for the argument list '(UnityEngine.Rect, System.Type)' was found."

could somebody tell me how i can do that

sorry about my inglish but is not my native langage