- Home /
Displaying name of currently focused object.
I've madee a script to highlight an object that the camera is pointing at. The script is attached to all tyhe objects that can be highlighted. But i also want to show their names when looking at them. so i've made a few changes but it's always showing me the names of all the objects the script is attached to, not just the one i'm looking at. Any ideas why?
using UnityEngine;
using System.Collections;
public class Highlight : MonoBehaviour {
GameObject cameraGO;
private Color defaultcolor;
GameObject picktoGO;
private bool lookAt = false;
[SerializeField]
private string objectName = "default";
void Start()
{
cameraGO=GameObject.FindGameObjectWithTag("MainCamera");
picktoGO=GameObject.FindGameObjectWithTag("pickto");
defaultcolor = renderer.material.color;
}
void Update()
{
visibleContainer (10);
}
public void visibleContainer(float range){
Ray ray = new Ray(cameraGO.transform.position, cameraGO.transform.forward);
RaycastHit hit;
if (Physics.Raycast (ray, out hit) && (hit.distance < range) && (hit.transform.tag == "pickup") && picktoGO.GetComponent<PickupObjects>().canpick
== true ) {
lookAt = true;
Debug.DrawLine (ray.origin, ray.origin + (ray.direction * hit.distance), Color.red, 2);
hit.transform.renderer.material.color
= Color.yellow;
} else{
transform.renderer.material.color = defaultcolor;
lookAt = false;
}
}
void OnGUI()
{
if (lookAt)
{
GUI.Label (new Rect(Screen.width/2,Screen.height/2,Screen.width/2,Screen.height/2),objectName);
}
}
}
Why not just create a static variable to store the object currently being viewed, then highlight only the static variable and display the name if it's not null?
Answer by PouletFrit · Jun 07, 2014 at 01:43 PM
If you attached this script directly to the gameobject that can be highlighted there is no need to try to find him with the tag, espacialy if there is more than one object with the tag "pickto" since it might not return the one you want. And the camera you could just got it with Camera.MainCamera, which pretty does the same thing.
And there is no need to serialize your object name, just either get him from the gameobject or declare a public variable that ull set for each of them.
// Public variable can be set in the inspector
public string objectName;
void Start()
{
cameraGO = Camera.main.gameObject;
// There is no real need to keep that variable in memory
picktoGO = this.gameObject;
defaultcolor = renderer.material.color
// The other possibility to get the object name
objectName = this.gameObject.name;
}
But just like rcober said you should use only one script, so you raycast only once per update, since raycasting is pretty performance heavy.
You should attach a script on your main camera and raycast in update function like you are already doing, if it hit something, store the gameobject and his default color, then switch its color to yellow. Then check if the object hit is the same than the one last frame, if it's not revert the gameobject color to his default.
public float range = 10;
// The currently displayed gameObject
private GameObject currentGO;
private Color currentGODefaultColor;
void Update()
{
Ray ray = new Ray(cameraGO.transform.position, cameraGO.transform.forward);
RaycastHit hit;
if (Physics.Raycast (ray, out hit) &&
(hit.distance < range) &&
(hit.transform.tag == "pickup") &&
(hit.gameObject.GetComponent<PickupObjects().canpick
== true)) {
// We did hit something, is it the same object than the last frame?
if (currentGO != hit.gameObject) {
// If the currentGO is not null, than we need to set his color back to default
if (currentGO != null) {
currentGO.renderer.material.color = currentGODefaultColor;
}
currentGO = hit.gameObject;
currentGODefaultColor = currentGO.renderer.material.color;
currentGO.renderer.material.color = Color.yellow;
}
// If didnt hit anything but the last frame, we did hit a gameObject, switch back this gameobject to his default color, we arent looking at him anymore
} else if (currentGO != null) {
currentGO.renderer.material.color = currentGODefaultColor;
// $$anonymous$$ake currentGO null so we only turn him back to his color the first frame we stop looking at him
currentGO = null;
}
}
I can't get the script from PouleFrit to work...could someone publish the complete code? I keep getting errors
Answer by ZorbaTHut · Jul 15, 2017 at 02:27 PM
I didn't like the given solution because I figured a raycast would be pretty slow. As some people have mentioned on other threads, the StandaloneInputModule seems to have the relevant data under CurrentFocusedGameObject; in addition, there's a function GetCurrentFocusedGameObject which gets that data. Easy, right?
Well, unfortunately the function is protected, so we can't call it . . .
. . . unless we're a total jerk about it. Luckily, I'm an expert jerk.
Add this to a static class in your project:
static MethodInfo gcfgo;
public static GameObject GetCurrentFocusedGameObject(this StandaloneInputModule sim)
{
if (gcfgo == null)
gcfgo = typeof(StandaloneInputModule).GetMethod("GetCurrentFocusedGameObject", BindingFlags.NonPublic | BindingFlags.Instance);
return gcfgo.Invoke(sim, null) as GameObject;
}
Now in order to get the info you want, you can just call .GetCurrentFocusedGameObject(), like so:
EventSystem.current.GetComponent<StandaloneInputModule>().GetCurrentFocusedGameObject()
Easy peasy!
This solution may break without warning in future builds, but hey, if I had the ability to plan long-term, I wouldn't be a game developer.
Answer by rcober · Jun 07, 2014 at 01:30 PM
From a performance standpoint, scaling would be better to attach the script to a single object, like the camera or maybe a gamemanager class.
You really only want to cast the ray once per update, not once for each object you want to test.
This will also eliminate extra labels from displaying.
Tried it at first, didn;t work out so well. I don't only highlight the objects i also pick them up and carry them in front of me so it was buggy like that
Your answer
