Skip to content

Instantly share code, notes, and snippets.

@kurtdekker
Last active February 16, 2024 10:21
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kurtdekker/0f5f353911d7a064e20868e4e5f4dba4 to your computer and use it in GitHub Desktop.
Save kurtdekker/0f5f353911d7a064e20868e4e5f4dba4 to your computer and use it in GitHub Desktop.
Head shake no and nod yes gesture detector
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();
}
}
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();
}
}
@kurtdekker
Copy link
Author

See it in action here:

https://youtu.be/KIp0d8h3utw

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment