Hey, I am pretty new with Unity and I am trying to make a little game. This code is supposed to make a robot look at the player if they are within the sight range. I have written a script that should work(or so I think), but it doesn’t. If you could help me out fixing it I would be grateful. Thanks in advanced!
The code:
using UnityEngine;
using System.Collections;
public class RobotSight : MonoBehaviour {
public float fieldOfViewAngle=110f;
public bool playerInSight;
public Vector3 playerPos;
public float yVar;
private SphereCollider col;
private GameObject player;
void Awake(){
col=GetComponent<SphereCollider>();
player=GameObject.FindGameObjectWithTag(Tags.player);
}
void Update(){
playerPos=new Vector3(player.transform.position.x,yVar,player.transform.position.z);
OnTriggerStay(col);
}
void OnTriggerStay (Collider other)
{
if(other.gameObject == player)
{
playerInSight = false;
Vector3 direction = other.transform.position - transform.position;
float angle = Vector3.Angle(direction, transform.forward);
if(angle < fieldOfViewAngle * 0.5f)
{
RaycastHit hit;
if(Physics.Raycast(transform.position + transform.up, direction.normalized, out hit, col.radius))
{
if(hit.collider.gameObject == player)
{
playerInSight = true;
if (playerInSight){
transform.LookAt(playerPos);
}
}
}
}
}
}
void OnTriggerExit(Collider other){
if(other.gameObject==player){
playerInSight=false;
}
}
}
The biggest problem is a misunderstanding of how to use OnCollisionStay
. You should never be calling OnCollisionStay
, it is only every called when a collider other collides with the collider of the game object the script is attached to. So passing col
to OnCollisionStay
will not work, and it doesn’t even really make much sense. Don’t worry; I was a little confused too the first time I used the OnCollision functions.
I have included a fixed version of your code below, and a sample unity scene (as a .zip) which implements it. hit play and try moving the player capsule around in the scene view to see that it works.
The basic ideas behind your code were ok; you just had too many unnecessary variables and a slight misunderstanding of a function. Try keeping the code a little tighter, and bugs like this will be easier to spot.
using UnityEngine;
using System.Collections;
//make sure the player has a kinematic ridged body attached. Otherwise OnTriggerStay will not be called
//make sure to replace the robot head collider with spear collider with a radius equal to its max view range
public class RobotSight : MonoBehaviour {
public float fieldOfViewAngle=110f;
private Vector3 initialForwardVector;//the way you had it before, the robot's forward vector would always be pointing at the player,
//so that part of the script was basically doing nothing.
//by caching off the initial forward vector, we can achieve what you wanted.
void Awake(){
initialForwardVector=transform.forward;
}
//the robot will only look at the player if the player is inside of its collider
void OnTriggerStay (Collider other){
if(other.gameObject.tag=="Player"){//use tags instead of a reference to the player.
Vector3 direction = other.transform.position - transform.position;
float angle=Vector3.Angle (direction,initialForwardVector);
//the robot will only turn its head a max of fieldOfViewAngle * 0.5f in either direction
if(angle < fieldOfViewAngle * 0.5f){
RaycastHit hit;
//the robot will only look at the player if there is nothing blocking its view
if(Physics.Raycast(new Ray(transform.position, direction),out hit)){//here I use a ray to simplify your raycast
if(hit.collider.gameObject.tag=="Player"){
transform.LookAt(new Vector3(other.transform.position.x,transform.position.y,other.transform.position.z));
//this gets rid of yVar, but still makes it so the robot head only moves left/right not up/down
}
}
}
}
}
}