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
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?
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
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.
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?
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.
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.
@joelsantos: I've uploaded a copy of my fog of war unity project so you and anyone can play around with it. here: http://anomalousunderdog.webs.com/UnityProjectUploads/
Thanks man. will check it later. I'm currently doing mine with Texture2D and setpixels, but I'm not very happy with the result.
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): function Start() { //getting the mesh var mesh : Mesh = GetComponent(MeshFilter).mesh; var vertices = mesh.vertices; var colors = new Color[vertices.length]; //have to filter out whatever game object its attatched too, to make sure the colours have //been set correctly before they get altered later, stops invalid array errors where colours return null if(gameObject.name == "Fow50") { for(i=0;i<vertices.length;i++) { colors[i] = Color.grey; colors[i].a = 1; } mesh.colors = colors; } if(gameObject.name == "Fow100") { for(i=0;i<vertices.length;i++) { colors[i] = Color.black; colors[i].a = 1; } mesh.colors = colors; } //only the 50% fog needs to be refreshed if(gameObject.name == "Fow50") { RefreshFog(); } } function RefreshFog() { while(true) { var mesh : Mesh = GetComponent(MeshFilter).mesh; var vertices = mesh.vertices; var colors = mesh.colors; for(i=0;i<colors.length;i++) { //if the alpha of the mesh isnt 1, add 0.25 alpha on each time //this should cause less of a flicker than a full reset to 1 alpha causes //giving the fog a gradual regrowth feel if(colors[i].a <= 1) { //getting the current colours alpha in a var var f : float = colors[i].a; //incrementing the alpha by 1/4 f += 0.1; //f shouldnt go above 1, but incase this sets the alpha correctly if(f > 1) { f = 1; } colors[i].a = f; } } mesh.colors = colors; yield WaitForSeconds(1); } } 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
Code (csharp): var radius = 1.0; function Update () { var layerMask = 1 << 13; var hits : RaycastHit[]; hits = Physics.RaycastAll(transform.position, Vector3.up, 500, layerMask); for(var i=0;i<hits.length;i++) { var hit : RaycastHit = hits[i]; var filter : MeshFilter = hit.collider.GetComponent(MeshFilter); var relativePoint; if(hit.collider.gameObject.name == "Fow50") { if(filter) { relativePoint = filter.transform.InverseTransformPoint(hit.point); HalfMesh(filter.mesh, relativePoint, radius); } } if(hit.collider.gameObject.name == "Fow100") { if(filter) { relativePoint = filter.transform.InverseTransformPoint(hit.point); FullMesh(filter.mesh, relativePoint, radius); } } } } function HalfMesh(mesh : Mesh, position : Vector3, inRadius : float) { var vertices = mesh.vertices; var normals = mesh.normals; var sqrRadius = inRadius * inRadius; var colours = mesh.colors; for(var i=0;i<vertices.length;i++) { //getting the vertices around the local point passed var sqrMagnitude = (vertices[i] - position).sqrMagnitude; //if the vertex is too far away, dont carry on if (sqrMagnitude > sqrRadius) continue; colours[i].a = 0; } mesh.colors = colours; } function FullMesh(mesh : Mesh, position : Vector3, inRadius : float) { var vertices = mesh.vertices; var normals = mesh.normals; var sqrRadius = inRadius * inRadius; var colours = mesh.colors; for(var i=0;i<vertices.length;i++) { //getting the vertices around the local point passed var sqrMagnitude = (vertices[i] - position).sqrMagnitude; //if the vertex is too far away, dont carry on if (sqrMagnitude > sqrRadius) continue; //set the alpha to 0 colours[i].a = 0; } mesh.colors = colours; } 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
@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/
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.
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)
@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
@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?
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.
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.
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.
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.
@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!
@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/