Skip to content

Instantly share code, notes, and snippets.

@beardordie
Created December 6, 2023 06:23
Show Gist options
  • Save beardordie/4dc6f949299a917ce845a30edcfddce3 to your computer and use it in GitHub Desktop.
Save beardordie/4dc6f949299a917ce845a30edcfddce3 to your computer and use it in GitHub Desktop.
Using audiosamples/volume of AudioSource to simply animate a Jaw Transform. As seen here: https://youtu.be/5P_mWSFA4ow
[SerializeField] private AudioSource _linkedAudioSource = null;
[SerializeField] private float _minRmsValue = 0.0001f; // minimum to consider "talking"
[SerializeField] private Renderer _rendererToCheckVisibility = null;
[SerializeField] private float _jawTalkSpeed = 0.12f;
private JawStates _jawState = JawStates.Default;
private float[] _samples = new float[512]; // For spectrum data
private float _rmsValue; // Root mean square, representing audio level
public enum JawStates
{
Default,
Talking
}
void GetAudioData()
{
_linkedAudioSource.GetSpectrumData(_samples, 0, FFTWindow.BlackmanHarris);
}
void CalculateRMS()
{
float sum = 0;
for (int i = 0; i < _samples.Length; i++)
{
sum += _samples[i] * _samples[i];
}
decimal decimalValue = Math.Round((decimal)Mathf.Sqrt(sum / _samples.Length), 4);
_rmsValue = (float)decimalValue;
}
void Update()
{
bool RmsIsLoudEnough()
{
GetAudioData();
CalculateRMS();
return rmsValue >= minRmsValue;
}
if (Time.frameCount % 10 == 0) // only check once every 10 frames
{
// this if condition is complex because we don't want to calculate things when not necessary. the most expensive calculation is last in the condition
if (_linkedAudioSource.clip != null && _linkedAudioSource.isPlaying && _rendererToCheckVisibility.isVisible && RmsIsLoudEnough())
{
if (_jawState != JawStates.Talking)
JawTalking();
}
else
{
if (_jawState != JawStates.Default)
JawShut();
}
}
}
void JawTalking()
{
jawState = JawStates.Talking;
// Insert your "jaw is now talking" animation/tweening logic here. I did a simple pingponging tween of the LocalRotation of the jaw transform.
}
void JawShut()
{
jawState = JawStates.Default;
// Insert your "jaw shuts" animation/tween logic here. I did a simple one-time quick tween of the LocalRotation of the jaw transform to shut and stay shut.
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment