Hi.
Is there a way in Unity 4, to check if a foot has touched the ground? Maybe through the Foot IK feature in mecanim?
Thanks!
Hi.
Is there a way in Unity 4, to check if a foot has touched the ground? Maybe through the Foot IK feature in mecanim?
Thanks!
I would suggest that you use the Curves function and in the Preview when the foot hits the ground then set the curve to 1 and other than that set it to 0 just prior and just after. When a variable is compared and it is equivalent to 1 or greater than 0.95 for example then set the audio to play once. This way the Curve drives the sound and can be set visually.
Hello people, I solved the problem of footstep sound timing like this…
I attached an empty gameOject to each foot, gave it an audio source, a small sphere collider (make it a trigger) and made it rigidbody. Positioned them so half the collider
is sticking out the sole of the characters feet just behind toes.
In the walk and run animations I created float curves that go above 0.01 when left foot is at full forward swing point then back to 0 just after foot has touched the ground. For the right foot the float curve goes below -0.01 when its full forward etc.
I use the float curve to make sure the foot has passed the point where it skims the ground in middle of forward swing. (Stops it playing unwanted foot steps sounds at that point)
A copy of the java script is bellow.
Doing it like this means footsteps will all ways be in time regardless of walk/running speed and you don’t need to check character is grounded.
And each foot will play the correct sound if for example left foot is on a rug and right is on wood floorboard or stepping on a metal man hole cover on a pavement.
Tag each ground surface for its relevant sound.
Attach script to gameobject on left foot make a duplicate(name 1 leftfoot the other rightfoot) and change anim.GetFloat(“footSteps”)>0.01) to
anim.GetFloat(“footSteps”)<-0.01) in each line its in.
public var anim : Animator;
public var footstepGravel : AudioClip[];
public var footstepForest : AudioClip[];
public var footstepWood : AudioClip[];
public var footstepMetal : AudioClip[];
public var footstepCarpet : AudioClip[];
function Start()
{
anim = GameObject.Find("Main_Char").GetComponent(Animator);
}
function OnTriggerEnter (col : Collider)
{
if(col.gameObject.tag == "Gravel" && anim.GetFloat("footSteps")>0.01)
{
audio.PlayOneShot(footstepGravel[Random.Range(0,footstepGravel.Length)]);
}
else if(col.gameObject.tag == "Forest" && anim.GetFloat("footSteps")>0.01)
{
audio.PlayOneShot(footstepForest[Random.Range(0,footstepForest.Length)]);
}
else if(col.gameObject.tag == "Wood" && anim.GetFloat("footSteps")>0.01)
{
audio.PlayOneShot(footstepWood[Random.Range(0,footstepWood.Length)]);
}
else if(col.gameObject.tag == "Metal" && anim.GetFloat("footSteps")>0.01)
{
audio.PlayOneShot(footstepMetal[Random.Range(0,footstepMetal.Length)]);
}
else if(col.gameObject.tag == "Carpet" && anim.GetFloat("footSteps")>0.01)
{
audio.PlayOneShot(footstepCarpet[Random.Range(0,footstepCarpet.Length)]);
}
}
Use Animation Events
http://docs.unity3d.com/Documentation/Components/animeditor-AnimationEvents.html
Use animator.pivotPosition which keeps changing positions with left foot to right foot. I’ve written a script for it:
public class FootstepsController : MonoBehaviour {
private Animator animator;
private AudioSource audioSource;
// Use this for initialization
void Start () {
animator = GetComponent<Animator> ();
audioSource = GetComponent<AudioSource>();
}
bool isLeftFootAhead;
bool playedLeftFoot;
bool playedRightFoot;
// Update is called once per frame
void Update () {
//Check if character is grunded
if (animator.GetBool ("OnGround") == false)
return;
//we don't want to trigger the footsteps when not moving
if (animator.velocity.magnitude < 0.2f)
return;
//Left Foot distance between the pivot position and the left foot
if (Vector3.Distance (leftFootIKPos, animator.pivotPosition) <= 0.15f && playedLeftFoot == false) {
PlayFootStep();
playedLeftFoot = true;
playedRightFoot = false;
}
//RightFoot
if (Vector3.Distance (rightFootIKPos, animator.pivotPosition) <= 0.15f && playedRightFoot == false) {
PlayFootStep();
playedRightFoot = true;
playedLeftFoot = false;
}
}
void PlayFootStep()
{
//AudioSource.PlayClipAtPoint (SoundBank.footstep, transform.position);
audioSource.PlayOneShot (SoundBank.footstep);
}
Vector3 leftFootIKPos;
Vector3 rightFootIKPos;
//Here the animator will give us the position of the left foot and right foot
void OnAnimatorIK()
{
leftFootIKPos = animator.GetIKPosition (AvatarIKGoal.LeftFoot);
rightFootIKPos = animator.GetIKPosition (AvatarIKGoal.RightFoot);
}
void OnDrawGizmos()
{
if (animator == null)
return;
Gizmos.DrawSphere (animator.pivotPosition, 0.1f);
}
}