raycast is slowing down computer...

Hello Everyone,

I currently have a first person underwater exploration game.
All of my fish and sharks use a type of raycast to detect if they get to close to a wall or not, or in the case of the shark, if they detect the player.
The problem is, the raycasting is SEVERLY lowering my games FPS.

Would anyone be nice enough to take a look at my scripts and help me understand how I can fix it to prevent it from lagging so much? It lags if I even have 5 or 6 sharks. If I look at the profiler it is maxing out my GPU, but reset back to normal once I turn the fish/sharks off.

Thank you for your help!

this is the sharks:

var animalSpeed: float;
var rotSpeed : float = 10;
var moveDir : int = 1;
var provoked : boolean = false;
var attacking : boolean = false;
var turning : boolean = false;
var sharkAnimator : Animator;
var sharkHitDetect :LayerMask;
 var Player : Transform;
 var sharkBite : GameObject;
 var MoveSpeed = 4;
 var MaxDist = 10;
 var loseSight = 120;
 var MinDist = 5;


function Start ()
{
sharkBite.SetActive(false);
sharkAnimator.SetBool("hurt", false);
sharkAnimator.SetBool("attacking", false);
sharkAnimator.SetBool("dying", false);
attacking = true;
}


function FixedUpdate()
{
	
		///////////
		 if (Player == null)
		   	{
		  	Player = null;
		  	provoked = false;
		   	attacking = true;
		   	turning = false;
		   	}
	if (provoked == false)
	{
	this.transform.localEulerAngles.x=0;

	    if(!Physics.Raycast(transform.position, transform.forward, 5))
	    {
	    moveDir = 1;
	        transform.Translate(Vector3.forward * animalSpeed * Time.smoothDeltaTime);
	   }
	   if(Physics.Raycast(transform.position, transform.forward, 5))
	    {
	    moveDir = 10;
	        transform.Translate(Vector3.forward * animalSpeed * Time.smoothDeltaTime);
	   }
	        if(Physics.Raycast(transform.position, (- transform.right), 1))
	        {
	          moveDir = 10;
	        }
	        if(Physics.Raycast(transform.position, transform.right, 1))
	        {
	            moveDir = -10;
	        }    
	        transform.Rotate(Vector3.up, 90 * rotSpeed * Time.smoothDeltaTime * moveDir); 
	  }
   ////////////////////////
   
   var hit : RaycastHit;
		if (Physics.Raycast (transform.position, transform.forward, hit, MaxDist,sharkHitDetect)) {
   
   Debug.DrawLine (transform.position, hit.point, Color.red);
   
   if (hit.collider.tag == "Player" || hit.collider.tag == "ship")
   {
   provoked = true;
   Player = hit.collider.transform;
   }
   }
   
    else if (Physics.Raycast (transform.position, transform.forward, hit, loseSight,sharkHitDetect)) {
   provoked = false;
   Debug.DrawLine (transform.position, hit.point, Color.blue);
   }

   
   if (Player != null)
   {
   if (provoked == true)
   {
     if(Vector3.Distance(transform.position,Player.position) <= MinDist)
     {
       Attacking (); 
        moveDir = 0; 
      
     }
    }
         if(Vector3.Distance(transform.position,Player.position) <= MaxDist)
             {
             MoveSpeed = 5;
             transform.position += transform.forward*MoveSpeed*Time.deltaTime;
    		 } 
    
    if(Vector3.Distance(transform.position,Player.position) >= MaxDist && (Vector3.Distance(transform.position,Player.position) >= MinDist))
     {
		provoked = false;
		sharkAnimator.SetBool("attacking", false);
		Player = null;
   	}	
   

}
}

function Attacking ()
{
// attacking = true; 
////////////
	 if (attacking == true)
		 {
		 sharkBite.SetActive(true);
		 sharkAnimator.SetBool("attacking", true);
		 MoveSpeed = 20;
		  transform.Translate(Vector3.forward * MoveSpeed*Time.deltaTime);

		  yield WaitForSeconds(3);
		  attacking = false;
		  sharkAnimator.SetBool("attacking", false);
		  sharkBite.SetActive(false);
		  turning = true;
		  
		  
		  
		 }
	 if (turning == true && attacking == false)
		 {
		  
		  MoveSpeed = 10;  
		  var targetDir = Player.position - transform.position;
		var step = 2 * Time.deltaTime;

		var newDir = Vector3.RotateTowards(transform.forward, targetDir, step, 2.0);
		 transform.rotation = Quaternion.LookRotation(newDir);
		yield WaitForSeconds(3);
		 attacking = true;
		}
		if (turning == true && attacking == true)
		{
		turning =false;
		attacking = true;
		}
		
		if (attacking == true && provoked == false)
	{
	  sharkAnimator.SetBool("attacking", false);
	}
 }

this is the fish.

var animalSpeed: float;
var rotSpeed : float = 10;
var moveDir : int = 1;

function Start ()
{

}
 
function FixedUpdate()
{
    if(!Physics.Raycast(transform.position, transform.forward, 5))
    {
    moveDir = 1;
        transform.Translate(Vector3.forward * animalSpeed * Time.smoothDeltaTime);
   }
   if(Physics.Raycast(transform.position, transform.forward, 5))
    {
    moveDir = 10;
        transform.Translate(Vector3.forward * animalSpeed * Time.smoothDeltaTime);
   }
   
  

    
        if(Physics.Raycast(transform.position, (- transform.right), 1))
        {
          moveDir = 10;
        }
        if(Physics.Raycast(transform.position, transform.right, 1))
        {
            moveDir = -10;
        }
       

          
        transform.Rotate(Vector3.up, 90 * rotSpeed * Time.smoothDeltaTime * moveDir);   
  		  
  
}

Firstly, I agree with Therian13. I suspect your Debug’s are slowing you down severely.

Secondly, a number of times, are are checking if something is true, and then to see if it’s false. Just check for either true or false (whichever is most likely), then say “else”. For instance, you can replace:

if(!Physics.Raycast(transform.position, transform.forward, 5))
{
   ...
}
if(Physics.Raycast(transform.position, transform.forward, 5))
{
   ...
}

–with:

if(!Physics.Raycast(transform.position, transform.forward, 5))
{
   ...
}
else
{
   ...
}

This saves you a raycast.

Thirdly, I’m not certain whether or not this applies to your game – but if sharks don’t need to attack from off screen, in the fish’s script, you can cache their Renderer during the Start() function, then only only perform raycasts if their renderer is visible.

For example:

var thisRenderer : Renderer;

function Start ()
{
   thisRenderer = GetComponent.<Renderer>();
}

function FixedUpdate()
{
  if ( thisRenderer.isVisible )
  {
      if(!Physics.Raycast(transform.position, transform.forward, 5))
      {
        ...

Hope this helps!

raycasting is one of the known offenders for taking up a lot of cpu usuage. there are a few others you have to watch out for too. Normally it wouldnt be noticable but since you are doing the raycasting every frame on multiple objects its just too much for the raycast function!!!

functions like raycast, overlapshere, getting vector3.distance and some others call request info from outside your javascript and have to wait for the unity game engine to return the info. so its good to to these sort of things as sparingly as possible if your needing proficency. its a good coding habit.

colliders do not slow a game. the freindly unity develpers set these things up this way for detection. I would have recommended setting up a small secondary box collider whatever distance in front of the moving object to sence a secondary collision in front of the object.

anyways if you really want to use raycasting, you could limit the detection to every few frames instead of EVERY frame it will speed up your game and pry show no noticable difference in your game play.
your sharks detecting 10 times a second instead of 30 times a second shouldnt matter to the player, but it would make a big difference to your cpu!

expirament with how often your game really needs the raycast! i like to limit things in your situation with counters like this:

     var animalSpeed: float;
     var rotSpeed : float = 10;
     var moveDir : int = 1;
     var framecount=0;
     

      
     function FixedUpdate()
     {framecount=framecount+1;

     if(framecount>4){
           
           framecount=0;

           if(Physics.Raycast(transform.position, transform.forward, 5))
           {moveDir = 1;}else{moveDir = 10;}
         
           if(Physics.Raycast(transform.position, (- transform.right), 1))
             {moveDir = 10;}
           if(Physics.Raycast(transform.position, transform.right, 1))
             {moveDir = -10;}
      }
            
     
             transform.Translate(Vector3.forward * animalSpeed * Time.smoothDeltaTime); 
             transform.Rotate(Vector3.up, 90 * rotSpeed * Time.smoothDeltaTime * moveDir);   
                 
       
     }

this is just an example. hopefully you can figure out the frame counter concept to add it yourself. i agree its a good idea to remove any type of debug logs whenever you are done with a secton on code but i can assure you that you cant do this much raycasting unless you only plan on maybe one or two lonely fish:(

you may even want to trigger the three different raycasts in different frames so the are no happining all at once. but this should get ya thinking in the right direction and this will speed up your game!