Block line of sight if there's an object between guard and player?

As the title says, I’m trying to make the guard behavior a bit richer. The solution in the video works for outdoors and open spaces, but if the scene is in, say, a dungeon, I found that guards can catch you and come after you even if you are walking in the corridor outside their room, for example. Rather frustrating gameplay when enemies you have not even seen yet attack you, and it also limits level design options.
My solution was to add a collider to every relevant object in the scene, then raycast from guard to player and see if it hits anything before reaching the player.
It sounds rather expensive and I’m worried what would happen if you have an actual game scene with dozens of enemies, NPCs and the likes rather than this triny sandbox.

Is there a better way to achieve this?

Also, bonus question: speaking of stuff being expensive, I found that one of my main problems is actually understanding how bad something is in terms of performance, and that’s a serious limit when it comes to my own experiments and projects. I’m always scared that anything I add, whether it is level geometry, terrain size, props/decorations, behavior scripts, whatever, is going to bog down the whole thing and slow it to a crawl. Is there any good rule of thumb to learn? Or good resources to learn from? Thanks!

EDITS: fixed spelling mistakes, because proofriding before hitting send is too smart for me :stuck_out_tongue:

This sounds fine, but you may want to only do this if the player is within a certain range of the enemy. The enemy could check the distance to the player and only start raycasting when the player is within range. Or better even; Have a trigger collider around the enemy and start raycasting when the player is in that collider and stop again when they exit. The physics engine is optimised for these kinds of things and will do likely better on performance than you would

My experience; Don’t worry too much about it. These things can handle a lot more than we think. If you know you are going to have 10,000 bullets on the screen at one given moment, you’d worry about it a little and consider that when you do the bullets but in most of our cases you can get away with being a little sloppy. Also, if you think you did something that may require optimisation, check the ‘stats’ in the game window. It shows the fps and if you can see it drop below 60 (my own benchmark) when that something happens, it needs some optimisation.
I have, over time, learned to not do things like GetComponent in the Update method, etc. and I keep an eye on doing things like ‘static math’ in loops. With this I mean on each iteration of the loop do the same math that gives the same result. Like when enemies aggro when the player gets close to the goal. I don’t have to calculate the player’s distance to the goal for each enemy I want to aggro. In that loop, the player will always be the same distance from the goal, so I can calculate it once. Some things also don’t have to happen every single frame. In most cases enemies don’t have to check the distance to the player on every frame. They can do it 10 times per second instead. It will still have the same effect and you could spread the check over multiple frames if you need to, and the actual check lends itself to it. In general, though, you don’t really have to worry too much about it if you aren’t going to build a massive game, and like I said; you can keep an eye on the fps in the game window. Just be aware that having the scene view open at the same time will affect the performance. Don’t do it. I have wasted hours on trying to find why I’m getting 12fps, only to learn that it’s 112 when the scene view is not visible (These numbers were made up on the spot and may not be a true reflection of the difference)

2 Likes

This sounds fine, but you may want to only do this if the player is within a certain range of the enemy.

Oh, sure! I forgot to specify that: my AiController class is almost entirely the same as the course’s, except that I added this extra bit to it. The unmodified class already checks for the distance before activating any behavior. I added the raycast after said check.

The problem I can see with using colliders for line of sight is that in the course we already use the colliders to handle mouse interactions. As far as I know you can’t have multiple colliders of the same kind on the same gameobject, and anyway all colliders on a given gameobject do the same thing, you can’t have one handling player sighting and another handling hits.

My experience; Don’t worry too much about it. These things can handle a lot more than we think.

Yeah, I need to learn to do that. I already saw in this very course how many behaviors we’ve added to each game element and it barely had any effect on performance on my relatively old computer, yet I can’t help but worry too much about it when i add my own stuff. The straw that broke the camel’s back sort of thing.

This is true, but you can have multiple game objects, each with its own collider and behaviour.

There are tricks to using multiple colliders. One of the biggest tricks is to have colliders on their own GameObject with logic to pass information back to the controllers on the root…

You could, for example, have a child object with a sphere collider with the range of the character’s chase range. You would set the Layer on this collider to EnemyTargeting. Then set the layer on the Player to Player (you’ll need to create these layers).

Then in the Project Settings/Physics, you can set the EnemyTargeting layer to only interact with the Player layer.

Now on the EnemyTargeting GameObject, you’ll add a class

using UnityEngine;

public class Targeter : MonoBehaviour
{
     
     
     public event System.Action<Collider> OnTargetEntered;
     public event System.Action<Collider> OnTargetExited;

     void OnTriggerEnter(Collider other)
     {
          OnTargetEntered?.Invoke(other);
     }
     void OnTriggerExit(Collider other)
     {
          OnTargetExited?.Invoke(other);
     }
}

Now your AiController can subscribe to this Targeter, and whenever the Player steps within range, you’ll get an OnTargetEntered event, and when it leaves, you’ll get OnTargetExited. If you restrict your raytraces to these times, you’ll let the Physics system do the heavy lifting.

1 Like

Would you recommend this approach for the project in the RPG course?

It’s what I’m using in a “from scratch” redux of the course project.

1 Like

Privacy & Terms