- Home /
Character Movement jitters
The characters moves but its very jitter, like he starts and stops. I bought an asset and it's just not working well.
Heres the code below
//An enchanced version of the unity's character motor from the standard assets
#pragma strict
#pragma implicit
#pragma downcast
var crouchLayerMask : LayerMask;
var fixedUpdate : boolean = true;
var canControl : boolean = true;
var canCrouch : boolean = true;
@System.NonSerialized
var inputMoveDirection : Vector3 = Vector3.zero;
@System.NonSerialized
var inputJump : boolean = false;
@System.NonSerialized
var running : boolean;
@System.NonSerialized
var crouch : boolean = false;
class CharacterMotorMovement{
var maxForwardSpeed : float = 2.0;
var maxRunSpeed : float = 3.5;
var maxStamina : float = 7.0;//1 = 1 second of running
@System.NonSerialized
var staminaLeft : float;
var maxCrouchSpeed : float = 1.0;
var slopeSpeedMultiplier : AnimationCurve = AnimationCurve(Keyframe(-90, 1), Keyframe(0, 1), Keyframe(90, 0));
var maxGroundAcceleration : float = 30.0;
var maxAirAcceleration : float = 20.0;
var gravity : float = 10.0;
var maxFallSpeed : float = 20.0;
@System.NonSerialized
var collisionFlags : CollisionFlags;
@System.NonSerialized
var velocity : Vector3;
@System.NonSerialized
var frameVelocity : Vector3 = Vector3.zero;
@System.NonSerialized
var hitPoint : Vector3 = Vector3.zero;
@System.NonSerialized
var lastHitPoint : Vector3 = Vector3(Mathf.Infinity, 0, 0);
}
var movement : CharacterMotorMovement = CharacterMotorMovement();
enum MovementTransferOnJump{
None, // The jump is not affected by velocity of floor at all.
InitTransfer, // Jump gets its initial velocity from the floor, then gradualy comes to a stop.
PermaTransfer, // Jump gets its initial velocity from the floor, and keeps that velocity until landing.
PermaLocked // Jump is relative to the movement of the last touched floor and will move together with that floor.
}
class CharacterMotorJumping{
var enabled : boolean = true;
var baseHeight : float = 1.0;
//var extraHeight : float = 4.1;
var perpAmount : float = 0.0;
var steepPerpAmount : float = 0.5;
// For the next variables, @System.NonSerialized tells Unity to not serialize the variable or show it in the inspector view.
// Very handy for organization!
@System.NonSerialized
var jumping : boolean = false;
@System.NonSerialized
var holdingJumpButton : boolean = false;
@System.NonSerialized
var lastStartTime : float = 0.0;
@System.NonSerialized
var lastButtonDownTime : float = -100;
@System.NonSerialized
var jumpDir : Vector3 = Vector3.up;
}
var jumping : CharacterMotorJumping = CharacterMotorJumping();
class CharacterMotorMovingPlatform{
var enabled : boolean = true;
var movementTransfer : MovementTransferOnJump = MovementTransferOnJump.PermaTransfer;
@System.NonSerialized
var hitPlatform : Transform;
@System.NonSerialized
var activePlatform : Transform;
@System.NonSerialized
var activeLocalPoint : Vector3;
@System.NonSerialized
var activeGlobalPoint : Vector3;
@System.NonSerialized
var activeLocalRotation : Quaternion;
@System.NonSerialized
var activeGlobalRotation : Quaternion;
@System.NonSerialized
var lastMatrix : Matrix4x4;
@System.NonSerialized
var platformVelocity : Vector3;
@System.NonSerialized
var newPlatform : boolean;
}
var movingPlatform : CharacterMotorMovingPlatform = CharacterMotorMovingPlatform();
class CharacterMotorSliding{
var enabled : boolean = true;
var slidingSpeed : float = 15;
var sidewaysControl : float = 1.0;
// How much can the player influence the sliding speed?
// If the value is 0.5 the player can speed the sliding up to 150% or slow it down to 50%.
var speedControl : float = 0.4;
}
var sliding : CharacterMotorSliding = CharacterMotorSliding();
@System.NonSerialized
var grounded : boolean = true;
@System.NonSerialized
var groundNormal : Vector3 = Vector3.zero;
@System.NonSerialized
var fallDamage : float;
@System.NonSerialized
var normalWalkSpeed : float;
private var lastGroundNormal : Vector3 = Vector3.zero;
private var Tran : Transform;
private var controller : CharacterController;
private var gameController : GameObject;
function Awake(){
Tran = transform;
controller = GetComponent(CharacterController);
normalWalkSpeed = movement.maxForwardSpeed;
gameController = GameObject.FindGameObjectWithTag("GameController");
movement.staminaLeft = movement.maxStamina;
}
private function UpdateFunction(){
var velocity : Vector3 = movement.velocity;
velocity = ApplyInputVelocityChange(velocity);
velocity = ApplyGravityAndJumping (velocity);
var moveDistance : Vector3 = Vector3.zero;
if(MoveWithPlatform()){
var newGlobalPoint : Vector3 = movingPlatform.activePlatform.TransformPoint(movingPlatform.activeLocalPoint);
moveDistance = (newGlobalPoint - movingPlatform.activeGlobalPoint);
if(moveDistance != Vector3.zero)
controller.Move(moveDistance);
var newGlobalRotation : Quaternion = movingPlatform.activePlatform.rotation * movingPlatform.activeLocalRotation;
var rotationDiff : Quaternion = newGlobalRotation * Quaternion.Inverse(movingPlatform.activeGlobalRotation);
var yRotation = rotationDiff.eulerAngles.y;
if(yRotation != 0){
Tran.Rotate(0, yRotation, 0);
}
}
var lastPosition : Vector3 = Tran.position;
var currentMovementOffset : Vector3 = velocity * Time.deltaTime;
var pushDownOffset : float = Mathf.Max(controller.stepOffset, Vector3(currentMovementOffset.x, 0, currentMovementOffset.z).magnitude);
if(grounded)
currentMovementOffset -= pushDownOffset * Vector3.up;
movingPlatform.hitPlatform = null;
groundNormal = Vector3.zero;
movement.collisionFlags = controller.Move (currentMovementOffset);
movement.lastHitPoint = movement.hitPoint;
lastGroundNormal = groundNormal;
if(movingPlatform.enabled && movingPlatform.activePlatform != movingPlatform.hitPlatform){
if(movingPlatform.hitPlatform != null){
movingPlatform.activePlatform = movingPlatform.hitPlatform;
movingPlatform.lastMatrix = movingPlatform.hitPlatform.localToWorldMatrix;
movingPlatform.newPlatform = true;
}
}
var oldHVelocity : Vector3 = new Vector3(velocity.x, 0, velocity.z);
movement.velocity = (Tran.position - lastPosition) / Time.deltaTime;
var newHVelocity : Vector3 = new Vector3(movement.velocity.x, 0, movement.velocity.z);
if(oldHVelocity == Vector3.zero){
movement.velocity = new Vector3(0, movement.velocity.y, 0);
}
else{
var projectedNewVelocity : float = Vector3.Dot(newHVelocity, oldHVelocity) / oldHVelocity.sqrMagnitude;
movement.velocity = oldHVelocity * Mathf.Clamp01(projectedNewVelocity) + movement.velocity.y * Vector3.up;
}
if(movement.velocity.y < velocity.y - 0.001){
if(movement.velocity.y < 0)
movement.velocity.y = velocity.y;
else
jumping.holdingJumpButton = false;
}
if(grounded && !IsGroundedTest()){
grounded = false;
if(movingPlatform.enabled && (movingPlatform.movementTransfer == MovementTransferOnJump.InitTransfer || movingPlatform.movementTransfer == MovementTransferOnJump.PermaTransfer)){
movement.frameVelocity = movingPlatform.platformVelocity;
movement.velocity += movingPlatform.platformVelocity;
}
SendMessage("OnFall", SendMessageOptions.DontRequireReceiver);
Tran.position += pushDownOffset * Vector3.up;
}
else if(!grounded && IsGroundedTest()){
grounded = true;
jumping.jumping = false;
SubtractNewPlatformVelocity();
SendMessage("OnLand", SendMessageOptions.DontRequireReceiver);
}
if(MoveWithPlatform()){
movingPlatform.activeGlobalPoint = Tran.position + Vector3.up * (controller.center.y - controller.height * 0.5 + controller.radius);
movingPlatform.activeLocalPoint = movingPlatform.activePlatform.InverseTransformPoint(movingPlatform.activeGlobalPoint);
movingPlatform.activeGlobalRotation = Tran.rotation;
movingPlatform.activeLocalRotation = Quaternion.Inverse(movingPlatform.activePlatform.rotation) * movingPlatform.activeGlobalRotation;
}
}
function FixedUpdate(){
if(fixedUpdate)
UpdateFunction();
if(!grounded)
fallDamage -= Time.fixedDeltaTime * controller.velocity.y * 10;
if(Input.GetButton("Crouch") && canCrouch){
if(!crouch){
movement.maxForwardSpeed = movement.maxCrouchSpeed;
running = false;
crouch = true;
}
if(controller.height > 0.8)
controller.height -= Time.fixedDeltaTime * 2.5;
}
else{
if(controller.height < 1.8){
var hit : RaycastHit;
if(!Physics.CapsuleCast(Tran.position, Tran.position, controller.radius, Tran.up, hit, 1.8f, crouchLayerMask))
controller.height += Time.fixedDeltaTime * 2;
}
else if(controller.height >= 1.8){
if(crouch){
movement.maxForwardSpeed = normalWalkSpeed;
crouch = false;
}
}
}
if(controller.center.y != controller.height / 2)
controller.center.y = controller.height / 2;
if(controller.height < 0.8 || controller.height > 1.8)
controller.height = Mathf.Clamp(controller.height, 0.8, 1.8);
if(movingPlatform.enabled){
if(movingPlatform.activePlatform != null){
if(!movingPlatform.newPlatform){
var lastVelocity : Vector3 = movingPlatform.platformVelocity;
movingPlatform.platformVelocity = (movingPlatform.activePlatform.localToWorldMatrix.MultiplyPoint3x4(movingPlatform.activeLocalPoint) - movingPlatform.lastMatrix.MultiplyPoint3x4(movingPlatform.activeLocalPoint)) / Time.deltaTime;
}
movingPlatform.lastMatrix = movingPlatform.activePlatform.localToWorldMatrix;
movingPlatform.newPlatform = false;
}
else{
movingPlatform.platformVelocity = Vector3.zero;
}
}
if(controller.isGrounded){
if(controller.velocity.magnitude > 0.2){
if(running)
movement.staminaLeft -= Time.fixedDeltaTime;
else
movement.staminaLeft += Time.fixedDeltaTime / 3;
}
else
movement.staminaLeft += Time.fixedDeltaTime * 3;
}
movement.staminaLeft = Mathf.Clamp(movement.staminaLeft, 0, movement.maxStamina);
gameController.SendMessage("ApplyStaminaLeft", movement.staminaLeft / movement.maxStamina, SendMessageOptions.DontRequireReceiver);
}
function Update(){
if(!fixedUpdate)
UpdateFunction();
if(grounded){
if(fallDamage > 30)
SendMessageUpwards("ApplyFallDamage", fallDamage - 30, SendMessageOptions.DontRequireReceiver);
fallDamage = 0;
}
if(!crouch){
if(Input.GetButtonDown("Run")){
running = true;
movement.maxForwardSpeed = movement.maxRunSpeed;
}
else if(Input.GetButtonUp("Run") || movement.staminaLeft <= 0){
running = false;
movement.maxForwardSpeed = normalWalkSpeed;
}
}
var directionVector = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
if(directionVector != Vector3.zero){
var directionLength = directionVector.magnitude;
directionVector = directionVector / directionLength;
directionLength = Mathf.Min(1, directionLength);
directionLength = directionLength * directionLength;
directionVector = directionVector * directionLength;
}
inputMoveDirection = Tran.rotation * directionVector;
inputJump = Input.GetButton("Jump");
}
private function ApplyInputVelocityChange(velocity : Vector3){
if(!canControl)
inputMoveDirection = Vector3.zero;
var desiredVelocity : Vector3;
if(grounded && TooSteep()){
desiredVelocity = Vector3(groundNormal.x, 0, groundNormal.z).normalized;
var projectedMoveDir = Vector3.Project(inputMoveDirection, desiredVelocity);
desiredVelocity = desiredVelocity + projectedMoveDir * sliding.speedControl + (inputMoveDirection - projectedMoveDir) * sliding.sidewaysControl;
desiredVelocity *= sliding.slidingSpeed;
}
else
desiredVelocity = GetDesiredHorizontalVelocity();
if(movingPlatform.enabled && movingPlatform.movementTransfer == MovementTransferOnJump.PermaTransfer){
desiredVelocity += movement.frameVelocity;
desiredVelocity.y = 0;
}
if(grounded)
desiredVelocity = AdjustGroundVelocityToNormal(desiredVelocity, groundNormal);
else
velocity.y = 0;
// Enforce max velocity change
var maxVelocityChange : float = GetMaxAcceleration(grounded) * Time.deltaTime;
var velocityChangeVector : Vector3 = (desiredVelocity - velocity);
if(velocityChangeVector.sqrMagnitude > maxVelocityChange * maxVelocityChange){
velocityChangeVector = velocityChangeVector.normalized * maxVelocityChange;
}
if(grounded || canControl)
velocity += velocityChangeVector;
if(grounded){
velocity.y = Mathf.Min(velocity.y, 0);
}
return velocity;
}
private function ApplyGravityAndJumping(velocity : Vector3){
if(!inputJump || !canControl){
jumping.holdingJumpButton = false;
jumping.lastButtonDownTime = -100;
}
if(inputJump && jumping.lastButtonDownTime < 0 && canControl)
jumping.lastButtonDownTime = Time.time;
if(grounded)
velocity.y = Mathf.Min(0, velocity.y) - movement.gravity * Time.deltaTime;
else{
velocity.y = movement.velocity.y - movement.gravity * Time.deltaTime;
/*if(jumping.jumping && jumping.holdingJumpButton){
if(Time.time < jumping.lastStartTime + jumping.extraHeight / CalculateJumpVerticalSpeed(jumping.baseHeight)){
velocity += jumping.jumpDir * movement.gravity * Time.deltaTime;
}
}*/
velocity.y = Mathf.Max(velocity.y, -movement.maxFallSpeed);
}
if(grounded){
if(jumping.enabled && canControl && !crouch && (Time.time - jumping.lastButtonDownTime < 0.2)){
grounded = false;
jumping.jumping = true;
jumping.lastStartTime = Time.time;
jumping.lastButtonDownTime = -100;
jumping.holdingJumpButton = true;
if(TooSteep())
jumping.jumpDir = Vector3.Slerp(Vector3.up, groundNormal, jumping.steepPerpAmount);
else
jumping.jumpDir = Vector3.Slerp(Vector3.up, groundNormal, jumping.perpAmount);
velocity.y = 0;
velocity += jumping.jumpDir * CalculateJumpVerticalSpeed(jumping.baseHeight);
if(movingPlatform.enabled && (movingPlatform.movementTransfer == MovementTransferOnJump.InitTransfer || movingPlatform.movementTransfer == MovementTransferOnJump.PermaTransfer)){
movement.frameVelocity = movingPlatform.platformVelocity;
velocity += movingPlatform.platformVelocity;
}
}
else{
jumping.holdingJumpButton = false;
}
}
return velocity;
}
function OnControllerColliderHit (hit : ControllerColliderHit){
if(hit.normal.y > 0 && hit.normal.y > groundNormal.y && hit.moveDirection.y < 0){
if((hit.point - movement.lastHitPoint).sqrMagnitude > 0.001 || lastGroundNormal == Vector3.zero)
groundNormal = hit.normal;
else
groundNormal = lastGroundNormal;
movingPlatform.hitPlatform = hit.collider.transform;
movement.hitPoint = hit.point;
movement.frameVelocity = Vector3.zero;
}
}
private function SubtractNewPlatformVelocity(){
if(movingPlatform.enabled && (movingPlatform.movementTransfer == MovementTransferOnJump.InitTransfer || movingPlatform.movementTransfer == MovementTransferOnJump.PermaTransfer)){
if(movingPlatform.newPlatform){
var platform : Transform = movingPlatform.activePlatform;
yield WaitForFixedUpdate();
yield WaitForFixedUpdate();
if(grounded && platform == movingPlatform.activePlatform)
yield 1;
}
movement.velocity -= movingPlatform.platformVelocity;
}
}
private function MoveWithPlatform() : boolean{
return(
movingPlatform.enabled
&& (grounded || movingPlatform.movementTransfer == MovementTransferOnJump.PermaLocked)
&& movingPlatform.activePlatform != null);
}
private function GetDesiredHorizontalVelocity(){
var desiredLocalDirection : Vector3 = Tran.InverseTransformDirection(inputMoveDirection);
var maxSpeed : float = MaxSpeedInDirection(desiredLocalDirection);
if(grounded){
var movementSlopeAngle = Mathf.Asin(movement.velocity.normalized.y) * Mathf.Rad2Deg;
maxSpeed *= movement.slopeSpeedMultiplier.Evaluate(movementSlopeAngle);
}
return Tran.TransformDirection(desiredLocalDirection * maxSpeed);
}
private function AdjustGroundVelocityToNormal(hVelocity : Vector3, groundNormal : Vector3) : Vector3{
var sideways : Vector3 = Vector3.Cross(Vector3.up, hVelocity);
return Vector3.Cross(sideways, groundNormal).normalized * hVelocity.magnitude;
}
private function IsGroundedTest(){
return(groundNormal.y > 0.01);
}
function GetMaxAcceleration(grounded : boolean) : float{
if(grounded)
return movement.maxGroundAcceleration;
else
return movement.maxAirAcceleration;
}
function CalculateJumpVerticalSpeed(targetJumpHeight : float){
return Mathf.Sqrt(2 * targetJumpHeight * movement.gravity);
}
function IsJumping(){
return jumping.jumping;
}
function IsSliding(){
return(grounded && sliding.enabled && TooSteep());
}
function IsTouchingCeiling(){
return(movement.collisionFlags & CollisionFlags.CollidedAbove) != 0;
}
function IsGrounded(){
return grounded;
}
function TooSteep(){
return(groundNormal.y <= Mathf.Cos(controller.slopeLimit * Mathf.Deg2Rad));
}
function GetDirection(){
return inputMoveDirection;
}
function SetControllable(controllable : boolean){
canControl = controllable;
}
function MaxSpeedInDirection(desiredMovementDirection : Vector3) : float{
if(desiredMovementDirection == Vector3.zero)
return 0;
else{
var zAxisEllipseMultiplier : float = (desiredMovementDirection.z > 0 ? movement.maxForwardSpeed : movement.maxForwardSpeed) / movement.maxForwardSpeed;
var temp : Vector3 = new Vector3(desiredMovementDirection.x, 0, desiredMovementDirection.z / zAxisEllipseMultiplier).normalized;
var length : float = new Vector3(temp.x, 0, temp.z * zAxisEllipseMultiplier).magnitude * movement.maxForwardSpeed;
return length;
}
}
function SetVelocity(velocity : Vector3){
grounded = false;
movement.velocity = velocity;
movement.frameVelocity = Vector3.zero;
}
function ResetFallDamage(){
fallDamage = 0;
}
That's millions of lines of code for us to read. ;-)
You should better post only the relevant code related to your problem.
I think you have taken the comments on questions of others 'please post your code' quite seriously :-P
Answer by YoungDeveloper · Jun 30, 2014 at 10:58 AM
Nobody will read that long piece of a code, but let me give you reasons it's hapenning.
Your player and/or camera movement is executed in FixedUpdate(), which doesn't run every frame
Move/Update player and/or camera last, after every script has finished Update(), for that use LateUpdate()
Try smoothing out player/camera movement using Lerp, no movetowards or translate.
Your answer
Follow this Question
Related Questions
A node in a childnode? 1 Answer
Alternative of touchesMoved in Unity3D 0 Answers
Character Rotation 2 Answers
C# Twitchy Camera Movement 1 Answer
Scenario connection Problem 0 Answers