2D water reflections in Unity 5

Some people asked me how I’m doing the water reflections in Last Voyage Of The Orlova, so here’s a quick look at the shader. Download at the bottom of the post.

The solution consists of two components: a shader for the groundwork, and a script to render it on a quad.

The shader has a texture slot and a color picker. The texture is optional, you can just change the water color using the color picker.

The script has settings for the reflection resolution, offset, and which layers should be reflected. I keep the resolution intentionally low (256) because otherwise the reflection is too perfect and it doesn’t look like water anymore. And I like the way it shimmers when you walk.

I’ve packaged the files up so you can try this in your own project right now:
Click here to download.

To get started, add these files to your project’s Assets folder, and drag the reflection prefab into your scene. You can adjust the size and position of the prefab to your needs.

Let me know here or on twitter if you use it, I’d love to see it in action in other places.

If you’re looking to add waves (with physics!) to the water surface, the Zippy Water 2D asset is pretty good. I applied this shader to their water prefab and it works.

 

19 thoughts on “2D water reflections in Unity 5

    1. Oh yeah good point, I talked about coloring the water but didn’t include the texture, woops! Just make a little square image with whatever color you want the water to be, import that into Unity, then set the texture’s wrap mode to repeat and put it into the water shader component’s texture slot, and then your water should be colored.

      Like

  1. Hi HedgeField, I’m delighted to find your article since I am trying to do a 2d reflection in unity too. I used the instructions from Unify with your code, but I’m getting some lag + lots of errors:

    Screen position out of view frustum (screen pos 512.000000, 0.000000, 252418.296875) (Camera rect 0 0 512 512)
    UnityEngine.Camera:Render()
    MirrorReflectionTwoDimension:OnWillRenderObject() (at Assets/Scripts/MirrorReflectionTwoDimension.cs:101)
    UnityEditor.DockArea:OnGUI()

    Do you know what might be the issue? I’m using the code on a quad, placed on the water surface.

    Like

    1. Hey there! From your post I couldn’t fully understand whether you used the original Unify code or the code from the download in my blogpost? Are you on Unity 5? I’ve seen this error once or twice before but I’m not sure what causes it yet. Some people have solved it by switching the camera between orthographic and perspective, making sure the near clipping plane is not set to zero, or closing and reopening the game and scene windows. I hope one of these solutions work for you! http://forum.unity3d.com/threads/solved-screen-position-out-of-view-frustum.60851/

      Like

    2. Hey so I looked into that error some more and it looks like it’s a problem with Unity itself. I added my understanding of it to the Known Issues section in the updated post above. Hope that helps!

      Like

  2. Thanks a ton!
    And about the annoying “Screen position out of view frustum” error I got it work by changing in the MirrorReflection class. More details, I comment out the line 72 (approximate) “reflectionCamera.projectionMatrix = projection;” and add this “reflectionCamera.projectionMatrix = cam.projectionMatrix;”. I just guess the far/near info of the reflectionCamera was just not right, so it caused the error. After changing it no longer spams errors, no more! Yeah.

    Liked by 1 person

  3. Hi, its wonderful,

    But i have an issue with canvas screen space camera, Quad object added Reflection Script and It will over GUI canvas (2D Game).

    Please help me fix this issue ?

    Thanks

    Like

    1. Hey there, I see the problem. To fix it, set the Plane Distance on the GUI canvas to 1, and the Order In Layer to something like 5000. Or switch the GUI to Screen Space – Overlay mode.

      Unity renders alpha-tested things (like 2D graphics) before it renders transparent objects, so by changing those values you force the screen-space GUI to render over the water.

      (Unity render queue order: background=1000, geometry=2000, alpha test=2450, transparent=3000, overlay=4000)

      Like

  4. Hi,
    Thank you for this script, it is really helpful !

    Personally, I replaced the offset parameter by a Transform object that I use as a pivot, so that moving the mesh does not affect the reflection plane.
    I’ll probably also update it to add movement to the water (Such as in Kingdom:New Lands)

    Anyway, thanks again, it work great !

    Liked by 1 person

  5. Hey, this script is awesome and I am using it with the Zippy 2D water, but I notice that all my sprites render on top of the water, but I actually want my floor to look partially submerged. Any way that I can get this to render on top of sprites? I have tried changing the layer order inside the zippy script, but that only works with a standard sprite shader, not your reflection shader?
    Thanks!

    Like

    1. Never mind, fixed by adjusting the rendering queue, which I had already done but didnt seem to work, so not sure why its suddenly started working now…

      Like

      1. Ah glad you figured it out! Unity can be weird like that. Yeah you have to set the render queue in the water material inspector. If need be you can manually increase the number even further to make sure it renders in front of everything you need it to. And thanks for the praise!

        Like

  6. I was so happy to find this resource…unfortunately I don’t see how to make it work :(
    Does the quad need to be perpendicular to the sprites to be reflected? I doubt, it would prevent to use an orthographic camera! So the quad is co linear to the sprites?
    How does it come that moving view in scene editor seems to change the reflection on the quad?
    I may surely sound a little bit stupid…but I will face it cause I need to be able to use this resource! ;)
    Would you please have some time to tell me how to proceed to get a good result?..or point me to a downloadable scene with your script/shader in action, please?

    Like

    1. Hi there Jayme, thanks for getting in touch. I realize I didn’t give explicit instructions on how to set this up, so I can understand your trouble. I’ve created a test project that you can download from http://timhengeveld.com/files/reflectiontest.zip. It’s made in Unity 2017.2, and shows how the shader should be applied. I also updated the original download link with some extra stuff needed to get started.

      Like

      1. p.s. If you change to position or size of the reflection quad and the reflection looks strange, try adjusting the clip plane offset value on the mirrorreflection script. Negative values move the reflection down, positive values move it up.

        Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s