Search Unity

  1. Engage, network and learn at Unite Austin 2017, Oct 3 - 5. Get your ticket today!
    Dismiss Notice
  2. Introducing the Unity Essentials Packs! Find out more.
    Dismiss Notice
  3. Check out all the fixes for 5.6 on the patch releases page.
    Dismiss Notice
  4. Unity 2017.1 is now released.
    Dismiss Notice
  5. Unity 2017.2 beta is now available for download.
    Dismiss Notice

How to enable Camera Noise via script?

Discussion in 'Cinemachine' started by HarryDemch, Sep 12, 2017.

  1. HarryDemch

    HarryDemch

    Joined:
    Mar 9, 2015
    Posts:
    14
    Hey!
    Really love CM!

    For my 2D mobile game I need to be able to turn on a camera shake for about 0.5 sec. Before changing my camera to CM I used to do that using a script.
    I know I can shake a camera using Noise, but I need to shake it for a short period of time.

    The question is how can I apply Noise settings to vcam for exact period of time?
    1. apply Noise settings via script?
    2. blend between vcam w/o noise and vcam w/ noise?
    3. change Amplitude Gain and Frequency Gain of the Noise setting from 0 to 1 via script?
    What is the best way?

    Another question is how can I do any of this via script? Scripting references don't help me a lot. ScriptingExample.cs doesn't seem to be very helpful too.

    I'm using CM 2.1.

    Thank you!



    UPD 09.15.2017

    Here's the answer:
    1. Create CM VCam
    2. Make sure to use Basic Multi Channel Perlin in Noise Component (see attached screenshot)
    3. Add VCamShake.cs on the VCam
    4. From other script call VCamShake.Shake(0.3f) to shake camera for 0.3 sec. Insert any time you want.
    Code (CSharp):
    1. using System.Collections;
    2. using UnityEngine;
    3. using Cinemachine;
    4.  
    5. public class VCamShake : MonoBehaviour {
    6.  
    7.     public static VCamShake instance;
    8.  
    9.     private CinemachineVirtualCamera vcam;
    10.     private CinemachineBasicMultiChannelPerlin noise;
    11.     private float _timeAtCurrentFrame;
    12.     private float _timeAtLastFrame;
    13.     private float _fakeDelta;
    14.  
    15.  
    16.     void Awake()
    17.     {
    18.         instance = this;
    19.         vcam = GetComponent<CinemachineVirtualCamera>();
    20.         noise = vcam.GetCinemachineComponent<CinemachineBasicMultiChannelPerlin>();
    21.     }
    22.  
    23.     void Update()
    24.     {
    25.         // Calculate a fake delta time, so we can Shake while game is paused.
    26.         _timeAtCurrentFrame = Time.realtimeSinceStartup;
    27.         _fakeDelta = _timeAtCurrentFrame - _timeAtLastFrame;
    28.         _timeAtLastFrame = _timeAtCurrentFrame;
    29.     }
    30.  
    31.     public static void Shake(float duration)
    32.     {
    33.         instance.StopAllCoroutines();
    34.         instance.StartCoroutine(instance.cShake(duration));
    35.     }
    36.  
    37.     public IEnumerator cShake(float duration)
    38.     {
    39.         while (duration > 0)
    40.         {
    41.             noise.m_AmplitudeGain = 1f;
    42.             duration -= _fakeDelta;
    43.             yield return null;
    44.         }
    45.  
    46.         noise.m_AmplitudeGain = 0f;
    47.     }  
    48. }
    49.  
     

    Attached Files:

    Last edited: Sep 15, 2017
  2. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    310
    The noise settings themselves are assets, so modifying them at runtime is not recommended. The best way is to pulse the amplitude of the noise component.

    You can access the amplitude from script like this:
    CinemachineVirtualCamera vcam;
    vcam.GetCinemachineComponent<CinemachineBasicMultiChnnelPerlin>().m_Amplitude = bla;
     
    HarryDemch likes this.
  3. HarryDemch

    HarryDemch

    Joined:
    Mar 9, 2015
    Posts:
    14
    Hey, Gregoryl!

    Code (CSharp):
    1. vcam.GetCinemachineComponent<CinemachineBasicMultiChannelPerlin>().m_AmplitudeGain = 1f;
    This gives me a Null Reference error.
     
  4. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    310
    Like any other Unity component, you have to add it before you can reference it. vcam.AddCinemachineComponent<>() does it from script, else do it in the inspector.
     
    HarryDemch likes this.
  5. HarryDemch

    HarryDemch

    Joined:
    Mar 9, 2015
    Posts:
    14
    Hey, Gregoryl!

    Code (CSharp):
    1. vcam.AddCinemachineComponent<CinemachineBasicMultiChannelPerlin>();
    Gives a Null Reference too.

    I guess I should explain better what is happening.

    I have this script on CM vcam1
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Cinemachine;
    5.  
    6. public class VCamShake : MonoBehaviour {
    7.  
    8.     public static VCamShake instance;
    9.  
    10.     private CinemachineVirtualCamera vcam;
    11.     private float _timeAtCurrentFrame;
    12.     private float _timeAtLastFrame;
    13.     private float _fakeDelta;
    14.  
    15.  
    16.     void Awake()
    17.     {
    18.         instance = this;
    19.         vcam.AddCinemachineComponent<CinemachineBasicMultiChannelPerlin>();
    20.     }
    21.  
    22.     void Start()
    23.     {
    24.  
    25.     }
    26.  
    27.     void Update()
    28.     {
    29.         // Calculate a fake delta time, so we can Shake while game is paused.
    30.         _timeAtCurrentFrame = Time.realtimeSinceStartup;
    31.         _fakeDelta = _timeAtCurrentFrame - _timeAtLastFrame;
    32.         _timeAtLastFrame = _timeAtCurrentFrame;
    33.     }
    34.  
    35.     public static void Shake(float duration)
    36.     {
    37.         instance.StopAllCoroutines();
    38.         instance.StartCoroutine(instance.cShake(duration));
    39.     }
    40.  
    41.     public IEnumerator cShake(float duration)
    42.     {
    43.         while (duration > 0)
    44.         {
    45.             vcam.GetCinemachineComponent<CinemachineBasicMultiChannelPerlin>().m_AmplitudeGain = 1f;
    46.  
    47.             duration -= _fakeDelta;
    48.  
    49.             yield return null;
    50.         }
    51.     }
    52.  
    53. }

    In another script I'm calling
    Code (CSharp):
    1. VCamShake.Shake(0.3f);
    to shake CM vcam1 for 0.3 sec.

    Both
    Code (CSharp):
    1. vcam.AddCinemachineComponent<CinemachineBasicMultiChannelPerlin>();
    and
    Code (CSharp):
    1. vcam.GetCinemachineComponent<CinemachineBasicMultiChannelPerlin>().m_AmplitudeGain = 1f;
    are giving a Null Reference.

    What component should I add on the vcam? I prefer doing such things in inspector and I don't see nothing similar to CinemachineBasicMultiChannelPerlin (see attached screenshot).
     

    Attached Files:

  6. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    310
    Hi @HarryDemch Looks like you never initialize vcam. That's what's null.

    To set up noise via inspector, select "BasicMultiChannelPerlin" in the Noise component of the vcam. Assign it a Noise Definition from one of the preset assets included in the Cinemachine examples.

    Then from your script, get it (as described) and twiddle its amplitude.
     
    HarryDemch likes this.
  7. HarryDemch

    HarryDemch

    Joined:
    Mar 9, 2015
    Posts:
    14
    Hey, @Gregoryl
    Isn't it in the 10th line of VCamShake.cs?

    The "BasicMultiChannelPerlin" is turned on, using Noise Profile "Camera Shake", Amplitude Gain = 0, Frequency Gain = 1 (see the attached screenshot).

    Now VCamShake.cs looks like this

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Cinemachine;
    5.  
    6. public class VCamShake : MonoBehaviour {
    7.  
    8.     public static VCamShake instance;
    9.  
    10.     private CinemachineVirtualCamera vcam;
    11.     private float _timeAtCurrentFrame;
    12.     private float _timeAtLastFrame;
    13.     private float _fakeDelta;
    14.  
    15.  
    16.     void Awake()
    17.     {
    18.         instance = this;
    19.     }
    20.  
    21.     void Start()
    22.     {
    23.        
    24.     }
    25.  
    26.     void Update()
    27.     {
    28.         // Calculate a fake delta time, so we can Shake while game is paused.
    29.         _timeAtCurrentFrame = Time.realtimeSinceStartup;
    30.         _fakeDelta = _timeAtCurrentFrame - _timeAtLastFrame;
    31.         _timeAtLastFrame = _timeAtCurrentFrame;
    32.     }
    33.  
    34.     public static void Shake(float duration)
    35.     {
    36.         instance.StopAllCoroutines();
    37.         instance.StartCoroutine(instance.cShake(duration));
    38.     }
    39.  
    40.     public IEnumerator cShake(float duration)
    41.     {
    42.         while (duration > 0)
    43.         {
    44.             vcam.GetCinemachineComponent<CinemachineBasicMultiChannelPerlin>().m_AmplitudeGain = 1f;
    45.  
    46.             duration -= _fakeDelta;
    47.  
    48.             yield return null;
    49.         }
    50.     }
    51.    
    52. }

    Line 44 gives Null Reference.
     

    Attached Files:

  8. JacobSmaga

    JacobSmaga

    Joined:
    Aug 5, 2015
    Posts:
    125
    You never attatched vcam because it's private and there's no "vcam = ?;" function, that's why it's null. Make your vcam public or if the VCamShake is added to your VCam in the inspector just add "vcam = GetComponent<CinemachineVirtualCamera>();" in your Awake()
     
    Gregoryl and HarryDemch like this.
  9. HarryDemch

    HarryDemch

    Joined:
    Mar 9, 2015
    Posts:
    14
    Thank you very much, @Gregoryl and @JacobSmaga!

    For some reason I got confused, but now everything's working.

    Here's the answer to my question for anyone who might be interested:
    1. Create CM VCam
    2. Make sure to use Basic Multi Channel Perlin in Noise Component (see attached screenshot)
    3. Add VCamShake.cs on the VCam
    4. From other script call VCamShake.Shake(0.3f) to shake camera for 0.3 sec. Insert any time you want.
    Code (CSharp):
    1. using System.Collections;
    2. using UnityEngine;
    3. using Cinemachine;
    4.  
    5. public class VCamShake : MonoBehaviour {
    6.  
    7.     public static VCamShake instance;
    8.  
    9.     private CinemachineVirtualCamera vcam;
    10.     private CinemachineBasicMultiChannelPerlin noise;
    11.     private float _timeAtCurrentFrame;
    12.     private float _timeAtLastFrame;
    13.     private float _fakeDelta;
    14.  
    15.  
    16.     void Awake()
    17.     {
    18.         instance = this;
    19.         vcam = GetComponent<CinemachineVirtualCamera>();
    20.         noise = vcam.GetCinemachineComponent<CinemachineBasicMultiChannelPerlin>();
    21.     }
    22.  
    23.     void Update()
    24.     {
    25.         // Calculate a fake delta time, so we can Shake while game is paused.
    26.         _timeAtCurrentFrame = Time.realtimeSinceStartup;
    27.         _fakeDelta = _timeAtCurrentFrame - _timeAtLastFrame;
    28.         _timeAtLastFrame = _timeAtCurrentFrame;
    29.     }
    30.  
    31.     public static void Shake(float duration)
    32.     {
    33.         instance.StopAllCoroutines();
    34.         instance.StartCoroutine(instance.cShake(duration));
    35.     }
    36.  
    37.     public IEnumerator cShake(float duration)
    38.     {
    39.         while (duration > 0)
    40.         {
    41.             noise.m_AmplitudeGain = 1f;
    42.             duration -= _fakeDelta;
    43.             yield return null;
    44.         }
    45.  
    46.         noise.m_AmplitudeGain = 0f;
    47.     }  
    48. }
    49.  
     

    Attached Files: