Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Cinemachine Screen Shake NullReferenceException

Discussion in 'Cinemachine' started by Pichuscute0, Apr 25, 2019.

  1. Pichuscute0

    Pichuscute0

    Joined:
    Jun 14, 2014
    Posts:
    18
    I've banging my head against the wall for the past 24 hours trying to sort out why this Cinemachine plugin is throwing NullReferenceExceptions seemingly at random while trying to get a simple screenshake to work. I've taken this code below from somewhere else. Last night, I set the VirtualCamera's settings to this and it worked as intended.

    https://imgur.com/5acXMiW

    I made made a build and then saved & closed Unity, and that worked too. This morning, I've opened the project back up only to find that the NullReferenceExceptions have returned. Here's the code.

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5.  
    6. /// <summary>
    7. /// Add this component to your Cinemachine Virtual Camera to have it shake when calling its ShakeCamera methods.
    8. /// </summary>
    9. public class camShake : MonoBehaviour {
    10.     /// the amplitude of the camera's noise when it's idle
    11.     public float IdleAmplitude = 0.1f;
    12.     /// the frequency of the camera's noise when it's idle
    13.     public float IdleFrequency = 1f;
    14.  
    15.     /// The default amplitude that will be applied to your shakes if you don't specify one
    16.     public float DefaultShakeAmplitude = .5f;
    17.     /// The default frequency that will be applied to your shakes if you don't specify one
    18.     public float DefaultShakeFrequency = 10f;
    19.  
    20.     protected Vector3 _initialPosition;
    21.     protected Quaternion _initialRotation;
    22.  
    23.     protected Cinemachine.CinemachineBasicMultiChannelPerlin _perlin;
    24.     protected Cinemachine.CinemachineVirtualCamera _virtualCamera;
    25.  
    26.     /// On awake we grab our components
    27.     protected virtual void Awake() {
    28.         _virtualCamera = GameObject.FindObjectOfType<Cinemachine.CinemachineVirtualCamera>();
    29.         _perlin = _virtualCamera.GetCinemachineComponent<Cinemachine.CinemachineBasicMultiChannelPerlin>();
    30.     }
    31.  
    32.     /// On Start we reset our camera to apply our base amplitude and frequency
    33.     protected virtual void Start() {
    34.         CameraReset();
    35.     }
    36.  
    37.     /// Use this method to shake the camera for the specified duration (in seconds) with the default amplitude and frequency
    38.     public virtual void ShakeCamera(float duration) {
    39.         StartCoroutine(ShakeCameraCo(duration, DefaultShakeAmplitude, DefaultShakeFrequency));
    40.     }
    41.  
    42.     /// Use this method to shake the camera for the specified duration (in seconds), amplitude and frequency
    43.     public virtual void ShakeCam(float amplitude, float frequency, float duration) {
    44.         StartCoroutine(ShakeCameraCo(duration, amplitude, frequency));
    45.     }
    46.  
    47.     /// This coroutine will shake the
    48.     protected virtual IEnumerator ShakeCameraCo(float duration, float amplitude, float frequency) {
    49.         _perlin.m_AmplitudeGain = amplitude;
    50.         _perlin.m_FrequencyGain = frequency;
    51.         yield return new WaitForSeconds(duration);
    52.         CameraReset();
    53.     }
    54.  
    55.     /// Resets the camera's noise values to their idle values
    56.     public virtual void CameraReset() {
    57.         _perlin.m_AmplitudeGain = IdleAmplitude;
    58.         _perlin.m_FrequencyGain = IdleFrequency;
    59.     }
    60.  
    61. }
    The NullReferenceExceptions occur at any time there is a reference to m_AmplitudeGain, despite that clearly being a thing. My guess has been that since this is a Unity example project file from a little less than a year ago that I've loaded into 2017.1.1f1 (because that's what it used), that it's an old bug with Cinemachine. But I'm very scared to update because 1. I don't want to have to make another difference screen shake script for something that should be trivial and 2. I'm scared it will break even more. I already know that using the latest version of Unity breaks other parts of this project that I'm not willing to fix at the moment, so updating Unity is simply not an option.

    Is my only hope to remove Cinemachine entirely or is there something here I'm missing?
     
    Last edited: Apr 25, 2019
  2. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,658
    Probably your _perlin is null.
    This script is very fragile and could benefit from some null checks.
    Maybe when Awake() is called the vcam isn't loaded in your scene?
    Try moving the Awake() code to start, add add some diagnostic null checks.
    This approach is very outdated. There are much better ways to do camera shakes with CM.
     
  3. Pichuscute0

    Pichuscute0

    Joined:
    Jun 14, 2014
    Posts:
    18
    Yeah, I figured, but what does the perlin being null mean when I have it set in the Cinemachine settings to a perlin and am having the code get that? Especially since it was unchanged from when I last closed it, and it was working then. That's what confuses me.

    I've just added some code to prevent the error if it's null, but that doesn't actually make it function, obviously, which is what I want. Also, yeah, I'm aware there's probably better code, but I'm only using Cinemachine because it happened to be in this demo project already. Ideally, I'd just use a normal camera with a shake script I'd already written. But with that said, it's hard to find pretty much any info. on Cinemachine, so I would be hard-pressed to actually know how to make any better screenshake with it.


    EDIT: I've ended up just changing the target object (it was following/targeting my player) to a child object that I can move around for an unrelated effect. Realized this could be used to make a screen shake by just randomly changing that object's position, so I don't need something robust anymore. Still, this was a very odd error that I still don't really get.
     
    Last edited: Apr 25, 2019