Search Unity

Creating colored fog in a 2D game

Discussion in '2D' started by AlexTemina, Sep 8, 2016.

  1. AlexTemina

    AlexTemina

    Joined:
    Feb 19, 2014
    Posts:
    44
    Hi guys,
    some weeks ago we made a post in our blog about how to make fog for a 2D game, using color gradients.
    I think this may be very helpful for a lot of people, so I will share it with you:

    http://blog.moondrop.no/2016/08/creating-colored-fog-in-a-2d-game-with-unity/

    It comes with a unitypackage that has everything needed to practice.

    I hope you enjoy the reading!

    (Hopefully this is not considered spam, I just want to give some help. Otherwise, notice me about it!)
     
    PeaceLaced and JoeStrout like this.
  2. IDreamofIndie

    IDreamofIndie

    Joined:
    Dec 24, 2014
    Posts:
    38
    Hello,
    I stumbled upon your blog post and wanted to give this fog effect a try. I am having a few issues though.
    In Fog.cs lines 23 and 30 the FogData.HasInstance is coming back as not existing. And on line 60 the FogData.HasInstance is coming back as not existing, also I cannot figure out what to replace the &&"s with on line 60.

    Edit: I believe the &&"s are replaced with &&
    Correct?

    Line 77 in_fog_zone also coming back as not existing.

    I am using a different Singleton Class than the one on the Wiki if that matters.

    Any help would be appreciated!
    Thanks

    Edit: I believe I have fixed the FogData.HasInstance by replacing it with FogData.Instance.Activated, not sure though. Still Need to find where line 77 in_fog_zone is coming from.

    Edit 2: After downloading Package File From Blog I seen what was wrong. in_fog_zone bool was not set because it somehow got added into the comment above it.
    after fixing that it is now all working using the other Singletons I was using.

    Code (CSharp):
    1. using UnityEngine;
    2. public class Fog : MonoBehaviour
    3. {
    4.     #region Const
    5.     const string ON_KEYWORD = "_FOG_ON";
    6.     const string OFF_KEYWORD = "_FOG_OFF";
    7.     #endregion
    8.     #region PrivateFields
    9.     //Shader Property Ids. It's always better to use id's than to send strings to the shader.
    10.     private int _01_fog_depth_verticals_prop;
    11.     private int _fog_texture_prop;
    12.     //We use this to update fog if an object changes Z position.
    13.     private float _previous_z;
    14.     private Renderer _rend;
    15.     private Material[] materials;
    16.     private bool previous_activation_state;
    17.     #endregion PrivateFields
    18. #region Unity
    19. #if UNITY_EDITOR
    20.     //We subscribe to OnChange to update Fog if the inspector had changes. This only makes sense in Editor.
    21.     private void OnEnable( )
    22.     {
    23.         if( FogData.HasInstance )
    24.         {
    25.             FogData.Instance.OnChange += _UpdateFog;
    26.         }
    27.     }
    28.     private void OnDisable( )
    29.     {
    30.         if( FogData.HasInstance )
    31.         {
    32.             FogData.Instance.OnChange -= _UpdateFog;
    33.         }
    34.     }
    35. #endif
    36.     private void Awake( )
    37.     {
    38.         _01_fog_depth_verticals_prop = Shader.PropertyToID( "_01FogDepthVerticals" );
    39.         _fog_texture_prop = Shader.PropertyToID( "_FogTexture" );
    40.         _rend = GetComponent<Renderer>( );
    41.         materials = _rend.materials;
    42.         _UpdateFog( );
    43.     }
    44.     private void Update( )
    45.     {
    46.         //If the z changed, update fog
    47.         if( _previous_z != transform.position.z )
    48.         {
    49.             _UpdateFog( );
    50.         }
    51.     }
    52.     private void LateUpdate( )
    53.     {
    54.         _previous_z = transform.position.z;
    55.     }
    56. #endregion Unity
    57. #region LocalMethods
    58.     private bool _IsFogSetAndEnabled( )
    59.     {
    60.         return FogData.HasInstance && FogData.Instance.Activated && FogData.Instance.isActiveAndEnabled;
    61.     }
    62.     private void _UpdateFog( )
    63.     {
    64.         if( !_IsFogSetAndEnabled( ) )
    65.         {
    66.             SwitchEffectInShader( false );
    67.         }
    68.         else
    69.         {
    70.             FogData fog_data = FogData.Instance;
    71.             float object_z = Mathf.Abs( transform.position.z );
    72.             //If object is behind we consider front fog, otherwise we consider back fog
    73.             Vector2 fog_limits = fog_data.fogBack;
    74.             float depth_01 = 1;
    75.             //If we our z position is less than 0, we use fog front.
    76.             if( transform.position.z < 0 ) { fog_limits = fog_data.fogFront; depth_01 *= -1; } //Send properties if object is in fog boundaries. bool in_fog_zone = object_z >= fog_limits.x;
    77.             if( in_fog_zone )
    78.             {
    79.                 Texture2D fog_tex = fog_data.fogRampTexture;
    80.                 Vector2 fog_vertical = fog_data.verticalSplit;
    81.                 //This calculates the absolute coordinates for depth depending on FogBack and FogFront, and Z position of the object.
    82.                 depth_01 *= Mathf.Clamp01( 1f / ( fog_limits.y - fog_limits.x ) * ( object_z - fog_limits.x ) );
    83.                 //Send these properties to the shader, compressed in a Vector3, plus the texture
    84.                 _SetShaderFogProperties( new Vector3( depth_01, fog_vertical.x, fog_vertical.y ), fog_tex );
    85.             }
    86.             else
    87.             {
    88.                 //If we are out the fog zone, deactivate the shader.
    89.                 SwitchEffectInShader( false );
    90.             }
    91.         }
    92.     }
    93.     //This sends the properties to the shader. The Vector with 3 properties of fog boundaries and coordinates, and the texture.
    94.     private void _SetShaderFogProperties( Vector3 fog_depth_verticals_, Texture2D fog_texture_ )
    95.     {
    96.         SwitchEffectInShader( true );
    97.         foreach( Material material in materials )
    98.         {    
    99.             material.SetVector( _01_fog_depth_verticals_prop, fog_depth_verticals_ );
    100.             material.SetTexture( _fog_texture_prop, fog_texture_ );
    101.         }
    102.     }
    103.     //Just activate and deactivate the effect using multi compile, so it's not compiled if it's not necessary.
    104.     public void SwitchEffectInShader( bool activate_ )
    105.     {
    106.         if(activate_ == previous_activation_state)
    107.         {
    108.             return;
    109.         }
    110.         foreach( Material material in materials )
    111.         {
    112.             if( activate_ )
    113.             {
    114.                 material.DisableKeyword( OFF_KEYWORD );
    115.                 material.EnableKeyword( ON_KEYWORD );
    116.             }
    117.             else
    118.             {
    119.                 material.DisableKeyword( ON_KEYWORD );
    120.                 material.EnableKeyword( OFF_KEYWORD );
    121.             }
    122.         }
    123.         previous_activation_state = activate_;
    124.     }
    125. #endregion LocalMethods
    126. }
     
    Last edited: Jan 23, 2017
  3. AlexTemina

    AlexTemina

    Joined:
    Feb 19, 2014
    Posts:
    44
    Hey IDreamofIndie!

    yes, those amps are some mistake in the format of text or whatever. Download the Unity Package which has the files correctly. I'm going to solve those format problems no, thanks to find it out!

    HasInstance is our own method in Singleton, and it's just

    Code (CSharp):
    1. public static bool HasInstance
    2.         {
    3.             get
    4.             {
    5.                 if( instance == null )
    6.                 {
    7.                     instance = (T)FindObjectOfType( typeof( T ) );
    8.                 }
    9.  
    10.                 return instance == null ? false : true;
    11.             }
    12.         }
    You can just use "Instance" (Class Object of Unity can be casted into a bool, returning true if there is instance and false if not), but it would give you an error if there is no instance. Our own Singleton is in the Unity Package I just shared with you. "Instance.Activated" is not the same, since it just tells you if the gameobject is activated or not.

    Ok, I was answering you at the same time I was reading you, and I just read you downloaded the package and everything is correct.

    Ask anything you need, I'll be around ;)
     
  4. gustavim15

    gustavim15

    Joined:
    Jun 21, 2016
    Posts:
    3
    Hello, I tried to use it, but didn't work... Could you help me? It will help me a lot!

    Thank you!
     
  5. laymelek

    laymelek

    Joined:
    Apr 21, 2017
    Posts:
    16
    Hi Alex,

    the Fog is really awesome... I implemented it and it was looking great on the editor.. But I build it for Windows or Android and its not there. Standalone builds doesnt show the fog... Do you know about that or I am missing something here...