Best way to handle animations on my top-down shooter setup?

I’ve been mulling over this for about an hour now, and can’t think of a solution.

I have a top-down shooter prototype set up where the root object of the character has the CharacterMotor/Controller, and FPSWalker script on it. The character model itself (with the animations) is a child of this, with a LookAtMouse script on it (this is the only way I could figure out how to do the traditional top-down shooter/twin stick control setup, where you can look/shoot in one direction and move in another). The camera is simply in the scene, with a script that targets the player object, and looks at it from an offset above.

My problem is, I have 4 animations: run, two 45 degree angle runs (running at an angle both left and right), and two side-run animations (left and right). I can’t for the life of me figure out how I should determine which animations to play and when.

I was going to try basing them off of normalizing the character controller velocity.x and z, but that would only work if it was the character controller was also the object with my LookAtMouse, and if I do that, the controls get all backwards when you’re looking in the wrong direction.

Obviously I can’t just base them on the horizontal/vertical input axes, because you could, for example, be moving forward with the vertical input axis but looking in a different direction.

I’m not 100% sure how your control system works, but I think you can choose the animation based on the dot product of the camera’s and character’s forward direction vectors. The result will be close to 1 if the camera is looking in roughly the direction the character is going (forward run anim), close to 0.75 if it is looking diagonally (diagonal run anim) and close to 0 if it is looking sideways. If you don’t have any additional information to go on then you can tell whether to choose left or right using the technique in this thread:-

var dot = Vector3.Dot(transform.foward, cam.transform.forward);

if (dot < 0.5) {
  // Sideways.
} else if (dot > 0.5  dot < 0.87) {
  // Diagonal.
} else {
  // Forward.
}

If the result of the dot product is negative then it implies the character should be going backwards (maybe diagonally) if that is possible in your game.

Thanks for the response, Andeeee.

In my situation, the camera is fixed above the player pointing down, and follows him, but never rotates. Here is a gameplay video of alien swarm showing what i’m trying to replicate: http://www.youtube.com/watch?v=VJ-tGVfVve0

The camera is fixed above the player, pointing down… The player object moves forward/backward/left/right with FPSWalker (but it never actually rotates). The player model is parented to the player object, which always faces the mouse pointer (via LookAtMouse.js). All the weapons are parented to the player model (so that they shoot in the direction the player model is facing).

I think I can use a solution using dot products like you are, but its going to have to involve the horizontal/vertical input axes, or the x and z velocities of the character controller on the parent player object somehow.

Could I possibly somehow use Vector3.Angle with the character controller velocity Vector3 of the parent object, and the transform.forward of the player model (the child object that always faces the mouse)?

couple of ideas.

Have the character have a few basic controls. Left, right, up and down. Left and right are strafe,up is run forward, down is step backward.

The animations are basically linked to those. For those you have a few more animations per direction. So you have an animations for firing in those directions throwing a grenade in those directions and so on.

You should then base your facing on the mouse’s position on the screen. This can be done by using a plane and raycast from the screen and the character’s facing is then based on where the hit is in relation to him. (this can be lerp’ed) to prevent things from swinging drastically.

You should then have the camera face half way between the character and a certain distance away from him in the direction he is facing.

The whole thing should now basically work in a circle, if your mouse is on the left side of the screen, your character should be on the right of the circle facing left.

Next, to make things run a little easier you can have him target things vertically in that direction. So if you are walking down stairs, and shooting, he will automatically target the guy on the lower plane rather than force the player to rush oncoming enemies.

Couple of concepts that I was looking into myself.

Give the player a blank game object with a large circular trigger. This is connected to the OnTriggerEnter and OnTriggerExit events which manages an array. It will also need to find out if each target in the current array is still alive, (or even there) and remove it if it isn’t.

When something enters that area, you can have it target him only if he is above 0.8 or so on the dot product of his forward vector. It is a nifty concept for figuring out if something is in front and by what angle. Look at the Vector3.Dot example.

I already have my controls and combat functioning exactly as I want them, the only thing I can’t figure out is what animations to play and when.

It’s similar to what you just explained in detail, wasd moves forward/back/left/right, and the player model always faces the mouse. But in a situation like this, I can’t base the animations off of the wasd input, because “a” is not “strafe left”, its “move left”.

For instance, if i have the mouse point “north” of the player model, he is facing “north”, so yeah, hitting a would result in the player moving to the “west”, but facing “north”, so a strafing animation would be appropriate. But if the mouse cursor is to the “west” of the player model, the player is facing the “west”, so hitting a would move the player model “west” in regards to the world, but FORWARD in regards to the model’s transform(because he’s facing “west”), so I would want to play the “run forward” animation, not a strafing animation.

I do however think the solution might involve either Vector3.Angle or Vector3.Dot, though, I’ve used both before. I think if I get the dot product of the character controller velocity Vector3 and the transform.forward of the model, I can figure out if he is moving in the same direction he is facing, and figure out all other cases from there (eg: moving northwest, facing south, play strafe-right-reverse animation). I’m just not sure how yet.

I figured it out with the dot product method I just mentioned in the previous post, here’s a sneak peek :slight_smile: (still needs some tweaking)

http://www.designbyderek.net/shooter_prototype/

How did you figure this out PrimeDerektive? I’m having same problems as you were.

I am having exactly the same issue. Did either of you ever solve this? I know it’s all possible I just can’t think of a decent way to implement this.
Any help would be appreciated
Thanks
Guy

If someone is still looking for the solution here is a little snippet that I used and worked.

forwardDirection = Vector3.Dot(transform.forward, new Vector3(inputDirection.x, 0f, inputDirection.y));
rightDirection = Vector3.Dot(transform.right, new Vector3(inputDirection.x, 0f, inputDirection.y));
animator.SetFloat("vertical", forwardDirection);
animator.SetFloat("horizontal", rightDirection);

Input direction is a 2D vector based on Horizontal and Vertical axis from Unity’s Input class.

8 Likes

Thanks man!! You have saved my day!