Search Unity

How to Render a True Cone of Sight

Discussion in 'Scripting' started by liquidgraph, Jun 2, 2011.

  1. liquidgraph

    liquidgraph

    Joined:
    Feb 26, 2009
    Posts:
    324


    How would one go about achieving the above effect in Unity? I've thought about this one a bit and have come up short. Projectors don't work because the cone needs to be obstructed by walls and buildings. Raycasting to collect a set of points to create a custom mesh also seems problematic in the case of sloped surfaces, like ramps, hills, and staircases.

    Any ideas? Is there a way to project with occlusion? Is there a way to intersect two volumes and get the resulting shape as an array of points?
     
    Last edited: Jun 2, 2011
  2. Afisicos

    Afisicos

    Joined:
    Nov 13, 2010
    Posts:
    326
    Commandos! my spanish favorite game :p

    I think it have to be ussing raycasting from the character, but maybe is too complex.

    Other way can be use vector3.distance to check the distance of the target, and later check the direction of the target from the character, and compare it with the direction of the walls or buildings from the character.
    It is complex too because you need to check all vertex of the walls that are obstructing. Or you can create collision points between walls and the floor to get the angles that you need to check.
     
  3. jonbonazza

    jonbonazza

    Joined:
    Nov 6, 2010
    Posts:
    453
    He's asking about rendering the cone, not detecting whether or not something is inside of it.

    At any rate, I would just render a triangle and then make sure that the camera layer is on top so that it is always shown on top of everything else.

    EDIT: Actually, that wouldn't work as it wouldn't be offset height-wise.
     
  4. Afisicos

    Afisicos

    Joined:
    Nov 13, 2010
    Posts:
    326
    ah, sorry. I dont understood correctly the question.

    Then i only can imagine ways to make it ussing lights and proyectors, but i don't know if it can works. :S
     
  5. liquidgraph

    liquidgraph

    Joined:
    Feb 26, 2009
    Posts:
    324
    That's the problem, neither of these techniques are really suitable because I need to detect and render on different heights but also occlude the cone based on geometry.
     
  6. bigmisterb

    bigmisterb

    Joined:
    Nov 6, 2010
    Posts:
    4,221
    Projectors.... You create a cone shaped graphic, then use a projector to project it onto the scene. (look at the standard light projector) The graphic is very specific, and you have to turn the wrap mode to clamp, I think.

    Occlusion is built into the projector.

    A couple of things to note: The projector should be Orthographic. the size should be the siteRange and the far clip plane should be about 20.

    Code (csharp):
    1.  
    2. projector.transform.position = transform.forward * siteRange/2 + Vector3.up * 5;
    3. projector.transform.LookAt(transform.forward * siteRange + Vector3.up * 5;);
    4.  
    Feel free to play with the numbers and get what you want.
     
  7. liquidgraph

    liquidgraph

    Joined:
    Feb 26, 2009
    Posts:
    324
    I tried the projector last night, but doesn't it project straight through walls and buildings? What sort of settings will get the projected cone to be obscured by a building or wall?

    What do you mean by "Occlusion is built into the projector"?
     
  8. bigmisterb

    bigmisterb

    Joined:
    Nov 6, 2010
    Posts:
    4,221
    You are correct the projector posts through walls. The effect you are showing on the screen is a projector though. Occlusion is built in as you can set it NOT to appear on certain objects. The designers of that game simply made it where it wasn't an issue.

    There is no material that will not show through objects like that, save a light in unity pro.

    I can't think of a way that would specifically not show through objects. You would probably have to build a geometry light, that was additive. Then you could occlude things yourself as well as build a box where the AI would find things. That seems to be extreme though.

    Looking closely at the picture shows that is exactly what they did.
     
  9. Ntero

    Ntero

    Joined:
    Apr 29, 2010
    Posts:
    1,436
    You could do it in 3 steps

    1) Render Scene normally without light
    2) Render out all Occluding walls into the depth buffer only with a depth value of 1 (so nothing else can be rendered on top of it, it is marked as as close to camera as possible).
    3) Render Projector on applicable faces

    Projector will now show on top of faces it can be shown on, but will be blocked by walls designed to obscure.
     
  10. liquidgraph

    liquidgraph

    Joined:
    Feb 26, 2009
    Posts:
    324
    Sounds like it's worth trying, Ntero, but how to actually implement it. I've never used the depth buffer or non-standard rendering. How does that work?

    Edit: I set up 2 cameras in my scene and did a little test, but I still don't see how a wall will occlude the projector. Yes, I can certainly prevent the projector from affecting the wall, but then it still shines through on the opposite side of the wall. Am I doing it wrong?
     
    Last edited: Jun 2, 2011
  11. Ntero

    Ntero

    Joined:
    Apr 29, 2010
    Posts:
    1,436
    ohh yeah, I definitly blanked on that part, which is probably going to be the largest pain of all.

    btw, for writing directly to the Depth Buffer, you can use:
    http://www.unifycommunity.com/wiki/index.php?title=DepthMask
    Using the offset parameter added in to push it towards the screen:
    http://unity3d.com/support/documentation/Components/SL-CullAndDepth.html

    Now for the fun modification that is not going to be a simple task.
    Instead of rendering the walls that are supposed to block you render geometry made from this sort of algorithm:
    http://forums.tigsource.com/index.php?topic=8803.0
    Take the basic blocking shapes and extrude them down the line of sight, there are also other shadowing systems for convex shapes only, and a quick google search should show 1 or 2, but that would make world building more difficult.

    Outside of Unity, in a lower level environment, this wouldn't be nearly as difficult or costly, you would be able to use a stencil buffer rather than a depth mask to avoid multiple passes. There is probably an easier method but this will give some very well clean results.
     
  12. liquidgraph

    liquidgraph

    Joined:
    Feb 26, 2009
    Posts:
    324
    Yeah, I get the sense that it would be much easier with low-level access to the graphics engine. Is this something that could be done as a C++ plug-in? Or would Unity still not offer enough low-level access there?
     
  13. Ntero

    Ntero

    Joined:
    Apr 29, 2010
    Posts:
    1,436
    Kind of, the problem with rendering in a plugin is that can only really do anything in OpenGL, so windows platforms have to use the -force opengl parameter or else they won't work.

    With that though you have the full gamut of OpenGL operations, and it's just a matter of finding a good time to use the plugin and not mangle the rendering states.
     
  14. Nicolas-Liatti

    Nicolas-Liatti

    Joined:
    Jun 19, 2013
    Posts:
    89
    5 years later, did anybody managed to do this effect?
     
  15. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    Ryiah likes this.
  16. Nicolas-Liatti

    Nicolas-Liatti

    Joined:
    Jun 19, 2013
    Posts:
    89
    I managed to do the effect when everything is on the same level, with a mesh I create at runtime with raycast, but my problem is when the heights are different.

    One solution would be to raycast down, so that the mesh created would follow the heights. A bit like a decal system.

    Any other idea?
     
  17. Nicolas-Liatti

    Nicolas-Liatti

    Joined:
    Jun 19, 2013
    Posts:
    89
    Actually, what do you think about this:
    - create a mesh, in the shape of a triangle
    - make a shader that renders only the intersection with other meshes

    I'm not sure if that's possible to create such a shader though..?
     
  18. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    That's basically what the raycast approach in the gamedev link I posted does. The downside is that it's all CPU based whereas the camera approach is GPU. But you still get the overhead of rendering each camera.
     
  19. Nicolas-Liatti

    Nicolas-Liatti

    Joined:
    Jun 19, 2013
    Posts:
    89
    I'm not sure to understand the approach with a camera per object. Could you please elaborate?
     
  20. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    See the other link I posted. The view of each unit is rendered with a separate camera and then a shader is used to transform that camera's viewpoint onto the game camera's.
     
  21. Nicolas-Liatti

    Nicolas-Liatti

    Joined:
    Jun 19, 2013
    Posts:
    89
    I had another look at Commandos, and it seems that they used different technics depending on the game:
    - Commando 1 & 2: the game is in 3d isometric, based on tiles. So they know the height of each time, and can just render a cone at the right height
    In this case, the cone of sight "stops / is obstructed" when there is an object
    - Commando 3: the cone of vision seems to be just a projector, going through objects
     
  22. deXter_969

    deXter_969

    Joined:
    Nov 17, 2018
    Posts:
    4

    Did you get this working? The raycast approach seems to work but only on flat surfaces. And one can either block or see-through using layer masks. These games, not only create a different texture based on the obstruction height/depth but also identifies the position of the player relative to that cone.