4
\$\begingroup\$

I'm trying to implement a visibility representation in a 2D game ( no plains, no quads - plain 2D ) In the examples below I have calculated what the player can see using raytracing and added all the colliding points as vertices to a polygon 2D collider. What is within the polygon is in view.

I want everything outside this visible area to be darker / faded out / fogged out, so that it is not visible / as visible as what is in the view. Prefably I would want to choose what objects are included in this darkening, so that static enviroment is not affected but enemy players are.

Simply deactivating the object's renderers is not an option. I also though about overlaying a texture and using a cutout alpha mask, but that would not translate well considering that the visible polygon is updated every frame and the mask has to be premade(?).

A visualization of what the player (the one in orange) can see

An example of what I am trying to achieve - the non visible area blacked out

\$\endgroup\$
4
  • \$\begingroup\$ You should probably add some description to your images, it is not exactly clear what they display... \$\endgroup\$
    – wondra
    Jan 31 '15 at 15:16
  • \$\begingroup\$ @wondra Sorry, I did when adding the images, but that didn't seem to be saved... \$\endgroup\$
    – Alex
    Jan 31 '15 at 21:00
  • \$\begingroup\$ Have you looked at redblobgames.com/articles/visibility ? \$\endgroup\$
    – jzx
    Feb 6 '15 at 15:22
  • \$\begingroup\$ @jzx Several times. The problem is not how to calculate what's visible or not, it's using the information and displaying it / creating the overlay. \$\endgroup\$
    – Alex
    Feb 6 '15 at 15:47
2
\$\begingroup\$

I also though about overlaying a texture and using a cutout alpha mask, but that would not translate well considering that the visible polygon is updated every frame and the mask has to be premade(?).

I'd consider to dynamically build a mesh with the calculated polygons and draw it before everything else. It works occluding the rest of the scene behind (either fully opaque or semi-transparent depending on you requirements).

This way you can continuously update the mesh geometry depending on how visibility changes.

Of course some CPU work is required to rebuild the mesh on every visibility change, but from the screenshots above the vertices count seems not huge (I'll instead pay attention on using tons of raycast each fram to build it).

\$\endgroup\$
2
  • \$\begingroup\$ How would I go about creating the actual mesh? The points I have are those creating the inside of what's visible. The mesh, of course should only be covering what's outside those bounds. And is there any way I can use the points calculated and use in the collider to create the mesh? \$\endgroup\$
    – Alex
    Feb 1 '15 at 19:32
  • \$\begingroup\$ have a look at mesh api: docs.unity3d.com/ScriptReference/Mesh.html . \$\endgroup\$
    – Heisenbug
    Feb 1 '15 at 20:17
0
\$\begingroup\$

From your question, I understand you need to simulate object occlusion: in real life (as well as in any 3D videogame) you just can't see an object hiding behind another bigger object. I think of an easy way to accomplish this:

  • Use raytracing to detect which areas the player can or can't see from current position (that's what you did in figure 2) to simulate "distance fog";
  • Use simple line collision detection from player object towards any 'actor' (enemy, object, anything you need to hide if not "seen" from the player) to test if player can actually see them or not; if there's no collision along this line (thus there is no solid geometry between player and current actor) then render the actor's graphics, else don't.

This way actors will be rendered only if their origin point lies inside the 'visible' area.

Also, if you want to limit player's sight, you can check both line collision and distance from player to make sure engine doesn't render actors beyond the circumference representing player's 'field of view'.

\$\endgroup\$
4
  • \$\begingroup\$ This works and I've tried it, but there are however some problems with it. It does not create the charactistic look of what's visible and what's not. The enemies consist of several indidual objects rendering graphics and to turn them off I would have to loop, potentially reducing performance when introducing many objects to the scene. An overlay would be preferred. \$\endgroup\$
    – Alex
    Feb 6 '15 at 15:44
  • 1
    \$\begingroup\$ I could suggest you to play a look to This War Of Mine: when the player moves, everything he can't see is blurred, including enemies. You can achieve this by rendering complete scene, considering only the non-visible area of the canvas on the screen and apply blur filter. This way whatever is hidden by solid geometry will be blurred, and if an enemy is half visible he will be half blurred and half inaltered, graphically. \$\endgroup\$
    – liggiorgio
    Feb 6 '15 at 18:36
  • \$\begingroup\$ This is a really nice approach. I find it hard to implement in unity with my current knowledge however. Do you know how one would go about and implement this in unity? \$\endgroup\$
    – Alex
    Feb 8 '15 at 19:30
  • \$\begingroup\$ I guess Unity lets you use different canvas to draw things onto. Let's suppose you have two canvases, named A and B. Render scene, and draw it both on canvas A and B. Then compute the "visible area mask" (as you did in fig. 2) and invert it: you'll get the non-visible areas mask. Draw this mask onto canvas B, then make black areas transparent and blur canvas B (you'll actually blur only non-visible part of level, within the screen boundaries). Finally, draw canvas B on canvas A, render A on the screen, and you shall get the desired effect. Hope this helps. \$\endgroup\$
    – liggiorgio
    Feb 9 '15 at 15:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.