Search Unity

  1. Full schedule for #UniteBerlin is now available! Featuring talks on our roadmap, hands-on labs and much more! Check it out!
    Dismiss Notice
  2. Unity 2018.1 has arrived! Read about it here
    Dismiss Notice
  3. Scriptable Render Pipeline improvements, Texture Mipmap Streaming, and more! Check out what we have in store for you in the 2018.2 Beta.
    Dismiss Notice
  4. ARCore is out of developer preview! Read about it here.
    Dismiss Notice
  5. Magic Leap’s Lumin SDK Technical Preview for Unity lets you get started creating content for Magic Leap One™. Find more information on our blog!
    Dismiss Notice
  6. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

How to shake camera with cinemachine?

Discussion in 'Cinemachine' started by Tak2017, Jul 29, 2017.

  1. Tak2017

    Tak2017

    Joined:
    Mar 30, 2017
    Posts:
    6
    Hello,Can anyone help me with this?
    I used to shake camera with script when the charactor was hit by attack,
    After using cinemachine the script doesn't work,How can I shake the camera with cinemachine?
     
    vlad010694 likes this.
  2. JakubSmaga

    JakubSmaga

    Joined:
    Aug 5, 2015
    Posts:
    375
    Use the Noise module.
     
    Last edited: Dec 10, 2017
  3. sebsmax

    sebsmax

    Joined:
    Sep 8, 2015
    Posts:
    58
    hey @Tak2017, got the same issue, this is what I've done:
    • In the freeCamera, go and add a noise pattern, put AmplitudeGain and FrequencyGain to 0.
    • Add the following code in your camera function
    • launch the code with a "StartCoroutine(_ProcessShake (5, 0.5f) );"
    Code (CSharp):
    1.  
    2.  
    3.         private IEnumerator _ProcessShake(float shakeIntensity = 5f, float shakeTiming = 0.5f)
    4.         {
    5.                 Noise(1, shakeIntensity);
    6.                 yield return new WaitForSeconds(shakeTiming);
    7.                 Noise(0, 0);
    8.         }
    9.  
    10.         public void Noise(float amplitudeGain, float frequencyGain)
    11.         {
    12.             cmFreeCam.topRig.Noise.m_AmplitudeGain = amplitudeGain;
    13.             cmFreeCam.middleRig.Noise.m_AmplitudeGain = amplitudeGain;
    14.             cmFreeCam.bottomRig.Noise.m_AmplitudeGain = amplitudeGain;
    15.              
    16.             cmFreeCam.topRig.Noise.m_FrequencyGain = frequencyGain;
    17.             cmFreeCam.middleRig.Noise.m_FrequencyGain = frequencyGain;
    18.             cmFreeCam.bottomRig.Noise.m_FrequencyGain = frequencyGain;      
    19.  
    20.         }
    21.  
    22.  
     
    vlad010694 likes this.
  4. Tak2017

    Tak2017

    Joined:
    Mar 30, 2017
    Posts:
    6
    Thanks very much! I'll try this!
     
  5. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    1,108
    @Tak2017 Don't take the syntax in the example too literally. Have a look at Cinemachine/Examples/Scenes/Scripting/ScriptingExample.cs for the correct syntax for accessing CM camera component members.
     
    vlad010694 likes this.
  6. Tak2017

    Tak2017

    Joined:
    Mar 30, 2017
    Posts:
    6
    I want to shake strongly in very short time like 6 to 10 frames,not the handheld style.Thank you all the same~
     
  7. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    1,108
  8. Tak2017

    Tak2017

    Joined:
    Mar 30, 2017
    Posts:
    6
    Thanks for your reply!I'll Try this,and post my progess later,thank you!
     
  9. vlad010694

    vlad010694

    Joined:
    Nov 14, 2017
    Posts:
    1
    @sebsmax @Tak2017 @Gregoryl Thank you!

    Code (csharp):
    1.  
    2. CinemachineVirtualCamera vcam;
    3. CinemachineBasicMultiChannelPerlin noise;
    4.  
    5. void Start() {
    6.         vcam = GameObject.Find("CM vcam1").GetComponent<CinemachineVirtualCamera> ();
    7.         noise = vcam.GetCinemachineComponent<CinemachineBasicMultiChannelPerlin> ();
    8. }
    9.  
    10. public void Noise(float amplitudeGain, float frequencyGain) {
    11.         noise.m_AmplitudeGain = amplitudeGain;
    12.         noise.m_FrequencyGain = frequencyGain;    
    13. }
    14.  
     
    kirillrybin likes this.
  10. Meatgrind

    Meatgrind

    Joined:
    Jul 12, 2012
    Posts:
    36
    Duplicating my post here from https://forum.unity.com/threads/how-to-enable-camera-noise-via-script.495032/#post-3416215

    @Gregoryl You suggest to use the BasicMultiChannelPerlinNoise extension component, which is fine in this kind of setup where you have a Scene with one VirtualCamera that is always shaking.

    I'm looking for more of game-event driven camera shake to make short-duration events during play more impactful, like player getting damage, things breaking, final hits when defeating enemies, explosions happening.

    The thing is that there is a vast amount of Scenes, each with similarly large number of VirtualCameras, and some VirtualCameras are actually already using the noise component for something else that they need to emphasize.

    I'd like to setup a system where I can pretty much call CameraShake.Shake(someShakeTemplateParameter) where someShakeTemplateParameter is probably a ScriptableObject with various intensity and duration variables set up so I can call "CameraShake.Shake(playerHitShake);" or "CameraShake.Shake(hugeExplosion);" and such in code where enemies hit or bombs go off.

    I already threw together a class that tries to do a lot of things, like:
    • look for a CameraBrain to get the active VirtualCamera from
    • tracks Scene changes to re-look for a new CameraBrain and check for all other current references
    • tracks current CameraBrains VirtualCameraActivation event to check if it needs to Add or Get a new BasicMultiChannelPerlinNoise component for the current VirtualCamera
    • Hijacks the BasicMultiChannelPerlinNoise component and forces a new noise profile, new amplitude and new frequency values, storing the old values
    • restores the old values after a duration
    • etc.
    The system is not perfect by a long shot. It's easy to lose track of a VirtualCamera before restoring something and my quickly implemented system already managed to fail a couple of tests for tracking the VirtualCamera changes, so there's somewhere a on-standby VirtualCamera shaking wildly, while the active one no longer shakes when expected to.

    Yeah, I will probably try to improve my system to use your recommendation of VirtualCamera noise for camera shake, but it's a lot of work, breaks using the noise for other purposes, requires constantly adding/getting a ton of component references and I feel there has to be a better way.
     
  11. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    1,108
    There is very much a better way. Cinemachine has moved forward since the recommendation of using BasicMultiChannelPerlinNoise for camera shakes, and I would no longer recommend that approach.

    Right now in development is the Cinemachine Impulse system, which does something very much like what you describe (i.e. scriptable-object Shake definitions, and the ability to broadcast shakes to all active cameras). It really is exactly what you need. However, it's not quite ready for prime-time so I can't let you give it a spin just yet. But it's pretty close.

    If you're in a hurry to get something up and running now, I would suggest the following approach:
    1. Forget about using the BasicMultiChannelPerlinNoise component, for all the reasons you outline. Throw that idea away.
    2. Use the CinemachineExtension API to write a camera shaker. I'll include a simple example below, that shakes the camera continuously. Use that as a starting point for your extension.
    3. Instead of shaking the camera continuously, have the shaker extension query a singleton for current active "shakes", and apply the signal to the vcam.
    4. The "CameraShake(shakeDefinition) method could live on the singleton. Your game code would call it to initiate shakes.
    5. The key is not to push the shakes to the vcams. Let them listen for shakes instead, via the CameraShake extension. Put that extension on all your vcams. It won't interfere with any Perlin Noise that's on the vcams.
    That would be a baby version of the Impulse system. Of course you could just wait a few weeks for the real deal instead of home-brewing. Here is the sample extension I mentioned:
    Code (CSharp):
    1. using UnityEngine;
    2. using Cinemachine;
    3.  
    4. /// <summary>
    5. /// An add-on module for Cinemachine to shake the camera
    6. /// </summary>
    7. [ExecuteInEditMode] [SaveDuringPlay] [AddComponentMenu("")] // Hide in menu
    8. public class CameraShake : CinemachineExtension
    9. {
    10.     [Tooltip("Amplitude of the shake")]
    11.     public float m_Range = 0.5f;
    12.  
    13.     protected override void PostPipelineStageCallback(
    14.         CinemachineVirtualCameraBase vcam,
    15.         CinemachineCore.Stage stage, ref CameraState state, float deltaTime)
    16.     {
    17.         if (stage == CinemachineCore.Stage.Body)
    18.         {
    19.             Vector3 shakeAmount = GetOffset();
    20.             state.PositionCorrection += shakeAmount;
    21.         }
    22.     }
    23.  
    24.     Vector3 GetOffset()
    25.     {
    26.         // Note: change this to something more interesting!
    27.         return new Vector3(
    28.             Random.Range(-m_Range, m_Range),
    29.             Random.Range(-m_Range, m_Range),
    30.             Random.Range(-m_Range, m_Range));
    31.     }
    32. }
    33.  
     
    Last edited: Mar 7, 2018
    DeviTobi and Alverik like this.
  12. Meatgrind

    Meatgrind

    Joined:
    Jul 12, 2012
    Posts:
    36
    Wow, that's a fantastic response! Thank you for staying civil in the face of my rant and providing such a prompt, informative and immediately helpful answer!

    We're running on a deadline, so I don't quite have the time to roll my own at this point, nor can I simply wait for two weeks, but your example will tide my needs over as a nice compromise. I'll use that to implement a quick temporary solution and hope that your Impulse system will be available in two weeks - if not, I'll scramble to improve the slap-patch solution, but at least now I don't have an immediate need to allocate much time for it. :)
     
    Gregoryl likes this.
  13. Smoole

    Smoole

    Joined:
    Nov 3, 2017
    Posts:
    3
    @Gregoryl Any updates on the Cinemachine Impulse System that you can share? Any ETA? :p
     
  14. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    1,108
    Yes, it will be there in the next CM release, to coincide with Unite Berlin.
    It's possible that there will be some preview releases prior to then.
     
    Alverik and JakubSmaga like this.
  15. max_mcguire

    max_mcguire

    Joined:
    Sep 17, 2015
    Posts:
    3
    Did this feature make it into 2.1.12?
     
  16. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    1,108
    No, but it's on the verge.
     
  17. sandBucket2

    sandBucket2

    Joined:
    Mar 26, 2016
    Posts:
    10
    Hey Greg, quick question on the code you posted:

    Which object do I attach this script? Would it be one of the virtual cams? Would I call this class in another script and pass it the virtual cam? Also how would I control the time to shake? Would I Slerp the total shake over a set amount of time using a while loop in a coroutine?

    Let me know and thanks!
     
  18. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    1,108
    @sandBucket2 You just drop the script in your project, and it will show up in the virtual camera "Extensions" menu. Add it to the vcam from there.

    For making a pulse, you would need to set an amplitude and a duration. I would decay the amplitude over the course of the duration, not necessarily with a lerp, as that would look mechanical. Use some kind of exponential damping. You could do that animation in a coroutine, as you suggested. It will only shake the vcam it's attached to.
     
  19. sandBucket2

    sandBucket2

    Joined:
    Mar 26, 2016
    Posts:
    10
    Thanks! Also an offtopic question:

    I've tried to import the latest post processing stack (v2) off github but I keep getting this error after import: Assets/PostProcessing/CinemachinePostFX.cs(45,28): error CS0234: The type or namespace name `PostProcessing' does not exist in the namespace `UnityEngine'. Are you missing an assembly reference?

    I'm using Unity 2017 but I've heard that cinemachine works with the v2 stack on 2017. How would I go about fixing this?
     
  20. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    1,108
    If you're using Post v2 then you can just delete the file that's generating the errors. It's for Post v1 and you don't need it.
     
  21. sandBucket2

    sandBucket2

    Joined:
    Mar 26, 2016
    Posts:
    10
    Thanks again, last question: are there any other files that I should delete from the cinemachine folder to prevent unwanted interactions between the cinemachine scripts? Also which version of the post processing stack v2 should I use for the cinemachine I've downloaded on 2017 Unity?
     

    Attached Files:

  22. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    1,108
    Nothing more to delete afaik.

    At one point there was a mechanism for auto-detecting which Post version was installed. That was a little naive and seems to be backfiring, as it's depending on script defines which don't get cleaned up when stuff is uninstalled.

    Use whichever version of Post V2 has the features you need. CM is pretty agnostic. Probably the latest stable release is fine.
     
  23. sandBucket2

    sandBucket2

    Joined:
    Mar 26, 2016
    Posts:
    10
    Thanks, I got it to work :)

    I've been using cinemachine for a while now and I've noticed that it calls GUI.Repaint during runtime. I've seen from other threads that this should only happen during the editor and not during runtime, how would I go about fixing this?

    Here's the deep profile from runtime:
    upload_2018-5-20_10-45-42.png

    The GUI.Repaint() method is happening every frame and spikes every 10 seconds during runtime.
     
    Last edited: May 20, 2018 at 4:10 PM
  24. sandBucket2

    sandBucket2

    Joined:
    Mar 26, 2016
    Posts:
    10
    Following up from my last post, I ended up commenting out 5 instances of #if UNITY EDITOR regarding OnGui on:
    -CinemachineVirtualCameraBase.cs
    -CinemachineComposer.cs
    -CinemachineBlendListCamera.cs
    -CinemachineStateDrivenCamera.cs
    -CinemachineClearShot.cs

    when I commented out those blocks of code, the GUI.Repaint() was gone and I started getting stable framerate, however, have I removed something important from the editor when I did that? Any loss of functionality to the virtual camera in scene view? I can't tell, everything seems fine.

    Its noted in the CinemachineVirtualCameraBase.cs that OnGUI() was called as "Support for the deprecated CinemachineDebugger". Since I commented out the #if UNITY EDITOR on those files, are there other things I need to comment out like delegates or declared actions?

    Let me know and thanks!
     
  25. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    1,108
    The only things you're losing are the Composer Guides and some of the "current vcam" debug text in the upper left of the game screen. If you want the composer guides back then you need to uncomment OnGUI in CinemachineComposer.

    And remember, even if you don't comment anything out, Cinemachine won't ever call OnGUI in builds, since it's protected by #if UNITY_EDITOR.