How to detect if player looks at something
For a horror game, I want a gameobject to detect when it is looked at, play an audio clip, wait two or three seconds, then destroy itself. How do I do this? I know it would involve Destroy and Time.deltaTime, but how do I detect the looking?
-EDIT- The PLAYER looks at the GAMEOBJECT, and the GAMEOBJECT plays the sound and disappears after two seconds.
Answer by ZaninDevelopper · Nov 26, 2016 at 07:25 AM
Try using Raycasting for detecting if something is being looked at, then play the audio. When you detect a collision, use a Coroutine to detect the amount of time that passed.
Try using the following script (written in C#) for your monster:
PS: The beauty about disabling a script is that only it's self-recurring functions (such as FixedUpdate) are disabled. That means that the 2 seconds countdown will still apply and the GameObject will still be destroyed.
PS 2: After script there are some links that could help you better understanding this code.
public class Monster : MonoBehaviour {
// Whatever is your max distance (remove if not needed). However, it is nice to have a max distance to which your monster can see the player.
float maxDistance = 10;
void FixedUpdate()
{
// Will contain the information of which object the raycast hit
RaycastHit hit;
// if raycast hits, it checks if it hit an object with the tag Player
if(Physics.Raycast(transform.position, transform.forward, out hit, maxDistance) &&
hit.collider.gameObject.CompareTag("Player"))
{
this.enabled = false;
// Starts the countdown to destroy the enemy
StartCoroutine(Deactivate());
}
}
IEnumerator Deactivate()
{
// Plays your audio
gameObject.GetComponent<AudioSource>().Play();
// Waits for two seconds (you don't need to count it up with Time.deltaTime)
yield return new WaitForSeconds(2);
Destroy(gameObject);
}
}
Read on: WaitForSeconds, StartCoroutine
I don't think you understood my question, which is 100% my fault. When the PLAYER looks at the gameobject, the GA$$anonymous$$OBJECT will play a little scary noise and disappear after two seconds.
Oh, I see. That makes it much easier.
All you need is renderer.isVisible, which goes in a script that is in the monster/game object of choice. This way it will be true when the camera can see the object.
PS: This will trigger even when a little bit of the object is within the player's view, so you might want to wait some time before playing the sound to give the player some time to finish turning to the object (such as: player sees object -> object waits 0.5 seconds -> object plays sound). A coroutine can wait multiple times, with multiple "yield return new WaitForSeconds"
private Renderer render;
void Start()
{
render = gameObject.GetComponent<Renderer>();
}
void Update()
{
if (render.isVisible)
{
// Your code goes here
}
}
I still suggest using Coroutines to wait some time before actually doing something and disabling the script, because that way you don't have to worry about working your way around FixedUpdate (or Update) being called many times per second.
Thank you so much! This is something I didn't know about, because I'm a noob, and it will be helpful in the future.
Answer by UDN_077a3309-c352-4d18-bd5c-0ba0c6873aef · Nov 26, 2016 at 04:37 PM
If I understand your question correctly:- You probably want to Dot Product between forward axis of nearby "lookable" entities against the vector between your "audio object" and "lookable" entity.
if the angle between the vectors is between a range then that entity is looking at the audio object.
float angle = Vector3.Dot(Object, Lookable);
if ( angle > -0.1 && angle < 0.1 )
{
// being looked at
}
This is certainly the best approach, thank you!
Now I can get if the player (transform) is looking at the camera:
float cameraAngle = Vector3.Dot(transform.forward, mainCamera.forward);
if(cameraAngle < -0.5f){
playerRig.weight = 0f;
}else{
playerRig.weight = 1f;
}
Answer by Gaming-Dudester · Nov 26, 2016 at 10:10 AM
A bad but working way would be to use a stack of cubes and attach it to you camera. The cubes would have "istrigger" on and would be invisable so when said object enters it would detect it. Raycasting im not too sure but i think it pinpoints in a single point and raycasts (like it said in the unity survival shooter tutorial i think) would lag the game extremely if you sent alot out at once. So if you used raycast (again im not 100% sure) would only check the object in the exact center of the screen and if you sent a bunch out (to check objects at the outer edges of the screen) it would lag. But idk i dont use raycasts much. This is just an idea dont rage bcuz it dumb. Thx for reading.
Not dumb at all, this is a very creative approach. I will definitely consider this.
Answer by recagonlei · Nov 26, 2016 at 04:46 PM
You can do it with Physics.Raycast to make a ray starting from player and put a gameobject with collider in the world with a tag...
void Update()
{
RaycastHit _hit = new RaycastHit();
if(Physics.Raycast(transform.position, transform.forward, out _hit, distance)
{
if(_hit.transform.tag == "Test")
{
//Play the audio
}
}
}
Your answer
Follow this Question
Related Questions
I need help with this script. Can't figure out my it isn't working.,Can't get this script to work 0 Answers
How can I detect if a user is looking at a Gameobject inside a scene from a VR headset 0 Answers
How can I destroy a Gameobject from a list at a specific index 1 Answer
Does the Destroy function make the game object not exist? 1 Answer