- Home /
How to make an Inspect tool in-game?
Okay, so I'm doing this for school, and it's due by 11/28, so a fast response would be nice. I'm also new to all of this. As in, I know coding basics, but not everything.
So I want to add a script to the Main Camera. It's the generic FPS one that comes with unity. I want to make it so when I use the OnMouseEnter function, It activates a text object in the UI that was deactivated by default. I also want this to work vice versa. The mouse enters the object, the text appears, when it isn't on it, the text is invisible. I'm going to add this on multiple gameObjects, so is there any way I can I can just drag and drop the text elements and objects that makes the OnMouseEnter work?
Thanks!
Funderful
Answer by ThePersister · Nov 17, 2016 at 12:29 PM
Hey @Funderful,
A simple solution would be this, using OnMouseEnter and Exit like you suggested:
Simple Package: https://www.dropbox.com/s/jptfcmrky3wwjpb/InspectableSimple.unitypackage?dl=0
Visually:
https://gyazo.com/9bd1503a77ace25a7d04cfe500e990c6
Code:
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class InspectableSimple : MonoBehaviour {
public RectTransform m_tooltipCanvas;
public Text m_tooltipText;
private Transform m_transform;
private CharacterController m_player;
void Start()
{
m_player = FindObjectOfType<CharacterController>(); // Note that this object is not the player.
m_transform = transform;
m_tooltipText.text = string.Format( "Hi, my name is {0}", this.name );
}
void Update()
{
// Since a canvas' forward is turned away from the camera by default, we'll make the canvas look in the opposite direction.
Vector3 inverseDirection = m_tooltipCanvas.position - m_player.transform.position;
m_tooltipCanvas.rotation = Quaternion.LookRotation( inverseDirection );
}
void OnMouseEnter()
{
_setTooltip( true );
}
void OnMouseExit()
{
_setTooltip( false );
}
private void _setTooltip(bool visible)
{
m_tooltipCanvas.gameObject.SetActive( visible );
}
}
Note however, that this can cause some problems when the inspectable object doesn't have a "Uniform" (1,1,1) scale, because the TooltipCanvas will deform.
Instead you can try the following (Has 2 classes, Inspectable and ToolTipHandler )
Package: https://www.dropbox.com/s/ckjzmf7l3t51jmr/InspectableScaleProof.unitypackage?dl=0
Notice that the tooltip is not deformed for either of the 3 cubes you can look at. (Preview image below)
The code for the scaleproof variant:
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class Inspectable : MonoBehaviour
{
public Transform m_tooltTipShowTransform;
private Transform m_transform;
private CharacterController m_player;
private Transform m_currentTooltip;
void Start()
{
m_player = FindObjectOfType<CharacterController>(); // Note that this object is not the player.
m_transform = transform;
}
void Update()
{
if ( m_currentTooltip != null )
{
// Since a canvas' forward is turned away from the camera by default, we'll make the canvas look in the opposite direction.
Vector3 inverseDirection = m_currentTooltip.position - m_player.transform.position;
m_currentTooltip.rotation = Quaternion.LookRotation( inverseDirection );
}
}
void OnMouseEnter()
{
_setTooltip( true );
}
void OnMouseExit()
{
_setTooltip( false );
}
private void _setTooltip( bool visible )
{
if( visible )
{
m_currentTooltip = ToolTipHandler.Instance.GetTooltip( m_tooltTipShowTransform.position, _getTextToDisplay() ).transform;
}
else if (m_currentTooltip != null)
{
Destroy( m_currentTooltip.gameObject );
}
}
private string _getTextToDisplay()
{
return string.Format( "Hi, my name is {0}", this.name );
}
}
Tooltip Pool-like class:
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class ToolTipHandler : MonoBehaviour {
public static ToolTipHandler Instance;
void Awake() { Instance = this; }
public GameObject m_tooltipPrefab;
public GameObject GetTooltip( Vector3 position, string displayText )
{
GameObject newTooltip = (GameObject) Instantiate( m_tooltipPrefab, position, Quaternion.identity );
newTooltip.GetComponentInChildren<Text>().text = displayText;
return newTooltip;
}
}
To improve this setup:
Instead of using OnMouseEnter and OnMouseExit (if those don't work out for you), use Physics.Raycast
Instead of creating an destroying the tooltip everytime, you could apply the Instance Pool Pattern, to improve performance on larger scales.
I hope this answer helps you out! Best of luck in school and with that deadline, you can do it :) If you need anything else, let me know. Also, if this helped, please accept this answer, it'd be much appreciated!
Cheers,
ThePersister
Thank you so much! You added way more info than I needed, but thats okay. The script works great! I accepted the answer and gave you a point. I'll definitely be able to finish my project now.
:D Funderful
You're welcome! Thanks for accepting as well as the point, good luck with your project! :) And gj on finding out how to place that comment, haha.
Okay, so I got the new version of Unity (5.4.1), and I started seeing problems. As in, the way I was attaching the script to my gameObjects was no longer working and was generating lots of errors. If you can suggest any method of using these scripts on gameObjects, that would be great. In case it matters, I'm using humanoids with animations, along with other irregular objects.
Thanks! Funderful
That really depends on what kind of issues you're encountering. The setup I made was created in Unity 5.4.2 without issues, so I can imagine it's just something you're doing wrong with the setup.
You could simplify the Inspectable class and add a Tooltip class ins$$anonymous$$d.
using UnityEngine;
using System.Collections;
public class ToolTip : $$anonymous$$onoBehaviour {
private Transform m_transform;
void Start()
{
m_transform = transform;
}
void Update()
{
// Since a canvas' forward is turned away from the camera by default, we'll make the canvas look in the opposite direction.
Vector3 inverseDirection = m_transform.position - ToolTipHandler.Instance.m_generalTarget.position;
m_transform.rotation = Quaternion.LookRotation( inverseDirection );
}
}
This allows for simplifying the other code:
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class Inspectable : $$anonymous$$onoBehaviour
{
public Transform m_tooltTipShowTransform;
private GameObject m_currentTooltip;
void On$$anonymous$$ouseEnter()
{
_setTooltip( true );
}
void On$$anonymous$$ouseExit()
{
_setTooltip( false );
}
private void _setTooltip( bool visible )
{
if( visible )
{
m_currentTooltip = ToolTipHandler.Instance.GetTooltip( m_tooltTipShowTransform.position, _getTextToDisplay() );
}
else if (m_currentTooltip != null)
{
Destroy( m_currentTooltip );
}
}
private string _getTextToDisplay()
{
return string.Format( "Hi, my name is {0}", this.name );
}
}
ToolTipHandler:
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class ToolTipHandler : $$anonymous$$onoBehaviour {
public static ToolTipHandler Instance;
void Awake() { Instance = this; }
public Transform m_generalTarget; // Fill with Player Root OR Player's Eyes.
public GameObject m_tooltipPrefab;
public GameObject GetTooltip( Vector3 position, string displayText )
{
GameObject newTooltip = (GameObject) Instantiate( m_tooltipPrefab, position, Quaternion.identity );
newTooltip.GetComponentInChildren<Text>().text = displayText;
return newTooltip;
}
}
Here's the updated package! https://www.dropbox.com/s/4tuawwb02j5lia1/InspectableScaleProof_v2.unitypackage?dl=0
I hope that helps. :)
(Added extra comment because I exceeded the limit) Notice how, ins$$anonymous$$d of trying to find a CharacterController on Start. We just have a public variable in the ToolTipHandler, that every ToolTip looks at. Just fill that with the player (or for better results the player's eyes) to have the ToolTips look at the player again. $$anonymous$$ake sure to add the Tooltip script to the ToolTip Prefab.
Using the previously stated code, you shouldn't have issues in setting up your objects anymore, since we $$anonymous$$imized the odd references.
You might still have issues with On$$anonymous$$ouseEnter and On$$anonymous$$ouseExit, if that's the case, I can write a Physics.Raycast alternative.
Cheers!
Answer by Funderful · Nov 17, 2016 at 02:23 PM
Thank you so much! You really helped out and it works great. I'll definitely be able to finish my project now :D
Also I posted this as an answer because it won't let me post comments:/
Your answer
Follow this Question
Related Questions
Help fading a canvas image - after changing the image from remote script. 1 Answer
C# GUI Button 2 Answers
Text object can't be edited 3 Answers
In-game text editor, native or NGUI 2 Answers
v4.6 Create GUI Elements Via Script? 1 Answer