- Home /
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);
}
still an ongoing issue.... Any help would be appreciated! :D
remark out all your debug lines. I know debug.log slows me down alot! not sure about debug.line
Answer by S_Darkwell · Mar 08, 2015 at 03:57 AM
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!
im not sure what you mean by "if sharks don't need to attack from off screen"
You mean if they hit me from behind or outside of camera view? your character drives a small submarine pod in a 3d fps environment, so getting hit from different angles is needed.
I didn't think about the drawlines causing issue though. I'll take them out and see if that helps some.
How does changing one if statement to an else help with lag though? wouldn't it essentially be doing the same thing?
I'll try them out though.
Thank you for the feedback too! I've been wracking my brain trying to figure out what was causing it to lag.
I've seen zombie games that use raycasting with hundreds of zombies at a time, so I figured it was how my script was being done.
Thank you again! :D
Answer by toddisarockstar · Mar 08, 2015 at 05:14 AM
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!
toddisarockstar, is it really that bad using raycasting? I've seen other games use them with numerous enemies, and there seems to be no issue for them. I'll try your idea out as well though. Thank you for your help. :)
i decided to answer this one cause my last project had the identical problem. i worked on a strategy game with multiple players moving around multiple characters. my first attempt was raycasting to predict turns just like you! my soulution was limiting the raycasting. but after having more than a few dozen character scripts or so running, this soulution starts to fail on a slower machine. just depends on how many fish you anticipate.
anyways, after my research,if i where to do it again, i would have mounted seperate little box colliders that float in front of and to sides of the objects, for separate distance detection.
in my current project i have actually tested over 1500 box coliders in a level and NO lag....YAY.
im kinda new at this gamedevelopment thing too but im learning that getting code to work is only half the battle. proficency in cpu usage really needs to be considered in everything including script. i guess this problem is just one example. (Thats if you ever want to create anything more than super simple games)
Your answer
Follow this Question
Related Questions
Raycast returns null for no apparent reason 0 Answers
How can I find the distance from one object to another using raycasts? 1 Answer
How do I make raycast ignore the players collider 1 Answer
Raycast not hitting instantiated object when timescale is 0 1 Answer
Rigidbody.position causes shaking 1 Answer