Untitled diff

Created Diff never expires
17 removals
Lines
Total
Removed
Words
Total
Removed
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
280 lines
13 additions
Lines
Total
Added
Words
Total
Added
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
275 lines
using System.Collections;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine;
using KinematicCharacterController;
using KinematicCharacterController;
using System;
using System;


namespace KinematicCharacterController.Walkthrough.WallJumping
namespace LezCharacterController
{
{
public struct PlayerCharacterInputs
public struct PlayerCharacterInputs
{
{
public float horizontal;
public float horizontal;
public bool JumpDown;
public bool JumpDown;
}
}


public class MyCharacterController : BaseCharacterController
public class KinematicCharacter : BaseCharacterController
{
{
[Header("Stable Movement")]
[Header("Movement")]
public float MaxStableMoveSpeed = 10f;
public float MaxStableMoveSpeed = 10f;
public float StableMovementSharpness = 15;
public float StableMovementSharpness = 15;
public float rotateSpeed = 10;
public float rotateSpeed = 10;


[Header("Air Movement")]
[Header("Air Movement")]
public float MaxAirMoveSpeed = 10f;
public float MaxAirMoveSpeed = 10f;
public float AirAccelerationSpeed = 5f;
public float AirAccelerationSpeed = 5f;
public float Drag = 0.1f;
public float Drag = 0.1f;


[Header("Jumping")]
[Header("Jumping")]
public bool AllowJumpingWhenSliding = false;
public bool AllowJumpingWhenSliding = false;
public bool AllowDoubleJump = false;
public bool AllowDoubleJump = false;
public bool AllowWallJump = false;
public bool AllowWallJump = false;
public float JumpSpeed = 10f;
public float JumpSpeed = 10f;
public float JumpPreGroundingGraceTime = 0f;
public float JumpPreGroundingGraceTime = 0f;
public float JumpPostGroundingGraceTime = 0f;
public float JumpPostGroundingGraceTime = 0f;


[Header("Misc")]
[Header("Misc")]
public bool RotationObstruction;
public Vector3 Gravity = new Vector3(0, -30f, 0);
public Vector3 Gravity = new Vector3(0, -30f, 0);
public Transform MeshRoot;
public Transform MeshRoot;

private Vector3 moveDirection;
private float Angle;
private float inputAmount;
private bool _jumpRequested = false;
private bool _jumpRequested = false;
private bool _jumpConsumed = false;
private bool _jumpConsumed = false;
private bool _jumpedThisFrame = false;
private bool _jumpedThisFrame = false;
private float _timeSinceJumpRequested = Mathf.Infinity;
private float _timeSinceJumpRequested = Mathf.Infinity;
private float _timeSinceLastAbleToJump = 0f;
private float _timeSinceLastAbleToJump = 0f;
private bool _doubleJumpConsumed = false;
private bool _doubleJumpConsumed = false;
private bool _canWallJump = false;
private bool _canWallJump = false;
private Vector3 _wallJumpNormal;
private Vector3 _wallJumpNormal;


float inputAmount, Angle;
public Transform DirectionReference;
Vector3 moveDirection;
Transform DirectionReference;


private void Start()
private void Start()
{
{
DirectionReference = new GameObject("Player's Direction Reference").transform;
DirectionReference = new GameObject("Player's Direction Reference").transform;
}
}


/// <summary>
/// <summary>
/// This is called every frame by MyPlayer in order to tell the character what its inputs are
/// This is called every frame by MyPlayer in order to tell the character what its inputs are
/// </summary>
/// </summary>
public void SetInputs(ref PlayerCharacterInputs inputs)
public void SetInputs(ref PlayerCharacterInputs inputs)
{
{
// Clamp input
// Clamp input
float inputMagnitude = Mathf.Abs(inputs.horizontal);
float inputMagnitude = Mathf.Abs(inputs.horizontal);
inputAmount = Mathf.Clamp01(inputMagnitude);
inputAmount = Mathf.Clamp01(inputMagnitude);


// base movement on direction reference
// base movement on direction reference
Vector3 correctedHorizontal = inputs.horizontal * DirectionReference.transform.right;
Vector3 correctedHorizontal = inputs.horizontal * DirectionReference.transform.right;
moveDirection = new Vector3((correctedHorizontal).normalized.x, 0, (correctedHorizontal).normalized.z);
moveDirection = new Vector3((correctedHorizontal).normalized.x, 0, (correctedHorizontal).normalized.z);


// Jumping input
// Jumping input
if (inputs.JumpDown)
if (inputs.JumpDown)
{
{
_timeSinceJumpRequested = 0f;
_timeSinceJumpRequested = 0f;
_jumpRequested = true;
_jumpRequested = true;
}
}
}
}


/// <summary>
/// (Called by KinematicCharacterMotor during its update cycle)
/// This is called before the character begins its movement update
/// </summary>
public override void BeforeCharacterUpdate(float deltaTime)
public override void BeforeCharacterUpdate(float deltaTime)
{
{
}
}


/// <summary>
/// <summary>
/// (Called by KinematicCharacterMotor during its update cycle)
/// (Called by KinematicCharacterMotor during its update cycle)
/// This is where you tell your character what its rotation should be right now.
/// This is where you tell your character what its rotation should be right now.
/// This is the ONLY place where you should set the character's rotation
/// This is the ONLY place where you should set the character's rotation
/// </summary>
/// </summary>
public override void UpdateRotation(ref Quaternion currentRotation, float deltaTime)
public override void UpdateRotation(ref Quaternion currentRotation, float deltaTime)
{
{
// rotate player to movement direction
// rotate player to movement direction
if (moveDirection != Vector3.zero)
if (moveDirection != Vector3.zero)
{
{
Angle = Vector3.Angle(transform.forward, DirectionReference.right);
Angle = Vector3.Angle(transform.forward, DirectionReference.right);
Quaternion rot = Quaternion.LookRotation(moveDirection);
Quaternion rot = Quaternion.LookRotation(moveDirection);
Quaternion targetRotation = Quaternion.Slerp(transform.rotation, rot, deltaTime * inputAmount * rotateSpeed);
Quaternion targetRotation = Quaternion.Slerp(transform.rotation, rot, deltaTime * inputAmount * rotateSpeed);
currentRotation = targetRotation;
currentRotation = targetRotation;
}
}
else
else
{
{
if (Angle < 90)
if (Angle < 90)
{
{
Quaternion rot = Quaternion.LookRotation(DirectionReference.right);
Quaternion rot = Quaternion.LookRotation(DirectionReference.right);
Quaternion targetRotation = Quaternion.Slerp(transform.rotation, rot, deltaTime * rotateSpeed);
Quaternion targetRotation = Quaternion.Slerp(transform.rotation, rot, deltaTime * rotateSpeed);
currentRotation = targetRotation;
currentRotation = targetRotation;
}
}
else
else
{
{
Quaternion rot = Quaternion.LookRotation(-DirectionReference.right);
Quaternion rot = Quaternion.LookRotation(-DirectionReference.right);
Quaternion targetRotation = Quaternion.Slerp(transform.rotation, rot, deltaTime * rotateSpeed);
Quaternion targetRotation = Quaternion.Slerp(transform.rotation, rot, deltaTime * rotateSpeed);
currentRotation = targetRotation;
currentRotation = targetRotation;
}
}
}
}
}
}


/// <summary>
/// <summary>
/// (Called by KinematicCharacterMotor during its update cycle)
/// (Called by KinematicCharacterMotor during its update cycle)
/// This is where you tell your character what its velocity should be right now.
/// This is where you tell your character what its velocity should be right now.
/// This is the ONLY place where you can set the character's velocity
/// This is the ONLY place where you can set the character's velocity
/// </summary>
/// </summary>
public override void UpdateVelocity(ref Vector3 currentVelocity, float deltaTime)
public override void UpdateVelocity(ref Vector3 currentVelocity, float deltaTime)
{
{
Vector3 targetMovementVelocity = Vector3.zero;
Vector3 targetMovementVelocity = Vector3.zero;
if (Motor.GroundingStatus.IsStableOnGround)
if (Motor.GroundingStatus.IsStableOnGround)
{
{
// Reorient velocity on slope
// Reorient velocity on slope
currentVelocity = Motor.GetDirectionTangentToSurface(currentVelocity, Motor.GroundingStatus.GroundNormal) * currentVelocity.magnitude;
currentVelocity = Motor.GetDirectionTangentToSurface(currentVelocity, Motor.GroundingStatus.GroundNormal) * currentVelocity.magnitude;


// Calculate target velocity
// Calculate target velocity
Vector3 inputRight = Vector3.Cross(moveDirection, Motor.CharacterUp);
Vector3 inputRight = Vector3.Cross(moveDirection, Motor.CharacterUp);
Vector3 reorientedInput = Vector3.Cross(Motor.GroundingStatus.GroundNormal, inputRight).normalized * moveDirection.magnitude;
Vector3 reorientedInput = Vector3.Cross(Motor.GroundingStatus.GroundNormal, inputRight).normalized * moveDirection.magnitude;
targetMovementVelocity = reorientedInput * MaxStableMoveSpeed;
targetMovementVelocity = reorientedInput * MaxStableMoveSpeed;


// Smooth movement Velocity
// Smooth movement Velocity
currentVelocity = Vector3.Lerp(currentVelocity, targetMovementVelocity, 1 - Mathf.Exp(-StableMovementSharpness * deltaTime));
currentVelocity = Vector3.Lerp(currentVelocity, targetMovementVelocity, 1 - Mathf.Exp(-StableMovementSharpness * deltaTime));
}
}
else
else
{
{
// Add move input
// Add move input
if (moveDirection.sqrMagnitude > 0f)
if (moveDirection.sqrMagnitude > 0f)
{
{
targetMovementVelocity = moveDirection * MaxAirMoveSpeed;
targetMovementVelocity = moveDirection * MaxAirMoveSpeed;


// Prevent climbing on un-stable slopes with air movement
// Prevent climbing on un-stable slopes with air movement
if (Motor.GroundingStatus.FoundAnyGround)
if (Motor.GroundingStatus.FoundAnyGround)
{
{
Vector3 perpenticularObstructionNormal = Vector3.Cross(Vector3.Cross(Motor.CharacterUp, Motor.GroundingStatus.GroundNormal), Motor.CharacterUp).normalized;
Vector3 perpenticularObstructionNormal = Vector3.Cross(Vector3.Cross(Motor.CharacterUp, Motor.GroundingStatus.GroundNormal), Motor.CharacterUp).normalized;
targetMovementVelocity = Vector3.ProjectOnPlane(targetMovementVelocity, perpenticularObstructionNormal);
targetMovementVelocity = Vector3.ProjectOnPlane(targetMovementVelocity, perpenticularObstructionNormal);
}
}


Vector3 velocityDiff = Vector3.ProjectOnPlane(targetMovementVelocity - currentVelocity, Gravity);
Vector3 velocityDiff = Vector3.ProjectOnPlane(targetMovementVelocity - currentVelocity, Gravity);
currentVelocity += velocityDiff * AirAccelerationSpeed * deltaTime;
currentVelocity += velocityDiff * AirAccelerationSpeed * deltaTime;
}
}


// Gravity
// Gravity
currentVelocity += Gravity * deltaTime;
currentVelocity += Gravity * deltaTime;


// Drag
// Drag
currentVelocity *= (1f / (1f + (Drag * deltaTime)));
currentVelocity *= (1f / (1f + (Drag * deltaTime)));
}
}


// Handle jumping
// Handle jumping
{
{
_jumpedThisFrame = false;
_jumpedThisFrame = false;
_timeSinceJumpRequested += deltaTime;
_timeSinceJumpRequested += deltaTime;
if (_jumpRequested)
if (_jumpRequested)
{
{
// Handle double jump
// Handle double jump
if (AllowDoubleJump)
if (AllowDoubleJump)
{
{
if (_jumpConsumed && !_doubleJumpConsumed && (AllowJumpingWhenSliding ? !Motor.GroundingStatus.FoundAnyGround : !Motor.GroundingStatus.IsStableOnGround))
if (_jumpConsumed && !_doubleJumpConsumed && (AllowJumpingWhenSliding ? !Motor.GroundingStatus.FoundAnyGround : !Motor.GroundingStatus.IsStableOnGround))
{
{
Motor.ForceUnground();
Motor.ForceUnground();


// Add to the return velocity and reset jump state
// Add to the return velocity and reset jump state
currentVelocity += (Motor.CharacterUp * JumpSpeed) - Vector3.Project(currentVelocity, Motor.CharacterUp);
currentVelocity += (Motor.CharacterUp * JumpSpeed) - Vector3.Project(currentVelocity, Motor.CharacterUp);
_jumpRequested = false;
_jumpRequested = false;
_doubleJumpConsumed = true;
_doubleJumpConsumed = true;
_jumpedThisFrame = true;
_jumpedThisFrame = true;
}
}
}
}


// See if we actually are allowed to jump
// See if we actually are allowed to jump
if (_canWallJump ||
if (_canWallJump ||
(!_jumpConsumed && ((AllowJumpingWhenSliding ? Motor.GroundingStatus.FoundAnyGround : Motor.GroundingStatus.IsStableOnGround) || _timeSinceLastAbleToJump <= JumpPostGroundingGraceTime)))
(!_jumpConsumed && ((AllowJumpingWhenSliding ? Motor.GroundingStatus.FoundAnyGround : Motor.GroundingStatus.IsStableOnGround) || _timeSinceLastAbleToJump <= JumpPostGroundingGraceTime)))
{
{
// Calculate jump direction before ungrounding
// Calculate jump direction before ungrounding
Vector3 jumpDirection = Motor.CharacterUp;
Vector3 jumpDirection = Motor.CharacterUp;
if (_canWallJump)
if (_canWallJump)
{
{
jumpDirection = _wallJumpNormal;
jumpDirection = _wallJumpNormal;
}
}
else if (Motor.GroundingStatus.FoundAnyGround && !Motor.GroundingStatus.IsStableOnGround)
else if (Motor.GroundingStatus.FoundAnyGround && !Motor.GroundingStatus.IsStableOnGround)
{
{
jumpDirection = Motor.GroundingStatus.GroundNormal;
jumpDirection = Motor.GroundingStatus.GroundNormal;
}
}


// Makes the character skip ground probing/snapping on its next update.
// Makes the character skip ground probing/snapping on its next update.
// If this line weren't here, the character would remain snapped to the ground when trying to jump. Try commenting this line out and see.
// If this line weren't here, the character would remain snapped to the ground when trying to jump. Try commenting this line out and see.
Motor.ForceUnground();
Motor.ForceUnground();


// Add to the return velocity and reset jump state
// Add to the return velocity and reset jump state
currentVelocity += (jumpDirection * JumpSpeed) - Vector3.Project(currentVelocity, Motor.CharacterUp);
currentVelocity += (jumpDirection * JumpSpeed) - Vector3.Project(currentVelocity, Motor.CharacterUp);
_jumpRequested = false;
_jumpRequested = false;
_jumpConsumed = true;
_jumpConsumed = true;
_jumpedThisFrame = true;
_jumpedThisFrame = true;
}
}
}
}


// Reset wall jump
// Reset wall jump
_canWallJump = false;
_canWallJump = false;
}
}
}
}


/// <summary>
/// <summary>
/// (Called by KinematicCharacterMotor during its update cycle)
/// (Called by KinematicCharacterMotor during its update cycle)
/// This is called after the character has finished its movement update
/// This is called after the character has finished its movement update
/// </summary>
/// </summary>
public override void AfterCharacterUpdate(float deltaTime)
public override void AfterCharacterUpdate(float deltaTime)
{
{
// Handle jump-related values
// Handle jump-related values
{
{
// Handle jumping pre-ground grace period
// Handle jumping pre-ground grace period
if (_jumpRequested && _timeSinceJumpRequested > JumpPreGroundingGraceTime)
if (_jumpRequested && _timeSinceJumpRequested > JumpPreGroundingGraceTime)
{
{
_jumpRequested = false;
_jumpRequested = false;
}
}


if (AllowJumpingWhenSliding ? Motor.GroundingStatus.FoundAnyGround : Motor.GroundingStatus.IsStableOnGround)
if (AllowJumpingWhenSliding ? Motor.GroundingStatus.FoundAnyGround : Motor.GroundingStatus.IsStableOnGround)
{
{
// If we're on a ground surface, reset jumping values
// If we're on a ground surface, reset jumping values
if (!_jumpedThisFrame)
if (!_jumpedThisFrame)
{
{
_doubleJumpConsumed = false;
_doubleJumpConsumed = false;
_jumpConsumed = false;
_jumpConsumed = false;
}
}
_timeSinceLastAbleToJump = 0f;
_timeSinceLastAbleToJump = 0f;
}
}
else
else
{
{
// Keep track of time since we were last able to jump (for grace period)
// Keep track of time since we were last able to jump (for grace period)
_timeSinceLastAbleToJump += deltaTime;
_timeSinceLastAbleToJump += deltaTime;
}
}
}
}
}
}


public override bool IsColliderValidForCollisions(Collider coll)
public override bool IsColliderValidForCollisions(Collider coll)
{
{
return true;
return true;
}
}


public override void OnGroundHit(Collider hitCollider, Vector3 hitNormal, Vector3 hitPoint, ref HitStabilityReport hitStabilityReport)
public override void OnGroundHit(Collider hitCollider, Vector3 hitNormal, Vector3 hitPoint, ref HitStabilityReport hitStabilityReport)
{
{
}
}


public override void OnMovementHit(Collider hitCollider, Vector3 hitNormal, Vector3 hitPoint, ref HitStabilityReport hitStabilityReport)
public override void OnMovementHit(Collider hitCollider, Vector3 hitNormal, Vector3 hitPoint, ref HitStabilityReport hitStabilityReport)
{
{
// We can wall jump only if we are not stable on ground and are moving against an obstruction
// We can wall jump only if we are not stable on ground and are moving against an obstruction
if (AllowWallJump && !Motor.GroundingStatus.IsStableOnGround && !hitStabilityReport.IsStable)
if (AllowWallJump && !Motor.GroundingStatus.IsStableOnGround && !hitStabilityReport.IsStable)
{
{
_canWallJump = true;
_canWallJump = true;
_wallJumpNormal = hitNormal;
_wallJumpNormal = hitNormal;
}
}
}
}


public override void PostGroundingUpdate(float deltaTime)
public override void ProcessHitStabilityReport(Collider hitCollider, Vector3 hitNormal, Vector3 hitPoint, Vector3 atCharacterPosition, Quaternion atCharacterRotation, ref HitStabilityReport hitStabilityReport)
{
}

public void AddVelocity(Vector3 velocity)
{
{
}
}


public override void ProcessHitStabilityReport(Collider hitCollider, Vector3 hitNormal, Vector3 hitPoint, Vector3 atCharacterPosition, Quaternion atCharacterRotation, ref HitStabilityReport hitStabilityReport)
public override void PostGroundingUpdate(float deltaTime)
{
{
}
}
}
}
}
}