How to fix inconsistency in Pitch Shifting using an animation in Unity 2019.1.0f2

Viewed 229

I have an animation of a car driving along a road and I'm trying to adjust the pitch of an engine sound through the Audio Source component. The issue is that each time I run my application in the unity editor the pitch values spike and are inconsistent between plays.

This is for C# and Unity3d. I'm attempting to average the pitch based on the three most recent frames and clamping the pitch values between 1 and 3. When I average the pitch I then make sure it is within a maxDifference threshold to combat the spikes that have been occurring. The animation is not based on root motion so I can't use the Animation Velocity fields. To fix this, I'm calculating the distance traveled over a frame using the X and Z position of the current frame and the last frame inputted into the distance formula. I'm then multiplying that value by a scaling number to determine what my pitch values should be close to. That value is able to be changed through the editor and the value I've used most is 12.

public float scaler;

[Range(0, 0.7f)]
public float maxDifference;
public Animator anim;
public AudioSource audiosource;

Vector3 lastPos;
float lastPitch;
float lastPitch2;
float lastPitch3;  

var position = transform.position;

float deltaPosition = Mathf.Abs(Mathf.Sqrt(Mathf.Pow((lastPos.z - position.z), 2) + Mathf.Pow((lastPos.x - position.x), 2)));
audiosource.pitch = deltaPosition * scaler + 1;

if (audiosource.pitch < 1)
{
    audiosource.pitch = 1;
}

if (Mathf.Abs(audiosource.pitch - (lastPitch + lastPitch2 + lastPitch3) / 3f) > maxDifference 
    && !carStart)
{
    audiosource.pitch = (lastPitch + lastPitch2 + lastPitch3) / 3f;
}

if (audiosource.pitch > 3f)
    audiosource.pitch = 3f;

lastPos = position;
lastPitch3 = lastPitch2;
lastPitch2 = lastPitch;
lastPitch = audiosource.pitch;

I've expected consistent pitch values but each time I run it, the values change each time. The values also spike constantly.

1 Answers

When the current pitch goes too far away from the trailing average, you should clamp it to some distance from the trailing average, not set it to the trailing average exactly.

To simplify things, you can use Mathf.Clamp:

audiosource.pitch = Mathf.Clamp(deltaPosition * scaler + 1, 1f, 3f); 

float runningAverage = (lastPitch + lastPitch2 + lastPitch3) / 3f;
if (!carStart) 
{ 
    audiosource.pitch = Mathf.Clamp(audiosource.pitch, 
                                    runningAverage - maxDifference,
                                    runningAverage + maxDifference); 
} 

lastPos = this.transform.position; 

lastPitch3 = lastPitch2; 
lastPitch2 = lastPitch; 
lastPitch = audiosource.pitch;
Related