Hi, I have a character controller for my guy in a 2D platformer. It can jump normally with scripted gravity pulling it down over time. However, once I either A. Hit something above the character while jumping, or B. Walk off the edge of a platform, the character seems to teleport straight to the ground below it. Please help if you can, here is the code controlling vertical movement of the character:
void Update () {
movement = Vector3.zero;
HorizontalMovement();
VerticleMovement();
movement *= Time.deltaTime;
//Add movement to CharacterController
cc.Move(movement);
if(cc.collisionFlags == CollisionFlags.CollidedAbove){
velocity.y = Vector3.zero;//if we hit something above us, stop jumping upward
}
}
void VerticleMovement(){
if(cc.isGrounded){
jumping = false;
doubleJumping = false;
velocity = Vector3.zero;//On ground, so reset velocity which is only used when in air
if(controls.jump && jumping == false){//pressed jump button
jumping = true;
velocity = cc.velocity;
velocity.y = jumpSpeed;
controls.jump = false; //reset jump controls
}
}else{//Currently falling or in the middle of jumping upwards
DoubleJump();
if(controls.jump == true)//did user press jump while already jumping?
controls.jump = false; //reset the jump
velocity.y += gravity * Time.deltaTime;//update our verticle speed
}
if(cc.collisionFlags == CollisionFlags.CollidedAbove){
velocity.y = Vector3.zero;//if we hit something above us, stop jumping upward
}
movement.y += velocity.y;//Add the updated velocity
movement.y += gravity;// * Time.deltaTime;//add the effects of gravity
}
void DoubleJump(){
if(controls.jump && !doubleJumping){
velocity = Vector3.zero;
jumping = true;
velocity = cc.velocity;
velocity.y = doubleJumpSpeed;//move upwards from last know upward velocity
controls.jump = false; //reset jump controls
doubleJumping = true;//we can't double jump again
}
}
This is probably not good ethics to do this, but no one has seem to answer you and I am pretty tired. SO I will give you my code for my own 2D platformer. I haven’t added collision for above to reset jump velocity, but you have it down anyway.
So sorry I can’t answer to your specific question.
class TwoDPlatformController ( MonoBehaviour ):
//public test = TwoDPlatformControllerJumping() Access another class will also appear in inspector
public walkSpeed as single = 6.0F
public runSpeed as single = 10.0F
public jumpSpeed as single = 8.0F
public gravity as single = 20.0F
public doubleJumpEnabled as bool= true
public extraJump as int = 1
public autoRotate as bool = true
public maxRotationSpeed as single = 360
private moveDirection as Vector3 = Vector3.zero
private curNumJump as int = 0
private curSpeed as single = 0.0F
internal jumped as bool = false
private jumpingApexReached as bool = false
private controller as CharacterController
def Update():
PlayerMovement()
HandleEvents()
def PlayerMovement ():
controller = GetComponent(CharacterController)
// While character is grounded allow to jump and horizontal movement
// Player is restricted in jump movement. One way jump if double jump disabled
if controller.isGrounded:
curNumJump = 0
jumped = false
// Assign run speed when pressing left ctrl
if Input.GetKey(KeyCode.LeftControl):
curSpeed = runSpeed
// Assign default walk speed
else:
curSpeed = walkSpeed
// Apply vector direction, only focusing on X- axis
moveDirection = Vector3( Input.GetAxis('Horizontal') * curSpeed, 0, 0 )
// If player has jumped
// Allow player to single jump while in air
// Check if player has reached jump apex, used for animation states
if hasSingleJumped():
SingleJump()
hasReachedJumpingApex()
// Player is in the air
// Allow the player the option of extra jumping, already checks if extra jumping is enabled
// Check if player has reached jump apex, used for animation states
// TODO: Future implementation, allow user to shoot while in air
else:
if hasExtraJumped():
ExtraJump()
hasReachedJumpingApex()
ApplyGravityForce()
// Apply new vector direction to the character controller
controller.Move( moveDirection * Time.deltaTime )
def SingleJump ():
// Immediately present number of allowed mid air jumps when landed
// Allow player to jump
moveDirection.y = jumpSpeed
jumped = true
def ExtraJump ():
// Allow player the capability to jump multiple times in mid air
// Number of times is based on 'extraJump'
// Once limit is reach player must land before jumping again
// When jumping horizontal movement is unlocked for that jump then it will be locked again
if curNumJump < extraJump:
moveDirection = Vector3( Input.GetAxis('Horizontal') * walkSpeed, 0, 0 )
moveDirection.y = jumpSpeed
curNumJump += 1
def ApplyGravityForce ():
moveDirection.y -= ( gravity * Time.deltaTime )
def HandleEvents ():
// Events taken place are of action types: shooting, special attacks, interactable object, etc
pass
def hasSingleJumped ():
return ( Input.GetButtonDown( 'Jump' ) or Input.GetKeyDown( 'w' ) )
def hasExtraJumped ():
return ( Input.GetButtonDown( 'Jump' ) or Input.GetKeyDown( 'w' ) and doubleJumpEnabled )
def hasReachedJumpingApex ():
if jumped and controller.velocity.y <= 0.0:
jumpingApexReached = true
return jumpingApexReached
else:
if controller.isGrounded:
jumpingApexReached = false
return jumpingApexReached
def getSpeed ():
return moveDirection.x
singles meant float. walkSpeed as single is the same as float walkSpeed. The jumpApex is returning when the character starts to descend after a jump.
Hopefully it helps in some way and sorry if the code looks scary, it is suppose to be reader friendly.