Raycast and GetComponent

I have a script that is attached to a gameobject and that gameobject is a child of my turret. Here is the script attached to the child of the turret that is shooting the ray.

#pragma strict

var turret : Transform;

var range :float = 15;

function Start () 
{
  turret = GetComponent(Transform);
}

function Update()
{
  var hit : RaycastHit;
  
  if(Physics.Raycast (transform.position, transform.forward, hit, range))
    {
      if(hit.transform.tag == "Enemy")
        {
          print ("hitting current target");
          turret.GetComponent(turretControl).inSight = true;
          
        }
      else if(hit == null)
        {
          print("Hitting nothing");
          turret.GetComponent(turretControl).inSight = false;
        }
    }
}

The problem is that the script is not turning on the boolean “inSight” and off when the raycast is, and not hitting a object with a tag “Enemy”. Any help? I know my scripting must be off somewhere.

basically what I am trying to do is, my turret will only fire if the raycast hits a object with a certain tag. By turning on and off a boolean in another script.

Also I am getting an error:

NullReferenceException: Object reference not set to an instance of an object
boxAimCollider.Update () (at Assets/My Assets/Models/Turrets/Scripts/boxAimCollider.js:23)

which is the line:

turret.GetComponent(turretControl).inSight = true;

There will be a lot of turrets in this game and enemies if that helps.

Ok, first of all, it’s much better performance-wise to cache any components that you will be using repeatedly. So instead of calling turret.GetComponent() every frame, cache a reference to that component in your Start() method –

    var turret:Transform;
    var tControl:turretControl;   
    
    function Start() 
    {
        turret = GetComponent(Transform);
        tControl = turret.GetComponent(turretControl);
        if(tControl == null) {
            Debug.LogError("Could not find turretControl component.");
        }
    }

    function Update() {
        tControl.inSight = false; // eg...
    }

Second, as you can see I’ve added in a null check for your turretControl component. You should always perform a null check when using GetComponent before trying to access the components properties. There’s many possibilities when GetComponent can fail to find the component and return null. Which brings me to my third… You’re error message has confirmed what I mentioned, you’re GetComponent call is failing to find the turretControl component. My first guess is that it’s a simple hierarchy mistake. I would guess that your turretControl component is actually on the parent of the gameobject that this script is on? In that case you need to change your turret transform reference to turret = transform.parent.transform, or something similar (depending on your setup).

If you want your turret to hit only a certain target with a certain tag why not just run a check for that tag, and if if it is in range. Or, use a onTriggerEnter, with a sphere collider set to the max range of the turret? I could be wrong, but I don’t think a raycast is needed here.

There are several reasons why your boolean never returns to false.

  • Physics.Raycast returns only true when it hits something. You don’t do anything when it returns false, so the case when you hit nothing.
  • “hit” is a struct and not a reference type, so a check against null will always fail. This is the case when you hit something that isn’t tagged “Enemy”

What you want is probably:

if(Physics.Raycast (transform.position, transform.forward, hit, range))
{
    if(hit.transform.tag == "Enemy")
    {
        print ("hitting current target");
        turretScript.inSight = true;
    }
    else
    {
        print("Hitting something else");
        turretScript.inSight = false;
    }
}
else
{
    print("Hitting nothing");
    turretScript.inSight = false;
}

Note: I took the code sample of jimjames as base since you really should cache the script reference in Start :wink: