Camera Vibration in Canvas Based Unity Game
Currently I am maintaining a 2D Unity game (check it out here if you are interested). I was trying to implement a feature that when the user gives illegal input, the whole screen would shake (or vibrate if you would) for a while.
Here’s a GIF as a demo. When the user try to multiply of divide a variable with x, the whole screen will vibrate for 0.3 seconds.
I know what you would say, what’s the big deal here? We can simply randomly move the main camera for 0.3 seconds to achieve the effect. I don’t blame you, because that’s what I thought at first glance.
I attached a
CameraShaker.cs script to the main camera. The script looks like this
And in another script I call the
Then I ran the game and tried it… Oh wait! Why isn’t the screen shaking? I quickly found that it’s because the canvas’
renderMode property is at its default value
Screen Space - Overlay
When this property is set as
Screen Space - Overlay or
Screen Space - Camera, the canvas is always attached to the screen (and of course the camera), and so it’s vibrating with the camera. That’s why we can’t see any vibration happen.
So the solution is simply set the
renderMode property to
World Space in the inspector. In this way the canvas and the camera are decoupled and so the vibration can be seen.
This should work in most cases, but for me, I found that when set to
World Space, the light blue operator when dragged (see the above GIF) will not be displayed. That’s because to position the blue operator at mouse position the coupling between canvas and camera(screen) is needed.
So my final solution is, set the
renderMode of the canvas to
World Space when the vibration start, and set it back to
Screen Space - Overlay once the vibration finish. Since the vibration time is short, this should not affect the display of the light blue operator.
The final version of
CameraShaker.cs is shown below:
Let’s take a closer look at what I did in
Before setting the
WorldSpace, I set it to
ScreenSpaceCamera first. That’s because by setting it to
ScreenSpaceCamera, the canvas will be automatically positioned and scaled to fit in the camera. If I jump from
ScreenSpaceOverlay directly to
WorldSpace, the canvas will be out of the sight of the camera, and we will need to manually reposition the canvas in that case.