Contributions by Alex Ling
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
VibrateForTime
method:
|
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
VibrateForTime
:
|
Before setting the
renderMode
to 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.