Search Unity

Fog of war Mesh

Discussion in 'Scripting' started by Scoots, Jan 26, 2010.

  1. Scoots

    Scoots

    Joined:
    Oct 21, 2009
    Posts:
    31
    I have been reading what little posts there are on trying to setup a fog of war similar to the ones commonly seen in RTS games, however im unsure of how to do this exactly.

    So far ive been looking into a method involving 2 meshes, they will be the size of the map, and the theory is that if a players unit is below the mesh, the vertices that are near the unit have their alpha set to 0, so the fog looks like its disapeared

    So far i have tried to raycast from each of the vertexs on the mesh to the floor, and if it collides with a unit, set the vertex invisble, however as there are some 4000 vertices, this causes tiny but noticable freezes in the gameplay.

    How would it be possible to efficently detect if a unit is under this mesh( between the camera and unit)? or is there any other method of creating a fog of war ? would prefer to stay with the mesh method if its feasable however for learning purposes.

    Cheers
     
  2. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    Am I right in thinking you basically need to detect which vertex is nearest to each unit? If so, you might find the data structure script in this thread useful. Basically, it's an efficient method of finding the nearest of a static set of points to another chosen point.

    If I'm on the wrong lines here, perhaps you can give a bit more detail about the game mechanics?
     
  3. Scoots

    Scoots

    Joined:
    Oct 21, 2009
    Posts:
    31
    Hey andeeee, cheers for the reply, ill look into the link you posted come tommorow morning, it looks like it could be usefull elsewhere even if not specificly for the fog of war effect.

    I took 2 screenies of the mesh above a building, ive been trying to raycast down from each of the vertices on the mesh to see if it collides with a building, then set that vertex/triangle to 0 alpha, so the player can see through that section of the fog effect.



    if im not making much sense still, heres the origional post that put me onto the idea:
    http://forum.unity3d.com/viewtopic.php?t=10328&highlight=fog+war
    from AngryAnt's second post, however the second link doesnt exist anymore so i had to improvise a little, may have gone off course.

    Cheers
     
  4. Scoots

    Scoots

    Joined:
    Oct 21, 2009
    Posts:
    31
    ah its ok :) ive found a solution to it now, doenst lag out the game either.
    Instead of raycasting from the mesh to all colliders, im going to attach a script on any unit/base, that raycasts upwards to collide with the mesh, from there the different vertices are set to 0 alpha if they are within a certain radius.

     
  5. Joel-Santos

    Joel-Santos

    Joined:
    Feb 23, 2010
    Posts:
    121
    Can you explain better or post the script that you've used?
     
  6. Joel-Santos

    Joel-Santos

    Joined:
    Feb 23, 2010
    Posts:
    121
    Bump any help?
     
  7. AnomalusUndrdog

    AnomalusUndrdog

    Joined:
    Jul 3, 2009
    Posts:
    1,553
    I'd like to to see the script you made for this as well, Scoots, if its ok.

    How did you determine which vertices of the fog are within the radius?
     
  8. AnomalusUndrdog

    AnomalusUndrdog

    Joined:
    Jul 3, 2009
    Posts:
    1,553
    With Scoots permission, I'm sharing his explanation for getting the fog of war to work:
    Unfortunately, his method of checking through each vertex on the fog of war mesh really lags my program very much as my fog of war mesh has 100x100 vertices.

    I use instead RaycastHit.triangleIndex (http://unity3d.com/support/documentation/ScriptReference/RaycastHit-triangleIndex.html) to get which vertices are affected, which is more efficient. The only problem is this only gets vertices very close to the unit, not the surrounding fog of war vertices.
     

    Attached Files:

  9. Joel-Santos

    Joel-Santos

    Joined:
    Feb 23, 2010
    Posts:
    121
    I'm trying but I can't achieve the same results.. I must be very dumb :(
     
  10. AnomalusUndrdog

    AnomalusUndrdog

    Joined:
    Jul 3, 2009
    Posts:
    1,553
    Ok, I've solved the situation somewhat by making multiple raycasts arranged in a circular fashion, making the revealing of the fog-of-war have a range.

    The only problem is it still lags my game, I get about ~10 fps because of the large amount of raycasts being done in a single update.

    If only you could somehow make the raycasts be called lesser times per game loop ie make the update function be called lesser amount of times.
     

    Attached Files:

  11. AnomalusUndrdog

    AnomalusUndrdog

    Joined:
    Jul 3, 2009
    Posts:
    1,553
  12. Joel-Santos

    Joel-Santos

    Joined:
    Feb 23, 2010
    Posts:
    121
    Thanks man. will check it later. I'm currently doing mine with Texture2D and setpixels, but I'm not very happy with the result.
     
  13. Scoots

    Scoots

    Joined:
    Oct 21, 2009
    Posts:
    31
    Hey, i shoulda checked back on my topic it seems, sorry if i didnt explain much on the reply also anomalous i was just trying to remmber what my code was and ive got horrid memory.

    Ive got 2 scripts for the system, one goes on each unit, annother goes on the 2 fog objects, named Fow50 and Fow100, the 50 one has a 50% alpha material and the 100 a pure black material.
    Thats the code i attatch to the FOW objects, its in java sorry if your working in C#

    Code (csharp):
    1. function Start()
    2. {
    3.     //getting the mesh
    4.     var mesh : Mesh = GetComponent(MeshFilter).mesh;
    5.     var vertices = mesh.vertices;
    6.     var colors = new Color[vertices.length];
    7.    
    8.     //have to filter out whatever game object its attatched too, to make sure the colours have
    9.     //been set correctly before they get altered later, stops invalid array errors where colours  return null
    10.     if(gameObject.name == "Fow50")
    11.     {
    12.         for(i=0;i<vertices.length;i++)
    13.         {
    14.             colors[i] = Color.grey;
    15.             colors[i].a = 1;
    16.         }
    17.         mesh.colors = colors;
    18.     }
    19.     if(gameObject.name == "Fow100")
    20.     {
    21.         for(i=0;i<vertices.length;i++)
    22.         {
    23.             colors[i] = Color.black;
    24.             colors[i].a = 1;
    25.         }
    26.         mesh.colors = colors;      
    27.     }
    28.     //only the 50% fog needs to be refreshed
    29.     if(gameObject.name == "Fow50")
    30.     {
    31.         RefreshFog();
    32.     }
    33. }
    34.  
    35. function RefreshFog()
    36. {
    37.     while(true)
    38.     {
    39.         var mesh : Mesh = GetComponent(MeshFilter).mesh;
    40.         var vertices = mesh.vertices;
    41.         var colors = mesh.colors;
    42.        
    43.         for(i=0;i<colors.length;i++)
    44.         {
    45.             //if the alpha of the mesh isnt 1, add 0.25 alpha on each time
    46.             //this should cause less of a flicker than a full reset to 1 alpha causes
    47.             //giving the fog a gradual regrowth feel
    48.             if(colors[i].a <= 1)
    49.             {
    50.                 //getting the current colours alpha in a var
    51.                 var f : float = colors[i].a;
    52.                 //incrementing the alpha by 1/4
    53.                 f += 0.1;
    54.                 //f shouldnt go above 1, but incase this sets the alpha correctly
    55.                 if(f > 1)
    56.                 {
    57.                     f = 1;
    58.                 }
    59.                 colors[i].a = f;
    60.                
    61.             }
    62.  
    63.         }
    64.         mesh.colors = colors;
    65.        
    66.         yield WaitForSeconds(1);
    67.     }
    68. }
    Ill post back the code for the units, its got alot of code for other functions, just need to split it and see whats for the fog itself, and not for other stuff :)
     
  14. Scoots

    Scoots

    Joined:
    Oct 21, 2009
    Posts:
    31
    Code (csharp):
    1. var radius = 1.0;
    2.  
    3. function Update ()
    4. {
    5.     var layerMask = 1 << 13;
    6.    
    7.     var hits : RaycastHit[];
    8.     hits = Physics.RaycastAll(transform.position, Vector3.up, 500, layerMask);
    9.     for(var i=0;i<hits.length;i++)
    10.     {
    11.         var hit : RaycastHit = hits[i];
    12.         var filter : MeshFilter = hit.collider.GetComponent(MeshFilter);
    13.         var relativePoint;
    14.        
    15.         if(hit.collider.gameObject.name == "Fow50")
    16.         {          
    17.             if(filter)
    18.             {
    19.                 relativePoint = filter.transform.InverseTransformPoint(hit.point);
    20.                 HalfMesh(filter.mesh, relativePoint, radius);
    21.             }
    22.         }
    23.         if(hit.collider.gameObject.name == "Fow100")
    24.         {
    25.             if(filter)
    26.             {
    27.                 relativePoint = filter.transform.InverseTransformPoint(hit.point);
    28.                 FullMesh(filter.mesh, relativePoint, radius);
    29.             }
    30.         }
    31.     }
    32. }
    33.        
    34. function HalfMesh(mesh : Mesh, position : Vector3, inRadius : float)
    35. {
    36.     var vertices = mesh.vertices;
    37.     var normals = mesh.normals;
    38.     var sqrRadius = inRadius * inRadius;
    39.     var colours = mesh.colors;
    40.  
    41.     for(var i=0;i<vertices.length;i++)
    42.     {
    43.         //getting the vertices around the local point passed
    44.         var sqrMagnitude = (vertices[i] - position).sqrMagnitude;
    45.         //if the vertex is too far away, dont carry on
    46.         if (sqrMagnitude > sqrRadius)
    47.             continue;
    48.         colours[i].a = 0;
    49.     }
    50.     mesh.colors = colours;
    51. }
    52. function FullMesh(mesh : Mesh, position : Vector3, inRadius : float)
    53. {
    54.     var vertices = mesh.vertices;
    55.     var normals = mesh.normals;
    56.     var sqrRadius = inRadius * inRadius;
    57.     var colours = mesh.colors;
    58.     for(var i=0;i<vertices.length;i++)
    59.     {
    60.         //getting the vertices around the local point passed
    61.         var sqrMagnitude = (vertices[i] - position).sqrMagnitude;
    62.         //if the vertex is too far away, dont carry on
    63.         if (sqrMagnitude > sqrRadius)
    64.             continue;
    65.         //set the alpha to 0
    66.         colours[i].a = 0;
    67.     }
    68.     mesh.colors = colours;
    69. }
    Thats the code i attatched to each unit, its a more basic version of my own, mines got a few more checks to see whos team the units on etc. it just checks if its hit the 50 or 100% alpha meshes and then turns the alpha on the vertex down to 0 which makes it look like "fog", if you find its not making a large enough fog area, up the radius variable, mines around 10 i think, but it depends on the scale of the unit.

    I didnt seem to get any lag using this system, still got a good ammount of FPS, and this scripts attatched to any unit and building thats created

    Hope this helps
     
  15. AnomalusUndrdog

    AnomalusUndrdog

    Joined:
    Jul 3, 2009
    Posts:
    1,553
    @Scoots: how much FPS do you get with that script?

    I've updated my fog of war project and added a web player release.

    I animated the revealing of fog so the fog disappears smoothly, incidentally, it raised my FPS into ~20 average when revealing fog, since I don't set the fog's vertex colors too many times.

    Making the fog of war mesh smaller in size (from 100x100 to 80x80) also helped the framerate bringing it to an acceptable ~40 FPS

    web player:
    http://anomalousunderdog.herobo.com/Unity/FogOfWarTest.html

    project file:
    http://anomalousunderdog.herobo.com/UnityProjectUploads/
     
  16. Scoots

    Scoots

    Joined:
    Oct 21, 2009
    Posts:
    31
    Hey, that looks good, i get around 40-60 fps on average, but im prety sure the fog isnt causing a noticable FPS loss even with loads of units on the feild in real time.

    my games gone beyond the point that i can get it hosted on a webplayer else id upload an example of the fog itself in action.
     
  17. Bezzy

    Bezzy

    Joined:
    Apr 1, 2009
    Posts:
    75
    If you know how big your plane mesh is, and which order the vertices are, and know how big your world space is, you can probably do a really quick calculation to find the best index. Ray casts can be kind of expensive, so that's how I'd improve efficiency.

    1. Find your search point relative to your mesh object ( something like plane.transform.InverseTransformPoint(defogger.transform.position) )
    2. Get rid of the Y component for now!
    3. Find the min (x,z) of the plane using its renderer.bounds.mins
    4. Take that away from the search point.
    5. Divide the search point by the x an z of the renderer.bounds.size. Now your search point's X and Y are between 0..1
    6. Find the number of rows and columns used to construct the plane's mesh (should be Mathf.Sqrt( GetComponent<MeshFilter>().mesh.GetTriangles(0).Length / 6) or something). You divide by 6 because it takes 6 vertices to define a quad, and that's how they're packed in unity. unless they're not. In which case, I don't even know anymore ;_;. Quad strips?
    7. Imagine you have the neck of a giraffe.
    8. the closest index is something like (int)(searchpoint.z * rowLength * rowLength) + (int)(searchpoint.x + rowlength)
     
    Last edited: Nov 2, 2011
  18. TurboHermit

    TurboHermit

    Joined:
    Dec 20, 2011
    Posts:
    40
    @anomalous_underdog I'm loving the web player version... Which is the one I'd like a package from. Your latest version doesn't seem to be working like that one. The player doesn't move with the cursors, but the camera does. Also it doesn't reveal the FoW real-time. Is there any chance you could upload your old version too? =D
     
  19. Dang-Suc

    Dang-Suc

    Joined:
    Jul 24, 2012
    Posts:
    11
    Thank you, AnomalusUndrdog.
    I am trying to make a fog of war and your script is so great.
     
  20. nostyleguy

    nostyleguy

    Joined:
    Jul 27, 2012
    Posts:
    16
    @Danzou I downloaded AnomalusUndrdog's package too, and the reason I wasn't getting player movement is because there are no input axises named "Horizontal2" and "Vertical2". Once you set those up with file->project settings->input, you can move the player.

    @AnomalusUndrdog I was able to incorporate your Fog of war scripts into my game, but I'm a little confused on how you managed to get your fog of war mesh to follow the terrain in your test scene. I see in the code that you manually generate the mesh as a grid based on the public parameters (grid size, x count and y count) given to the Fog-of-war script, so it seems the FOW mesh should just be a 2d grid, and this is what happens when I implement it in my scene. However in your scene, the FOW mesh mimics the terrain mesh. How is this accomplished?
     
  21. MetaMythril

    MetaMythril

    Joined:
    May 5, 2010
    Posts:
    150
    Wouldn't something like this more efficiently handled with a mask via a shader? I don't know much about shaders, but I believe something like that should be possible.
     
  22. uurain

    uurain

    Joined:
    Oct 23, 2012
    Posts:
    3
    hi , can you send your "Fog of war Mesh" demo give me tks
    my email is 79584719@qq.com
     
  23. deleo

    deleo

    Joined:
    Oct 4, 2013
    Posts:
    4
    I found this very useful and I have been managing to create a FoW. However, I can't make the colors transparent. If I set the alpha to 0, the color just becomes black and when I use a transparent/diffuse shader, the length of mesh.colors is always 0. Any ideas?


    OK, anyone struggling with the same thing: use a particle shader, not a transparent shader.
     
    Last edited: Oct 13, 2013
  24. Piesk

    Piesk

    Joined:
    Sep 23, 2013
    Posts:
    14
    Hey guys i'm doing the same process atm, trying to get FoW working in my game. Coming across the obvious problem that raycast wont hit the underside of a plane, are you using a plane as your fog mesh? i've seen suggestions that using inversetransformpoint with raycastall can work for planes but it still returns no hit for me.
     
  25. Piesk

    Piesk

    Joined:
    Sep 23, 2013
    Posts:
    14
    You need to find a vertex alpha shader mate, can't remember what exactly it's called but search for vertex alpha shader and you probably find one.
     
  26. RickyTicky

    RickyTicky

    Joined:
    Oct 17, 2014
    Posts:
    2
    @AnomalusUndrdog. Great FOW package!
    However I'm having trouble implementing the package into my scene: the mesh which the FOG Of War script creates doesn't mimic my terrain. Any hints on how to get this going? Thanks in advance!
     
  27. AnomalusUndrdog

    AnomalusUndrdog

    Joined:
    Jul 3, 2009
    Posts:
    1,553
    @RickyTicky You know, I made that about 4 years ago so I can't remember. I think I recall the fog of war is created by doing a lot of raycasts down to the ground so it knows how high the ground is at that spot. I'm guessing there's a parameter there to set from which height to start the raycast. You probably need to make it higher, if your terrain is very high.

    However, I think it's better to use fholm's fog of war package (he made it free): https://github.com/fholm/unityassets

    Forum thread: http://forum.unity3d.com/threads/op...lable-under-the-mit-license-on-github.236955/
     
  28. RickyTicky

    RickyTicky

    Joined:
    Oct 17, 2014
    Posts:
    2