Last active
July 16, 2024 15:25
-
-
Save kurtdekker/0f5f353911d7a064e20868e4e5f4dba4 to your computer and use it in GitHub Desktop.
Head shake no and nod yes gesture detector
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
// @kurtdekker - head nod yes sensor | |
// | |
// To use: | |
// Put this on a mouse-controlled FPS camera and it can detect: | |
// - up/down "head nods yes." | |
// Optionally give it an audio to play | |
// | |
public class HeadNodYesSensor : MonoBehaviour | |
{ | |
public AudioSource AudioYes; | |
// how many up-downs until we say "you nodded" | |
const float NodCountRequired = 6; | |
// how much up/down constitutes half of a nod | |
const float NodAngularRequirement = 3; | |
// each phase of "nod" only latches for this long | |
const float NodTimingRequirement = 0.75f; | |
// track if we think you are nodding | |
float NodInProgress; | |
float LastSignificantNodAngle; | |
int LastDigitalNod; | |
int NodCount; | |
void UpdateNodYes() | |
{ | |
// time out | |
if (NodInProgress > 0) | |
{ | |
NodInProgress -= Time.deltaTime; | |
if (NodInProgress <= 0) | |
{ | |
//Debug.Log( "Timed out - NOD YES"); | |
NodCount = 0; | |
LastDigitalNod = 0; | |
} | |
} | |
// how far up/down is your head? | |
float forwardY = transform.forward.y; | |
float angle = Mathf.Asin( forwardY) * Mathf.Rad2Deg; | |
// quantize and study this nod | |
int nod = 0; // neutral, +1 is up, -1 is down | |
if (angle < LastSignificantNodAngle - NodAngularRequirement) | |
{ | |
//Debug.Log( "Down"); | |
nod = -1; | |
LastSignificantNodAngle = angle; | |
} | |
else | |
{ | |
if (angle > LastSignificantNodAngle + NodAngularRequirement) | |
{ | |
//Debug.Log( "Up"); | |
nod = +1; | |
LastSignificantNodAngle = angle; | |
} | |
} | |
// we've gone up / down enough? | |
if (nod != 0) | |
{ | |
// and it was in a different direction than before | |
if (nod != LastDigitalNod) | |
{ | |
LastDigitalNod = nod; | |
NodCount++; | |
// reset timing, we think you might still be nodding | |
NodInProgress = NodTimingRequirement; | |
if (NodCount >= NodCountRequired) | |
{ | |
NodCount = 0; | |
// TODO: perhaps inhibit sensing for a second or so? | |
Debug.Log( "Yuuuup!"); | |
if (AudioYes) AudioYes.Play(); | |
} | |
} | |
} | |
} | |
void Update () | |
{ | |
UpdateNodYes(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
// @kurtdekker - head shake no sensor | |
// | |
// To use: | |
// Put this on a mouse-controlled FPS camera and it can detect: | |
// - left/right "shake head no" | |
// Optionally give it an audio to play | |
// | |
public class HeadShakeNoSensor : MonoBehaviour | |
{ | |
public AudioSource AudioNo; | |
// how many left-rights until we say "you said no" | |
const float ShakeCountRequired = 6; | |
// how much left/right constitutes half of a shape | |
const float ShakeAngularRequirement = 3; | |
// each phase of "shake only latches for this long | |
const float ShakeTimingRequirement = 0.50f; | |
// track if we think you are nodding | |
float ShakeInProgress; | |
float LastSignificantShakeAngle; | |
int LastDigitalShake; | |
int ShakeCount; | |
void UpdateShakeNo() | |
{ | |
// time out | |
if (ShakeInProgress > 0) | |
{ | |
ShakeInProgress -= Time.deltaTime; | |
if (ShakeInProgress <= 0) | |
{ | |
//Debug.Log( "Timed out - SHAKE NO"); | |
ShakeCount = 0; | |
LastDigitalShake = 0; | |
} | |
} | |
// how far up/down is your head? | |
float angle = transform.eulerAngles.y; | |
// quantize and study this shake | |
int shake = 0; // neutral, -1 is right, +1 is left | |
float deltaAngle = Mathf.DeltaAngle( angle, LastSignificantShakeAngle); | |
if (deltaAngle < -ShakeAngularRequirement) | |
{ | |
//Debug.Log( "Right"); | |
shake = -1; | |
LastSignificantShakeAngle = angle; | |
} | |
else | |
{ | |
if (deltaAngle > +ShakeAngularRequirement) | |
{ | |
//Debug.Log( "Left"); | |
shake = +1; | |
LastSignificantShakeAngle = angle; | |
} | |
} | |
// we've gone left / right enough? | |
if (shake != 0) | |
{ | |
// and it was in a different direction than before | |
if (shake != LastDigitalShake) | |
{ | |
LastDigitalShake = shake; | |
ShakeCount++; | |
// reset timing, we think you might still be nodding | |
ShakeInProgress = ShakeTimingRequirement; | |
if (ShakeCount >= ShakeCountRequired) | |
{ | |
ShakeCount = 0; | |
// TODO: perhaps inhibit sensing for a second or so? | |
Debug.Log( "Nope!!"); | |
if (AudioNo) AudioNo.Play(); | |
} | |
} | |
} | |
} | |
void Update () | |
{ | |
UpdateShakeNo(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
See it in action here:
https://youtu.be/KIp0d8h3utw