I want to check if the player camera is able to see the actor. The methods I’ve tried have either detected the actor through walls or doesn’t account for the up/down angle of the camera. What method can I use to properly check the line of sight between the camera and an actor?
Hey there @TheRealRoboMan0! Other than using line traces, you could use the “line of sight to” node:
However if you want to check if something has been rendered at all, you can check “Was recently rendered” instead. If a character was rendered on screen, it will trigger this.
However at the end of the day you may still want to use a line trace to verify if something is where you want it to be even using one of these mechanisms. Render can have false positives if they are REALLY close to being in a visible state.
Disclaimer: One or more of these links are unaffiliated with Epic Games. Epic Games is not liable for anything that may occur outside of this Unreal Engine domain. Please exercise your best judgment when following links outside of the forums.
Line of Sight:
Rendered:
This isn’t really a perfect solution. Line of sight to just does a line trace from the camera to the objects center and another to it’s top. It’s great for small objects, but for big objects if you have something in the way right between the object and the player it’ll return false, even if it should be true. It’s extremely inaccurate and unreliable, borderline pointless.
As for was actor recently rendered, that is a bit better, because it’ll return true if the player is facing the thing and isn’t too far away from it.
It’s also imperfect however because it fires false if the object origin point (usually center) is out of frame. (Which is very odd because the object is clearly still being rendered…)
Hey there @Cestarian! Depending on your use case, a combination of both and socket checks instead of center can be worth it, but gets more complex. If your use case requires high precision a more custom solution might be in order.
Socket checks?
It’s a bit strange though, the engine clearly does ‘something’ when an object is completely out of frame or completely obscured, the engine can clearly tell when the player is not able to see an object, it’s strange that blueprints can’t check for this ‘something’.
You can for instance see it with planar reflections, they stop eating up your frames when they can’t be seen by the player. You can also see it with niagara systems, they stop the second you’re not looking at their origin, or if an object obstructs your view of it.
Technically that precise “something” is mostly on the GPU for rendering, which means it’s not something easily accessed. The other thing that happens is bounds checks, that is what determines niagara particles rendering like you mentioned, though these aren’t hyper precise and are approximated boxes. Even games like Overwatch 2 have socket checks for things like Cassidy’s ultimate for example, it’s not an entirely uncommon practice.
Disclaimer: One or more of these links are unaffiliated with Epic Games. Epic Games is not liable for anything that may occur outside of this Unreal Engine domain. Please exercise your best judgment when following links outside of the forums.
Bound checks looks like exactly what I need, but how do I actually check if the bounds are within the viewport?
I ended up creating a function to check for line of sight more thoroughly.
The line of sight node sends a line trace from the camera to the center and top of an object, so what I did was use dot product to check if the player is facing the object. (Normally ‘has recently been rendered’ should do the trick for this, but I had a case where it didn’t actually work, hence dot product)
And then I added extra line traces for each edge, and I offset it a little bit (10%) towards the center so that if the object is adjacent to another object (such as a wall) that object won’t be hit by the line trace since we only want objects that are actually obstructing our view to get hit.
It works quite well. It’s better to set the dot product greater than value to 0.4 instead of 0, it’s less forgiving that way (just about as soon as the object is out of frame usually it’ll return false).
I also decided to move it away from event tick and use a 1 second timer instead. When there is visibility, it enables ticking and keeps the 1 second timer, when there is no visibility it sets timer to 0.1 seconds instead and disables ticking so that it can respond quicker when the object is visible again and so resources aren’t wasted in the tick event when it isn’t necessary.
Hello!! The function looks great but where do you put this and how did you add the one second timer? I have an Actor blueprint for a portal effect that looks great but eats up resources even on a top end machine. I want to display it only when the player can see it