Search code examples
c#mobileunity-game-engineaccelerometer

How can I detect a shake motion on a mobile device using Unity3D? C#


I would have assumed unity has some event trigger for this but I can't find one in the Unity3d documentation. Would I need to work with changes in the accelerometer?

Thank you all.


Solution

  • Excellent discussion regarding detecting "shaking" can be found in this thread on the Unity forums.

    From Brady's post:

    From what I can tell in some of the Apple iPhone sample apps, you basically just set a vector magnitude threshold, set a high-pass filter on the accelerometer values, then if the magnitude of that acceleration vector is ever longer than your set threshold, it's considered a "shake".

    jmpp's suggested code (modified for readability and to be closer to valid C#):

    float accelerometerUpdateInterval = 1.0f / 60.0f;
    // The greater the value of LowPassKernelWidthInSeconds, the slower the
    // filtered value will converge towards current input sample (and vice versa).
    float lowPassKernelWidthInSeconds = 1.0f;
    // This next parameter is initialized to 2.0 per Apple's recommendation,
    // or at least according to Brady! ;)
    float shakeDetectionThreshold = 2.0f;
    
    float lowPassFilterFactor;
    Vector3 lowPassValue;
    
    void Start()
    {
        lowPassFilterFactor = accelerometerUpdateInterval / lowPassKernelWidthInSeconds;
        shakeDetectionThreshold *= shakeDetectionThreshold;
        lowPassValue = Input.acceleration;
    }
    
    void Update()
    {
        Vector3 acceleration = Input.acceleration;
        lowPassValue = Vector3.Lerp(lowPassValue, acceleration, lowPassFilterFactor);
        Vector3 deltaAcceleration = acceleration - lowPassValue;
    
        if (deltaAcceleration.sqrMagnitude >= shakeDetectionThreshold)
        {
            // Perform your "shaking actions" here. If necessary, add suitable
            // guards in the if check above to avoid redundant handling during
            // the same shake (e.g. a minimum refractory period).
            Debug.Log("Shake event detected at time "+Time.time);
        }
    }
    

    Note: I recommend you read the whole thread for the full context.