Jump animation triggered by collide

Hey guys! Sorry for this no0b question but I’m kinda stuck.

The setup: I have an animation script that is based on input from the player. you press left = walkLeft animation. this works well for a Left-Right and also for runs and idle that activates when you don’t have any input.

But the jumps are “digital” meaning that if i press the button marked “jump” once, the character is jumping the same height as it would if you pressed and held down the button. This is causing my animation to disappear once I released the jump button ( and also give some unwanted results on the landing, IE nothing).

So working with the animation script a while, i thought it would be easier if i just accessed the CollisionFlags.Below and made the animation play depending on if the collider is hitting something below or not.

example code:

function Update ()
{
var controller : CharacterController =   GetComponent(CharacterController);
if (controller.collisionFlags  CollisionFlags.Below)
{
//If I land on something I first play the Land animation once. 
animation.wrapMode = WrapMode.Once;
animation.CrossFade("jumpLand");
}
//If I'm not standing on the ground.
else
{
//Plays these animations only once
animation.wrapMode = WrapMode.Once;
animation.CrossFade("jumpStart");
animation.PlayQueued("jumpIdle", QueueMode.CompleteOthers);

//After finishing with the start section of the jump
//the jumpFall will loop until the "if" is broken.
animation.wrapMode = WrapMode.Loop;
animation.CrossFade("jumpFall");
}
}

Now my questions are

  1. Do I need to make an For-loop to make sure the jumpStart and jumpLand will only be played once?

  2. How can I specify what CharacterController I want to use if I’m not attaching this script to the CharacterController itself?

Thanks!

Well, the easiest way to handle the jumping is to have a boolean that you set to true when you jump and set to false when you finish the landing animation. So long as it’s true, the other animations don’t do anything and let the jumping animation finish.

After that, you just need to use this on the controller that’s jumping:

OnCollisionEnter(hit : Collision)
{
   if (hit.transform.tag == "Ground") {
      animation.CrossFade("jumpFall", 1);
      yield WaitForSeconds(animation["jumpFall"].length);
      jumping = false;
   }
}

Just be sure to tag all the ground pieces “Ground.”

Thanks for the speedy reply!

But will the onCollisionEnter be able to activate the animation on mesh that somewhere else? how do i connect the animation with the Controllers collision in your script example?

thanks again!

Store the other object in a variable like:
var animTarget : Animation;

and then call it like this:
animTarget.Play();

and so forth.

In order to detect the collision, however, you HAVE to have the script on one of the objects involved in the collision. Either the character that’s running around needs it or the ground needs it.

Hi! Thanks for the advice!

I’ve now added the onCollision functions for the animation. It works but it doesn’t work exactly like i wanted to…

(BTW you Idea was great using the collide, the only problem is that you CAN collide sideways while jumping, i only want to trigger it when colliding from below.)

First off, the animation doesn’t play in the OnCollision function unless i put it in a higher layer. And I’m guessing since it is on a higher layer and alone in that layer, it has nothing to crossFade from/into? Becuase the animation snaps and does not blend.

Second, the animation loops indefinitely. Even if i use wrapmode.Once it still loops even when it has collided back to the ground. The only way for me to stop it is to make a onCollisionEnter function and stop that certain animation. And here again it snaps.

But I have an Idea that will kinda solve these problems, I would like them to be reviewed.

Statements:
(using CharacterController for movement btw)

  1. We don’t know if the player is performing a superJump or a normal jump.
  2. We don’t know when the player is landing.
  3. We know that the character is jumping while it has a positive movement (up).
  4. We know that the character is falling while it has a negative movement (down).
  5. We know that the character is on the ground while it has a no value movement up or down.

So… Lets connect the jump animations to the characterControllers velocity Y value.

function Update()
{
var MovementY = CharacterController.velocity.y
If (MovementY > 0.1)
{
animation.WrapMode.Once;
animation.CrossFade("JumpStart");
animation.WrapMode.Loop;
animation.playQueued("JumpUpIdle");
}
If (MovementY < -0.1)
{
animation.WrapMode.Loop;
animation.CrossFade("JumpFall");
}
}

This will virtually fix the jump animation for any height. Only problem is the landing part.

If i put the landing animation it in a different function,(I.E OnCollisionEnter) than the rest of the animations (jump up and fall etc) i think i must put them on a higher animation layer in order to actually play? (not sure)… Correct me if Im wrong here.

Can I detect Collision from below without going out of my “function update”?

perhaps using the
“if (controller.collisionFlags CollisionFlags.Below)” ???

thanks a million!

Yeah using the velocity.y did the trick!

but there’s still an issue of the landing animation when colliding.

I CAN get it to execute when touching the ground, but i cant make it STOP playing/looping. Even if the wrapMode is set to “Once”.

Is there a way to make the animation play once even though the collisionflag is being returned constantly?

Thanks!