- Home /
Basic Character Movement
As generic as it sounds, I haven't seen an example yet demonstrating moving a character, having the character face the direction it is moving, and giving it the ability to jump without be directed to the 3rd Person Tutorial.
UA reader: "Why don't u just use the third person Lerpz scirpt? it easy and has all that?"
My Answer: "Because it includes a lot of things I don't need, and it acts a bit weird on slopes regardless of the settings."
So, I wrote up a script for movement and tried to set up rotation and jumping. I have the movement working, but orienting the player to the direction it is going is acting funny. It updates right when you're moving, but as soon as you stop, it will face an totally different direction.
Also, I set up jumping (which works while moving) but if you are moving diagonally using WASD and try to jump, he won't jump while pressing WA or WD or SA or SD. Weird thing is, it works using the arrow keys with no problem.
The last part is the animation scheme. Should I use flags such as animate when the velocity is at a certain point or something?
function UpdateMovementDirection() { var horizontalVelocity : Vector3 = character.velocity; horizontalVelocity.y = 0; // Ignore vertical movement
// If moving significantly in a new direction, point that character in that direction
if ( horizontalVelocity.magnitude > 0.01)
thisTransform.rotation = Quaternion.Slerp(thisTransform.rotation, Quaternion.LookRotation(character.velocity), Time.deltaTime * rotationDamping);
}
function Update() { var x = Input.GetAxis("Horizontal"); var z = Input.GetAxis("Vertical");
var movement = Vector3( x, 0, z );
movement.y = 0;
//movement.Normalize(); // Adjust magnitude after ignoring vertical movement
movement *= speed;
// Check for jump
if ( character.isGrounded )
{
canJump = true;
if ( canJump && Input.GetKeyDown("space") )
{
// Apply the current movement to launch velocity
velocity = character.velocity;
velocity.y = jumpSpeed;
canJump = false;
}
}
else
{
// Apply gravity to our velocity to diminish it over time
velocity.y += Physics.gravity.y * Time.deltaTime;
// Adjust additional movement while in-air
movement.x *= inAirMultiplier;
movement.z *= inAirMultiplier;
}
movement += velocity;
movement += Physics.gravity;
movement *= Time.deltaTime;
UpdateMovementDirection();
// Actually move the character
character.Move( movement);
if ( character.isGrounded )
// Remove any persistent velocity after landing
velocity = Vector3.zero;
}`
I'm having trouble with this script, it works for turning the character to face the direction it's moving, but when you jump, as soon as you let go of the direction key the character falls straight down. There is no horizontal momentum in the air so it's totally unnatural looking. Anyone know how to fix this? I've tried various things but no luck :(
Answer by SirGive · May 13, 2011 at 06:26 AM
EDIT:
To clarify: SirVictory and I were working on this script together. I did not write this completely by myself nor just on a whim.
Hey SirVictory,
I finished cleaning up this code that we were working on. Here is a very basic movement script without sections for animation. I left movement speed in there as a variable for the walking animation, so if you (or anyone else) wants to add animation transitions that would be a great place to start. Just base the scale of the animation on the moveSpeed. Here it is (in c#):
using UnityEngine; using System.Collections;
// Require a character controller to be attached to the same game object [RequireComponent(typeof (CharacterController))] [AddComponentMenu("Third Person Player/Third Person Controller")]
public class Movement : MonoBehaviour {
public float rotationDamping = 20f;
public float runSpeed = 10f;
public int gravity = 20;
public float jumpSpeed = 8;
bool canJump;
float moveSpeed;
float verticalVel; // Used for continuing momentum while in air
CharacterController controller;
void Start()
{
controller = (CharacterController)GetComponent(typeof(CharacterController));
}
float UpdateMovement()
{
// Movement
float x = Input.GetAxis("Horizontal");
float z = Input.GetAxis("Vertical");
Vector3 inputVec = new Vector3(x, 0, z);
inputVec *= runSpeed;
controller.Move((inputVec + Vector3.up * -gravity + new Vector3(0, verticalVel, 0)) * Time.deltaTime);
// Rotation
if (inputVec != Vector3.zero)
transform.rotation = Quaternion.Slerp(transform.rotation,
Quaternion.LookRotation(inputVec),
Time.deltaTime * rotationDamping);
return inputVec.magnitude;
}
void Update()
{
// Check for jump
if (controller.isGrounded )
{
canJump = true;
if ( canJump && Input.GetKeyDown("space") )
{
// Apply the current movement to launch velocity
verticalVel = jumpSpeed;
canJump = false;
}
}else
{
// Apply gravity to our velocity to diminish it over time
verticalVel += Physics.gravity.y * Time.deltaTime;
}
// Actually move the character
moveSpeed = UpdateMovement();
if ( controller.isGrounded )
verticalVel = 0f;// Remove any persistent velocity after landing
}
}
Wow, this actually works really well! Thanks for the help!
Would this script be added to the character itself? cuz i tried copying it and none of the keys do anyway thing. please tell me if there is a problem. thnx :)
Answer by Owen-Reynolds · May 12, 2011 at 11:33 PM
If you use speed to set facing, then of course stopping == speed 0, so no facing. Here are the key parts of mine (C#):
float facing = 0.0f; // angle (degrees) we are facing public float turnSpeed = 120f; // degs/sec
public float speed = 20.0f;
public void FixedUpdate () { .... // L/R arrows turn us: facing += Input.GetAxis("Horizontal")*turnSpeed*Time.deltaTime; transform.rotation = Quaternion.Euler(0, facing, 0);
// since facing is set, we always move "forward": moveDirection = transform.forward mvSpd speed; .... }
Did you look at his script? He's moving the character in two directions. Your script use a rotation in the first place and your movement is applied locally, relative to your character, but he moves the character absolutely and wants to calculate the rotation. It's the other way round.
The problem is that using WASD for moving in any direction isn't possible. You can only get sustained motion in one of 8 directions. If you want to move directly towards an arbitrary point, you have to jiggle between | and /. Actually facing the way you move is only for NPCs or "click on ground to move" players. Plus, seeing canJump = true; if ( canJump
kind of worried me.
Answer by Bunny83 · May 13, 2011 at 02:16 AM
Well, i guess your problem could be that you set up horizontalVelocity
but you use character.velocity
to create your Quaternion.
if ( horizontalVelocity.magnitude > 0.01)
thisTransform.rotation = Quaternion.Slerp(thisTransform.rotation, Quaternion.LookRotation(horizontalVelocity), Time.deltaTime * rotationDamping);
That should eleminate your rotation problem, if not, try to increase your 0.01 limit a bit but it should be fine.
Your jumping issue seems to be hardware-related ;) there's not much you can do about that. I have only two solutions:
- Use another key to jump that isn't part of the same grid-line on your keyboard.
- Buy a keyboard that has a different pcb-layout.
WASD was actually chosen because those buttons normaly lay on different conducting paths so you can press them simultaneously.
You can try that in any text editor. just press W+A and hold them down, if you press space and no space is written it's definitely your keyboard ;)
Just tried it on my keyboard W+A or W+D works but S+A or S+D blocks the space bar, at least on my keyboard ;).
That's actually the advantage of console-controllers. If they have 16 buttons you can press them all at once.
I don't get your last part. What animations? What flags or for what purpose? Do you want to know when you should play your animations?
Thats a great explanation. I kinda thought it was a hardware thing. I wonder how I can get around this.
Answer by visakh123 · Apr 23, 2014 at 08:44 AM
please check out this link
http://answers.unity3d.com/questions/692807/how-to-make-character-run-along-a-slope-road-in-un.html