Search Unity

  1. Unity 2019.1 is now released.
    Dismiss Notice

2d day/night cycle and weather system à la "Alto's Adventure"

Discussion in 'General Graphics' started by joni-giuro, Jan 6, 2016.

  1. joni-giuro

    joni-giuro

    Joined:
    Nov 21, 2013
    Posts:
    433
    Hi All,
    I'm developing a small 2d game and I started thinking about the day/night cycle and the weather system but couldn't wrap my head around it. Take Alto's Adventure, for example. How do you think they achieved it?
    Can I make a background texture and then change it's tint from normal during the day to reddish for the sunset and then blue/black for the night? Would this be a good approach?
    Thank you!
     
  2. joni-giuro

    joni-giuro

    Joined:
    Nov 21, 2013
    Posts:
    433
    I got something, but it still doesn't look like what I wanted. Especially I don't like that when it goes from red to blue (the sky color) it goes through gray..

    here's how it looks now:


    How I made it:
    I have a day / night cycle controller which has:
    - a Gradient variable that controls the sky's color
    - an animation curve that controls the sun's position
    - an animation curve that controls the moons' position and opacity

    Every frame I increase the time of day and change colors and positions accordingly. This seems to work but I'm not sure it's the best way to go. Any suggestion, comment, or critique?

    PS: Sorry for recording with my mobile, it wasn't supposed to go on youtube, I just needed something on me to show it to a friend and ask feedback.
     
    Last edited: Jan 8, 2016
    KingLlama likes this.
  3. harrynesbitt

    harrynesbitt

    Joined:
    Feb 11, 2013
    Posts:
    14
    Hi, my name's Harry, I'm the artist & developer for Alto's Adventure!

    Looks like you've made pretty good start – similar in principle to how I did things:

    Firstly, make sure you're using "lit" shaders, i.e. ones that implement at least the ambient light colour defined under RenderSettings. You can then blend this value over time to tint the whole scene (i.e. white-ish during daytime, orange at sunset, blue at night etc...).

    Other objects like the sky, sun, moon and stars (things that are self-illuminated) use a different shader that ignores the ambient colour and can instead be controlled separately by setting the material or mesh colours.

    The final implementation also blends a bunch of other factors such as fog colour, fog density, sun flare, star brightness etc for different times of day.

    Here's an example of a few of the colour schemes I used:
    Lighting.png
     
  4. joni-giuro

    joni-giuro

    Joined:
    Nov 21, 2013
    Posts:
    433
    Thank you very much, it all makes much more sense now, I didn't know you can make things react to the light in 2d, too. I see the sky is always a gradient between two colors. The only way I found to make the sky a gradient is to create a gray gradient in photoshop, import it as sprite and then change the "color" attribute, how did you do it? Is it a background plane mesh and you generate the gradient at runtime and then apply it as a texture to the material or did you use a sprite too, or something else? I'm sorry for this noobish questions, I'm really new to the 2d world in unity.
    Thank you for your time.
     
  5. harrynesbitt

    harrynesbitt

    Joined:
    Feb 11, 2013
    Posts:
    14
    It's possibly a little misleading to think of Alto's Adventure as a 2D game – development started before the 2D tools were introduced, so I didn't really make much use of them. Aside from the character sprites, most of the game is constructed from 3D geometry (mountains, trees, terrain, rocks etc).

    The sky is simply a rectangle mesh comprising of 6 vertices. I set the gradient by changing the vertex colour on each pair of horizontal vertices (see attached). Doing it this way allowed me to reuse the same material shared by other objects in the scene, keeping draw calls to a minimum. Otherwise you might have a better time writing a shader that applies the gradient based on height.

    Screen Shot 2016-01-08 at 15.02.49.png
     
  6. joni-giuro

    joni-giuro

    Joined:
    Nov 21, 2013
    Posts:
    433
    Thank you SO much for your time and for not jealously keep your techniques for yourself.
    I love your game and still play it every now and then, it's truly a masterpiece, I hope I will get there some day.
    I'll try this in the weekend, can't wait to go home and start working on it.

    Cheers!
    Jonas
     
  7. kozle

    kozle

    Joined:
    Aug 6, 2015
    Posts:
    46
    Hey...

    I have a question for you Harry, if you dont mind...
    could you share one more secret with us? :)
    How are sun and the moon made? How do they emit light and produce flare effect?
    I've made something simillar with flare shader and flare texture. But it doesnt emmit light on its surrondings.
    Hope you can share this with us...

    Oh... and congrats on Alto's adventure. Game rocks :)
     
  8. harrynesbitt

    harrynesbitt

    Joined:
    Feb 11, 2013
    Posts:
    14
    They don't really "emit" light in the traditional sense, but I am layering up a few tricks to hopefully give that illusion. As you mention, the flare is a key part of it. I've tried to break things down with the following gif:

    Layers.gif

    Hopefully this is pretty self explanatory, though I will mention a few things:

    1. The "sun glow" is a radial gradient placed behind the sun and landscape. It's used to subtly pick out the mountain silhouette during the day and create that warm glow on the horizon just before and after sunset. It's made from a circular, vertex coloured mesh (alpha = 0 around the outside edge). I found this to be a nice cheap, textureless way of creating a large radial gradient without any nasty compression artefacts :p

    Glow Mesh.png

    2. The "sun flare" is a large textured plane, centred over the sun and tinted with vertex colours. The shader uses additive blending as part of the "overlay" render queue so it's always rendered on top of all other geometry. It also optionally blends in a "rainbow" texture during periods of light rain.

    Flare Mesh.png
    Flare.png Rainbow.png

    3. Some of the 3D objects in the scene (mainly buildings) use a toon style ramp shader that reacts to a global directional light, helping to add a little more depth.

    4. Finally, shadows are added to key objects in the scene by "projecting" their vertices down onto the terrain surface and masking them against the terrain using the stencil buffer. This was probably one of the more challenging aspect, so I'll save it for another time!

    Anyway, hope this helps!

    Harry
     
    joshcamas, lewispeel, felixpk and 2 others like this.
  9. joni-giuro

    joni-giuro

    Joined:
    Nov 21, 2013
    Posts:
    433
    Woah! I see you used a lot of actual geometry (I recall you mentioned the 2d toolset was not yet available in unity when you started). Do you think this is still the best way to go, now that the 2d stuff is in unity? Currently I'm using sprites with the default sprite diffuse shader and I find it works ok. What do you think?
    Thanks
     
  10. kozle

    kozle

    Joined:
    Aug 6, 2015
    Posts:
    46
    Wow!
    Thank you Harry for your extensive explanation.
    Joni... I'm currently working on 2D game, and I almost don't use sprites - only 3d meshes. On those 3D meshes I use 2D physics.
     
  11. joni-giuro

    joni-giuro

    Joined:
    Nov 21, 2013
    Posts:
    433
    You can still use pysics on spirtes. I'm currently working on a 2D game as well and I'm using sprites with the diffuse sprite shader and it works quite well, I just want to be sure I won't encounter a huge problem later down the development road. Why are you using 3d meshes? Did you follow a tutorial or are there any other reasons?
     
  12. kozle

    kozle

    Joined:
    Aug 6, 2015
    Posts:
    46
    I'm using 3d meshes because they support deformations. You cant (to my knowledge) deform sprites. I'm also using puppet2d where sprites are easily converted to 3D mesh-es.
     
  13. harrynesbitt

    harrynesbitt

    Joined:
    Feb 11, 2013
    Posts:
    14
    I wouldn't say it's always the best approach – every game is different – but it certainly made the most sense with Alto's Adventure considering I was going for a kind of bold, geometric art style anyway :) Using geometry vs sprites allowed me to keep things like texture memory and overdraw to a minimum, with the added benefit of being able to scale to any resolution! Saves a lot of work when making a mobile game for a bunch of different screen sizes :)
     
  14. RemDust

    RemDust

    Joined:
    Aug 28, 2015
    Posts:
    263
    Harry, I'm so impressed with you unselfishness, congrat's dude, i didn't know about Alto's Adventure (i'm kinda new to the indie world) and I'm gonna check it out right now !
     
  15. bkeiter

    bkeiter

    Joined:
    Jan 30, 2016
    Posts:
    1
    Harry, if your terrain randomly generated, how does your background synchronize with new terrain that is being generated (if so, what process was used to generate this terrain)?
     
  16. Helimike

    Helimike

    Joined:
    Feb 17, 2016
    Posts:
    1
    Hi. First of all I want to thank you for making the most beautiful "2d" game I ever seen. You inspired me to start learning Unity and I am now trying to reproduce the scenery you have done on your blog. I have managed to code a day and night cycle which I think will do it after some fine tuning. I have no previous experience in game or visual programming and I am struggling with the sun flare and halo shader. Is that one shader that blends both the halo and the flare or 2 you have 2 planes, one for the flare and one for the halo. I am using a addative shading but I struggle to make it render on top. Do you have any tips or suggestions? This is the shader I use and as you can see in the picture it won't render on top.

    Code (CSharp):
    1. Shader "SimpleAdditive" {
    2.     Properties{
    3.         _Color("Main Color", Color) = (1,1,1,1)
    4.         _MainTex("Base (RGB) Trans (A)", 2D) = "white" {}
    5.     _RimPower("Rim Exponent", Range(0.5,25.0)) = 3.0
    6.         _BaseAlpha("Base Alpha", Range(0.0,1.0)) = 1.0
    7.     }
    8.  
    9.  
    10.  
    11.         SubShader{
    12.         Tags{ "Queue" = "Overlay" "IgnoreProjector" = "True" "RenderType" = "Transparent" }
    13.  
    14.         CGPROGRAM
    15. #pragma surface surf Lambert alpha
    16.  
    17.  
    18.         sampler2D _MainTex;
    19.     fixed4 _Color;
    20.     float _RimPower;
    21.     float _BaseAlpha;
    22.  
    23.     struct Input {
    24.         float2 uv_MainTex;
    25.         float3 viewDir;
    26.     };
    27.  
    28.     void surf(Input IN, inout SurfaceOutput o) {
    29.         fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
    30.         half rim = saturate(dot(normalize(IN.viewDir), o.Normal));
    31.         //o.Albedo = c.rgb;        //No albedo, only emission
    32.         o.Emission = c.rgb;
    33.         o.Alpha = pow(rim, _RimPower) * _BaseAlpha * c.a;
    34.     }
    35.     ENDCG
    36.     }
    37.         FallBack "Self-Illumin/Diffuse"
    38. }
    Thanks.

    Mike
     

    Attached Files:

  17. harrynesbitt

    harrynesbitt

    Joined:
    Feb 11, 2013
    Posts:
    14
    Hi Mike, try setting ZTest Always to ensure the flare is always drawn in front of other geometry. I'm also not sure you need such a complicated shader (i.e. rim lighting etc) – I was able to get the desired affect using Unity's ShaderLab syntax:

    Code (CSharp):
    1.  
    2. Shader "ALTO/Additive Overlay Alpha" {
    3.     Properties {
    4.         _MainTex ("Texture 1", 2D) = "white" {}
    5.         _SecondaryTex ("Texture 2", 2D) = "white" {}
    6.         _SecondaryTexScale ("Texture 2 Scale", Color) = (0,0,0,0)
    7.     }
    8.  
    9.     Category {
    10.  
    11.         Tags { "Queue" = "Overlay" }
    12.        
    13.         Blend SrcAlpha One
    14.         Cull Back Lighting Off ZWrite Off Fog { Mode Off }
    15.         ZTest Always
    16.        
    17.         BindChannels {
    18.             Bind "Color", color
    19.             Bind "Vertex", vertex
    20.             Bind "TexCoord", texcoord
    21.         }
    22.        
    23.         SubShader {
    24.             Tags { "LightMode" = "Vertex" }
    25.             Pass {
    26.                 SetTexture [_SecondaryTex] {
    27.                     constantColor [_SecondaryTexScale]
    28.                     combine texture * constant
    29.                 }
    30.                 SetTexture [_MainTex] {
    31.                     combine texture + previous
    32.                 }
    33.                 SetTexture [_MainTex] {
    34.                     combine previous * primary
    35.                 }
    36.             }
    37.         }
    38.     }
    39. }
     
  18. joni-giuro

    joni-giuro

    Joined:
    Nov 21, 2013
    Posts:
    433
    I remember harry saying Alto isn't really 2d as it's using actual 3d geometries. At first I though it's because he used an older version of unity but I've been working on my game for quite some time now and I have gone full 3d as well to avoid the problem of "I can't get it to render this 3d plane in front of that 2d sprite". I think having 3d objects makes everything a bit easier, so you might want consider to do that too.
     
  19. felixpk

    felixpk

    Joined:
    Nov 7, 2013
    Posts:
    17
    Hey, first of all thanks for all the information you are sharing with us.
    Despite all your tips I'm struggeling with the Vertex colored (Sun Glow) shader:
    My Problem is that the alpha=0 part of the Glow ignores all shaders (The sky gradient vertex colored shader) in the background. This means that the alpha=0 part ist masking the sky gradient and instead renders the clear flag of the camera. Do you have any idea why this is happening?

    Felix

    Edit: I uploaded a screenshot to clearify what is happening.

    Code (CSharp):
    1. Shader "Custom/SunGlow" {
    2.     Properties{
    3.         _Glow("Glow", Color) = (0,1,0,1)
    4.     }
    5.  
    6.     SubShader{
    7.         Tags{ "Queue" = "Transparent" }
    8.  
    9.         Blend SrcAlpha One
    10.         Lighting Off
    11.         ZWrite On
    12.         Fog{ Mode Off }
    13.         ZTest Always
    14.  
    15.         Pass{
    16.  
    17.             CGPROGRAM
    18.             #pragma vertex vert
    19.             #pragma fragment frag
    20.             #pragma target es3.0
    21.  
    22.             struct v2f {
    23.                 fixed4 color : COLOR0;
    24.                 float4 pos : SV_POSITION;
    25.             };
    26.  
    27.             fixed4 _Glow;
    28.  
    29.             v2f vert(float4 vertex : POSITION, uint id : SV_VertexID){
    30.                 v2f o;
    31.  
    32.                 o.pos = mul(UNITY_MATRIX_MVP, vertex);
    33.              
    34.                 if (id == 0){
    35.                     o.color = _Glow;
    36.                 }
    37.                 else {
    38.                     o.color = fixed4(_Glow.x, _Glow.y, _Glow.z,0);
    39.                 }
    40.  
    41.                 return o;
    42.             }
    43.  
    44.             fixed4 frag(v2f i) : SV_Target{
    45.                 return i.color;
    46.             }
    47.  
    48.             ENDCG
    49.         }
    50.     }
    51. }
    And here the SkyGradient Shader:

    Code (CSharp):
    1. Shader "Custom/SkyGradient" {
    2.     Properties
    3.     {
    4.         _SkyTop("Sky Top", Color) = (0,0,1,1)
    5.         _SkyMiddle("Sky Middle", Color) = (0,0,0,1)
    6.         _SkyBottom("Sky Bottom", Color) = (0,0,1,1)
    7.     }
    8.  
    9.     SubShader{
    10.         Pass{
    11.             CGPROGRAM
    12.             #pragma vertex vert
    13.             #pragma fragment frag
    14.             #pragma target es3.0
    15.  
    16.             struct v2f {
    17.                 fixed3 color : COLOR0;
    18.                 float4 pos : SV_POSITION;
    19.             };
    20.  
    21.             fixed4 _SkyTop;
    22.             fixed4 _SkyMiddle;
    23.             fixed4 _SkyBottom;
    24.  
    25.             v2f vert(float4 vertex : POSITION, uint id : SV_VertexID){
    26.                 v2f o;
    27.  
    28.                 o.pos = mul(UNITY_MATRIX_MVP, vertex);
    29.                
    30.                 if (id < 2){
    31.                     o.color = _SkyTop;
    32.                 }
    33.                 else if (id < 4) {
    34.                     o.color = _SkyMiddle;
    35.                 }
    36.                 else if (id < 6) {
    37.                     o.color = _SkyBottom;
    38.                 }
    39.  
    40.                 return o;
    41.             }
    42.  
    43.             fixed4 frag(v2f i) : SV_Target{
    44.                 return fixed4(i.color, 1);
    45.             }
    46.  
    47.             ENDCG
    48.         }
    49.     }
    50. }
     

    Attached Files:

    Last edited: Jun 8, 2016
  20. felixpk

    felixpk

    Joined:
    Nov 7, 2013
    Posts:
    17
    I also would love to know how you made the parallax effect to only affect the X-Axis.
    Do you align the Background's y-Position with the Cameras y-Position?
    How far away is your Background?
    Which FogMode do you use? (Linear?)
    How do you access the Vertices to set the Vertex-Colors? (Vertex ID?)
     
  21. Paradisebear

    Paradisebear

    Joined:
    Jun 8, 2016
    Posts:
    1
    This is a simple script for adding meshes to sortinglayers:
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class MeshSortingLayer : MonoBehaviour
    4. {
    5.     [SerializeField]
    6.     string sortingLayer;
    7.     [SerializeField]
    8.     int order;
    9.  
    10.     void Awake(){
    11.         MeshRenderer renderer = GetComponent<MeshRenderer>();
    12.         renderer.sortingLayerName = sortingLayer;
    13.         renderer.sortingOrder = order;
    14.     }
    15. }
     
    joni-giuro likes this.
  22. vfxjex

    vfxjex

    Joined:
    Jun 3, 2013
    Posts:
    73
    @harrynesbitt
    I got a project right now and they wan't it to look how Alto's Adventure looks like. At first I thought it was simple, bit after playing the game for some quite time ive realize things are quite complicated and it was perfectly made. For me it is a mystery! One thing that puzzles me is how did you create the shadow?
     
  23. THEAK472009

    THEAK472009

    Joined:
    Jan 24, 2013
    Posts:
    21
    Yo I saw this cool game last weekend and here is an implementation of the same system.
    I could only do this because of the very detailed explanation by the developer.
    If anyone wants to give it a try, here is the unity package.

    Note: I didn't add the stars logic and some stuff like weather, rainbow blending (should be pretty straightforward)
     

    Attached Files:

  24. joni-giuro

    joni-giuro

    Joined:
    Nov 21, 2013
    Posts:
    433
    Here's the result after a couple of weeks of testing, in case anyone's interested:
     
  25. Zehru

    Zehru

    Joined:
    Jun 19, 2015
    Posts:
    84
  26. simply-kashiff

    simply-kashiff

    Joined:
    Jun 17, 2016
    Posts:
    2
    Thanks for every bit of knowledge this discussion has provided me but i'm facing a problem when i'm creating the mesh with code instead of showing whatever color i've provided it shows the material color. Can you please help me with this?

    Thannk You!
     
  27. simply-kashiff

    simply-kashiff

    Joined:
    Jun 17, 2016
    Posts:
    2
    Hey Harry!
    Can you please tell me did you use a shader to support vertex alpha in "Sun Radial Gradient"? If yes, Can you please share the shader i'm searching for solution as i dont know how to write shaders can you please help me?
     
  28. Alucard-Belmont

    Alucard-Belmont

    Joined:
    Jul 4, 2017
    Posts:
    3

    I am interested. Could you share the source code to learn how you did it please?
     
  29. joni-giuro

    joni-giuro

    Joined:
    Nov 21, 2013
    Posts:
    433
    Sure, but keep in mind that I'm not an experienced programmer, so take this with a grain of salt.

    First the day/night cycle, which is basically a bunch of planes that sit on top of each other. During the night the nightsky becomes visible and during the day the day sky becomes visible.
    The day sky is a vertex-colored plane with 6 vertices and when the time passes I change the color of those vertices to create the sunrise/sunset/day sky.

    I used seasons in this script to change rain/snow cycles, but that's of course not mandatory.

    To position the sun and the moon I created one AnimationCurve each and every Update() I evaluate the position on that curve and set the position of the sun/moon accordingly (it makes more sense if you look at the code).

    Here's what the inspector looks like in my project (it's easier to understand the script if you see the sky colors and the animation curves):

    upload_2018-1-29_10-42-31.png upload_2018-1-29_10-42-31.png

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class DayNightSample : MonoBehaviour {
    5.     public Gradient skyColors;
    6.     public Gradient skyMiddleColors;
    7.     public Gradient skyBottomColors;
    8.     public Gradient lightColors;
    9.     [Range(0.0f, 24.0f)]
    10.     public float timeOfDay = 12f;
    11.     public float timeSpeed = .1f;
    12.     public AnimationCurve sunAnimationCurve;
    13.     public AnimationCurve moonAnimationCurve;
    14.     public AnimationCurve sunHorizontalAnimationCurve;
    15.     public AnimationCurve moonHorizontalAnimationCurve;
    16.     public AnimationCurve nightSkyTransparency;
    17.     public int startShootingStarsAt;
    18.     public int stopShootingStarsAt;
    19.     public float shootingStarProbability;
    20.     public int totalDaysThisSeason = 0;
    21.     public int seasonLength = 2;
    22.     public string currentSeason = "summer";
    23.  
    24.     GameObject sky;
    25.     Mesh skyMesh;
    26.     Vector3[] skyVertices;
    27.     Color[] skyVertexColors;
    28.     GameObject sun;
    29.     GameObject moon;
    30.     GameObject nightSky;
    31.     Renderer moonRenderer;
    32.     Renderer nightSkyRenderer;
    33.     Light skylight;
    34.     GameObject shootingStartsGO;
    35.     ParticleSystem shootingStars;
    36.     bool canShootStars = false;
    37.  
    38.     // public static DayNightSample Instance { get; private set; }
    39.  
    40.     // Use this for initialization
    41.     void Start () {
    42.         sky = GameObject.Find("SkyGradient");
    43.         if (sky) {
    44.             skyMesh = sky.GetComponent<MeshFilter> ().mesh;
    45.             skyVertices = skyMesh.vertices;
    46.             skyVertexColors = new Color[skyVertices.Length];
    47.         }
    48.  
    49.         sun = GameObject.Find("sun");
    50.  
    51.         moon = GameObject.Find("moon");
    52.         if (moon) {
    53.             moonRenderer = moon.GetComponent<Renderer>();
    54.         }
    55.  
    56.         skylight = GameObject.Find("Skylight").GetComponent<Light>();
    57.  
    58.         nightSky = GameObject.Find("NightSky");
    59.         if (nightSky) {
    60.             nightSkyRenderer = nightSky.GetComponent<Renderer>();
    61.         }
    62.         shootingStartsGO = GameObject.Find ("ShootingStars");
    63.         if (shootingStartsGO) {
    64.             shootingStars = shootingStartsGO.GetComponent<ParticleSystem> ();
    65.         }
    66.     }
    67.    
    68.     void Update () {
    69.         IncreaseTime();
    70.         Color currentSkyColor = GetCurrentSkyColor("top");
    71.         Color currentSkyMiddleColor = GetCurrentSkyColor("middle");
    72.         Color currentSkyBottomColor = GetCurrentSkyColor("bottom");
    73.         if (sky) {
    74.             ChangeSkyColor(currentSkyColor, currentSkyMiddleColor, currentSkyBottomColor);
    75.         }
    76.         Color currentLightColor = GetCurrentSkylightColor();
    77.         ChangeSkylightColor(currentLightColor);
    78.         if (sun) {
    79.             UpdateSunPosition();
    80.         }
    81.         if (moon) {
    82.             UpdateMoonPosition();
    83.         }
    84.         if (nightSky) {
    85.             UpdateNighskyVisibility();
    86.         }
    87.         if (shootingStartsGO) {
    88.             UpdateShootingStars ();
    89.         }
    90.     }
    91.  
    92.     void IncreaseTime() {
    93.         if (timeOfDay > 24) {
    94.             totalDaysThisSeason += 1;
    95.             if (totalDaysThisSeason == seasonLength) {
    96.                 ChangeSeason();
    97.             }
    98.             timeOfDay = 0;
    99.         } else {
    100.             timeOfDay += (timeSpeed * Time.deltaTime);
    101.         }
    102.     }
    103.  
    104.     void ChangeSeason() {
    105.         if (currentSeason == "summer") {
    106.             currentSeason = "winter";
    107.         } else {
    108.             currentSeason = "summer";
    109.         }
    110.         totalDaysThisSeason = 0;
    111.         Debug.Log("Current Season: " + currentSeason);
    112.     }
    113.  
    114.     void UpdateShootingStars() {
    115.         if (Mathf.Round (timeOfDay) == startShootingStarsAt) {
    116.             canShootStars = true;
    117.         } else if (Mathf.Round (timeOfDay) == stopShootingStarsAt) {
    118.             canShootStars = false;
    119.         }
    120.  
    121.         if (canShootStars) {
    122.             float randomValue = Random.value;
    123.             if (randomValue < shootingStarProbability) {
    124.                 shootingStars.Emit (1);
    125.             }
    126.         }
    127.     }
    128.  
    129.     void UpdateNighskyVisibility() {
    130.         float currentPointInCurve = nightSkyTransparency.Evaluate(timeOfDay);
    131.         nightSkyRenderer.material.color = new Color(1, 1, 1, currentPointInCurve);
    132.     }
    133.  
    134.     void ChangeSkyColor(Color color, Color middleColor, Color bottomColor) {
    135.         skyVertexColors [3] = color;
    136.         skyVertexColors [2] = color;
    137.         skyVertexColors [1] = middleColor;
    138.         skyVertexColors [0] = middleColor;
    139.         skyVertexColors [5] = bottomColor;
    140.         skyVertexColors [4] = bottomColor;
    141.         skyMesh.colors = skyVertexColors;
    142.     }
    143.  
    144.     void ChangeSkylightColor (Color color) {
    145.         skylight.color = color;
    146.     }
    147.  
    148.     void UpdateSunPosition() {
    149.         Vector3 sunPosition = sun.transform.position;
    150.         sunPosition.y = sunAnimationCurve.Evaluate(timeOfDay);
    151.         sun.transform.position = sunPosition;
    152.         Vector3 currentLocalPosition = sun.transform.localPosition;
    153.         sun.transform.localPosition = new Vector3(sunHorizontalAnimationCurve.Evaluate(timeOfDay), currentLocalPosition.y, currentLocalPosition.z);
    154.     }
    155.  
    156.     void UpdateMoonPosition() {
    157.         Vector3 moonPosition = moon.transform.position;
    158.         float currentPointInCurve = moonAnimationCurve.Evaluate(timeOfDay);
    159.         moonPosition.y = currentPointInCurve;
    160.         moon.transform.position = moonPosition;
    161.         Vector3 currentLocalPosition = moon.transform.localPosition;
    162.         moon.transform.localPosition = new Vector3(moonHorizontalAnimationCurve.Evaluate(timeOfDay), currentLocalPosition.y, currentLocalPosition.z);
    163.         moonRenderer.material.color = new Color(255, 255, 255, currentPointInCurve / 3);
    164.     }
    165.  
    166.     public Color GetCurrentSkyColor(string position) {
    167.         if (position == "top") {
    168.             return skyColors.Evaluate (timeOfDay / 24);
    169.         } else if (position == "middle") {
    170.             return skyMiddleColors.Evaluate (timeOfDay / 24);
    171.         } else {
    172.             return skyBottomColors.Evaluate (timeOfDay / 24);
    173.         }
    174.  
    175.     }
    176.  
    177.     public Color GetCurrentSkylightColor() {
    178.         return lightColors.Evaluate(timeOfDay / 24);
    179.     }
    180. }

    And here's the weather system, this just controls a bunch of particles emitters for rain/snow/lightning.
    I also have a plane with a fog texture on it that becomes visible when it rains or snows.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class MeteoController : MonoBehaviour {
    5.     bool isRainingOrSnowing = false;
    6.     ParticleSystem rain;
    7.     ParticleSystem.EmissionModule rainEm;
    8.     ParticleSystem.VelocityOverLifetimeModule rainVelocity;
    9.     ParticleSystem snow;
    10.     ParticleSystem.EmissionModule snowEm;
    11.     ParticleSystem.VelocityOverLifetimeModule snowVelocity;
    12.     AudioSource rainSound;
    13.     int currentDropsAmount = 0;
    14.     GameObject rainbow;
    15.     Animator rainbowAnimator;
    16.     GameObject fog;
    17.     Renderer fogRenderer;
    18.     GameObject lighting;
    19.     Light lightingLight;
    20.     Animation lightingAnimation;
    21.     GameObject lightningBolt;
    22.     Renderer lightningBoltRenderer;
    23.     AudioSource thunderSound;
    24.     DayNightSample dayNightSample;
    25.     ParticleSystem.EmissionModule currentEmitter;
    26.     WindController windController;
    27.  
    28.     public float rainProbability = .2f;
    29.     public float rainbowProbability = .5f;
    30.     public float lightingPropability = 1f;
    31.     public float fogAlphaIncrease = .001f;
    32.     public float maxAlphaValue = .9f;
    33.     public float maxRainParticles = 1000;
    34.     public int dropsIncrease = 5;
    35.     public float firstRainCheck = .5f;
    36.     public float checkRainEvery = 10.0f;
    37.     public float firstLightingCheck = 5.0f;
    38.     public float checkLightingEveryEvery = 10.0f;
    39.     // float currentFogAlpha = 0;
    40.  
    41.     void Start () {
    42.         fog = GameObject.Find ("Fog");
    43.         fogRenderer = fog.GetComponent<Renderer> ();
    44.         rain = GameObject.Find ("RainParticles").GetComponent<ParticleSystem> ();
    45.         rainEm = rain.emission;
    46.         rainVelocity = rain.velocityOverLifetime;
    47.         rainbow = GameObject.Find("Rainbow");
    48.         rainbowAnimator = rainbow.GetComponent<Animator>();
    49.         currentEmitter = rainEm;
    50.         snow = GameObject.Find ("Snow").GetComponent<ParticleSystem> ();
    51.         snowEm = snow.emission;
    52.         snowVelocity = snow.velocityOverLifetime;
    53.         rainSound = GameObject.Find("RainSound").GetComponent<AudioSource>();
    54.         lighting = GameObject.Find("Lighting");
    55.         lightingLight = lighting.transform.FindChild("LightingLight").GetComponent<Light>();
    56.         lightingAnimation = GameObject.Find("LightingLight").GetComponent<Animation>();
    57.         lightningBolt = GameObject.Find("LightningBolt");
    58.         lightningBoltRenderer = lightningBolt.GetComponent<Renderer>();
    59.         thunderSound = GameObject.Find("Thunder").GetComponent<AudioSource>();
    60.         dayNightSample = GameObject.Find("DayNightCycle").GetComponent<DayNightSample>();
    61.         windController = GameObject.Find("GameController").GetComponent<WindController>();
    62.         InvokeRepeating("TryRainOrSnow", firstRainCheck, checkRainEvery);
    63.         InvokeRepeating("TryLighting", firstLightingCheck, checkLightingEveryEvery);
    64.     }
    65.  
    66.     void Update() {
    67.         UpdateRain ();
    68.         UpdateLightningBolt();
    69.         UpdateRainSnowDirection();
    70.     }
    71.  
    72.     void UpdateLightningBolt() {
    73.         lightningBoltRenderer.material.color = new Color(1, 1, 1, lightingLight.intensity / 3);
    74.     }
    75.  
    76.     void TryLighting() {
    77.         if (isRainingOrSnowing && dayNightSample.currentSeason == "summer") {
    78.             float random = Random.value;
    79.             if (random < lightingPropability) {
    80.                 fireLighting ();
    81.             }
    82.         }
    83.     }
    84.  
    85.     void fireLighting() {
    86.         lightingAnimation.Play();
    87.         thunderSound.Play();
    88.     }
    89.  
    90.     void TryRainOrSnow() {
    91.         float random = Random.value;
    92.         if (random < rainProbability) {
    93.             if (!isRainingOrSnowing) {
    94.                 if (dayNightSample.currentSeason == "summer") {
    95.                     currentEmitter = rainEm;
    96.                 } else {
    97.                     currentEmitter = snowEm;
    98.                 }
    99.                 startRaining ();
    100.             } else {
    101.                 stopRaining ();
    102.             }
    103.         }
    104.     }
    105.  
    106.     void UpdateRain() {
    107.         if (isRainingOrSnowing) {
    108.             if (currentDropsAmount < maxRainParticles) {
    109.                 currentDropsAmount += dropsIncrease;
    110.                 ParticleSystem.MinMaxCurve rate = new ParticleSystem.MinMaxCurve ();
    111.                 rate.constantMax = currentDropsAmount;
    112.                 currentEmitter.rate = rate;
    113.                 float attenuatedRate = rate.constantMax / 1000;
    114.                 // Only if it's not snowing
    115.                 if (dayNightSample.currentSeason == "summer") {
    116.                     rainSound.volume = attenuatedRate;
    117.                 }
    118.                 UpdateFog(attenuatedRate);
    119.             }
    120.         } else {
    121.             if (currentDropsAmount > 0) {
    122.                 currentDropsAmount -= dropsIncrease;
    123.                 ParticleSystem.MinMaxCurve rate = new ParticleSystem.MinMaxCurve();
    124.                 rate.constantMax = currentDropsAmount;
    125.                 currentEmitter.rate = rate;
    126.                 float attenuatedRate = rate.constantMax / 1000;
    127.                 if (rainSound.volume != 0) {
    128.                     rainSound.volume = attenuatedRate;
    129.                 }
    130.                 UpdateFog(attenuatedRate);
    131.             }
    132.         }
    133.     }
    134.  
    135.     void UpdateFog(float value) {
    136.         fogRenderer.material.color = new Color(1,1,1, Mathf.Clamp(value, 0, maxAlphaValue));
    137.     }
    138.  
    139.     void startRaining() {
    140.         isRainingOrSnowing = true;
    141.     }
    142.  
    143.     void stopRaining() {
    144.         isRainingOrSnowing = false;
    145.         if (Random.value < rainbowProbability) {
    146.             rainbowAnimator.Play("RainbowFade", -1, 0f);
    147.         }
    148.     }
    149.    
    150.     void UpdateRainSnowDirection() {
    151.         if (windController.isTweening) {
    152.             ParticleSystem.MinMaxCurve rate = new ParticleSystem.MinMaxCurve();
    153.             rate.constantMax = windController.windSpeed;
    154.             snowVelocity.x = rate;
    155.             rate.constantMax = windController.windSpeed * 15;
    156.             rainVelocity.x = rate;
    157.         }
    158.     }
    159. }
     
    GrayRorschach likes this.
  30. Alucard-Belmont

    Alucard-Belmont

    Joined:
    Jul 4, 2017
    Posts:
    3

    In unitypackage please. Very thanks!!
     
  31. joni-giuro

    joni-giuro

    Joined:
    Nov 21, 2013
    Posts:
    433
    nope
     
  32. sngdan

    sngdan

    Joined:
    Feb 7, 2014
    Posts:
    798
    haha, i was just about to ask if you can scratch my back...
     
    joni-giuro likes this.
  33. mohansaimanthri03

    mohansaimanthri03

    Joined:
    Apr 17, 2018
    Posts:
    2
    can anyone post a video tutorial, it would be very helpful, because i am new to unity and c#
     
  34. mohansaimanthri03

    mohansaimanthri03

    Joined:
    Apr 17, 2018
    Posts:
    2
    or please post the meshes you are using
     
  35. johng1493

    johng1493

    Joined:
    Apr 25, 2017
    Posts:
    1
    In your MeteoController, do you have the code for your WindController object?
     
  36. joni-giuro

    joni-giuro

    Joined:
    Nov 21, 2013
    Posts:
    433
    sure:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class MeteoController : MonoBehaviour {
    5.     bool isRainingOrSnowing = false;
    6.     ParticleSystem rain;
    7.     ParticleSystem.EmissionModule rainEm;
    8.     ParticleSystem.VelocityOverLifetimeModule rainVelocity;
    9.     ParticleSystem snow;
    10.     ParticleSystem.EmissionModule snowEm;
    11.     ParticleSystem.VelocityOverLifetimeModule snowVelocity;
    12.     AudioSource rainSound;
    13.     int currentDropsAmount = 0;
    14.     GameObject rainbow;
    15.     Animator rainbowAnimator;
    16.     GameObject fog;
    17.     Renderer fogRenderer;
    18.     GameObject lighting;
    19.     Light lightingLight;
    20.     Animation lightingAnimation;
    21.     GameObject lightningBolt;
    22.     Renderer lightningBoltRenderer;
    23.     AudioSource thunderSound;
    24.     DayNightSample dayNightSample;
    25.     ParticleSystem.EmissionModule currentEmitter;
    26.     WindController windController;
    27.  
    28.     public float rainProbability = .2f;
    29.     public float rainbowProbability = .5f;
    30.     public float lightingPropability = 1f;
    31.     public float fogAlphaIncrease = .001f;
    32.     public float maxAlphaValue = .9f;
    33.     public float maxRainParticles = 1000;
    34.     public int dropsIncrease = 5;
    35.     public float firstRainCheck = .5f;
    36.     public float checkRainEvery = 10.0f;
    37.     public float firstLightingCheck = 5.0f;
    38.     public float checkLightingEveryEvery = 10.0f;
    39.     // float currentFogAlpha = 0;
    40.  
    41.     void Start () {
    42.         fog = GameObject.Find ("Fog");
    43.         fogRenderer = fog.GetComponent<Renderer> ();
    44.         rain = GameObject.Find ("RainParticles").GetComponent<ParticleSystem> ();
    45.         rainEm = rain.emission;
    46.         rainVelocity = rain.velocityOverLifetime;
    47.         rainbow = GameObject.Find("Rainbow");
    48.         rainbowAnimator = rainbow.GetComponent<Animator>();
    49.         currentEmitter = rainEm;
    50.         snow = GameObject.Find ("Snow").GetComponent<ParticleSystem> ();
    51.         snowEm = snow.emission;
    52.         snowVelocity = snow.velocityOverLifetime;
    53.         rainSound = GameObject.Find("RainSound").GetComponent<AudioSource>();
    54.         lighting = GameObject.Find("Lighting");
    55.         lightingLight = lighting.transform.FindChild("LightingLight").GetComponent<Light>();
    56.         lightingAnimation = GameObject.Find("LightingLight").GetComponent<Animation>();
    57.         lightningBolt = GameObject.Find("LightningBolt");
    58.         lightningBoltRenderer = lightningBolt.GetComponent<Renderer>();
    59.         thunderSound = GameObject.Find("Thunder").GetComponent<AudioSource>();
    60.         dayNightSample = GameObject.Find("DayNightCycle").GetComponent<DayNightSample>();
    61.         windController = GameObject.Find("GameController").GetComponent<WindController>();
    62.         InvokeRepeating("TryRainOrSnow", firstRainCheck, checkRainEvery);
    63.         InvokeRepeating("TryLighting", firstLightingCheck, checkLightingEveryEvery);
    64.     }
    65.  
    66.     void Update() {
    67.         UpdateRain ();
    68.         UpdateLightningBolt();
    69.         UpdateRainSnowDirection();
    70.     }
    71.  
    72.     void UpdateLightningBolt() {
    73.         lightningBoltRenderer.material.color = new Color(1, 1, 1, lightingLight.intensity / 3);
    74.     }
    75.  
    76.     void TryLighting() {
    77.         if (isRainingOrSnowing && dayNightSample.currentSeason == "summer") {
    78.             float random = Random.value;
    79.             if (random < lightingPropability) {
    80.                 fireLighting ();
    81.             }
    82.         }
    83.     }
    84.  
    85.     void fireLighting() {
    86.         lightingAnimation.Play();
    87.         thunderSound.Play();
    88.     }
    89.  
    90.     void TryRainOrSnow() {
    91.         float random = Random.value;
    92.         if (random < rainProbability) {
    93.             if (!isRainingOrSnowing) {
    94.                 if (dayNightSample.currentSeason == "summer") {
    95.                     currentEmitter = rainEm;
    96.                 } else {
    97.                     currentEmitter = snowEm;
    98.                 }
    99.                 startRaining ();
    100.             } else {
    101.                 stopRaining ();
    102.             }
    103.         }
    104.     }
    105.  
    106.     void UpdateRain() {
    107.         if (isRainingOrSnowing) {
    108.             if (currentDropsAmount < maxRainParticles) {
    109.                 currentDropsAmount += dropsIncrease;
    110.                 ParticleSystem.MinMaxCurve rate = new ParticleSystem.MinMaxCurve ();
    111.                 rate.constantMax = currentDropsAmount;
    112.                 currentEmitter.rate = rate;
    113.                 float attenuatedRate = rate.constantMax / 1000;
    114.                 // Only if it's not snowing
    115.                 if (dayNightSample.currentSeason == "summer") {
    116.                     rainSound.volume = attenuatedRate;
    117.                 }
    118.                 UpdateFog(attenuatedRate);
    119.             }
    120.         } else {
    121.             if (currentDropsAmount > 0) {
    122.                 currentDropsAmount -= dropsIncrease;
    123.                 ParticleSystem.MinMaxCurve rate = new ParticleSystem.MinMaxCurve();
    124.                 rate.constantMax = currentDropsAmount;
    125.                 currentEmitter.rate = rate;
    126.                 float attenuatedRate = rate.constantMax / 1000;
    127.                 if (rainSound.volume != 0) {
    128.                     rainSound.volume = attenuatedRate;
    129.                 }
    130.                 UpdateFog(attenuatedRate);
    131.             }
    132.         }
    133.     }
    134.  
    135.     void UpdateFog(float value) {
    136.         fogRenderer.material.color = new Color(1,1,1, Mathf.Clamp(value, 0, maxAlphaValue));
    137.     }
    138.  
    139.     void startRaining() {
    140.         isRainingOrSnowing = true;
    141.     }
    142.  
    143.     void stopRaining() {
    144.         isRainingOrSnowing = false;
    145.         if (Random.value < rainbowProbability) {
    146.             rainbowAnimator.Play("RainbowFade", -1, 0f);
    147.         }
    148.     }
    149.    
    150.     void UpdateRainSnowDirection() {
    151.         if (windController.isTweening) {
    152.             ParticleSystem.MinMaxCurve rate = new ParticleSystem.MinMaxCurve();
    153.             rate.constantMax = windController.windSpeed;
    154.             snowVelocity.x = rate;
    155.             rate.constantMax = windController.windSpeed * 15;
    156.             rainVelocity.x = rate;
    157.         }
    158.     }
    159. }