Diff
checker
Text
Text
Images
Documents
Excel
Folders
Legal
Enterprise
Desktop
Pricing
Sign in
Download Diffchecker Desktop
Compare text
Find the difference between two text files
Tools
History
Real-time editor
Hide unchanged lines
Disable line wrap
Layout
Split
Unified
Diff precision
Smart
Word
Char
Syntax highlighting
Choose syntax
Ignore
Transform text
Go to first change
Edit input
Diffchecker Desktop
The most secure way to run Diffchecker. Get the Diffchecker Desktop app: your diffs never leave your computer!
Get Desktop
Untitled diff
Created
7 years ago
Diff never expires
Clear
Export
Share
Explain
17 removals
Lines
Total
Removed
Characters
Total
Removed
To continue using this feature, upgrade to
Diff
checker
Pro
View Pricing
280 lines
Copy
12 additions
Lines
Total
Added
Characters
Total
Added
To continue using this feature, upgrade to
Diff
checker
Pro
View Pricing
275 lines
Copy
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;
Copy
Copied
Copy
Copied
namespace
Kinematic
CharacterController
.Walkthrough.WallJumping
namespace
Lez
CharacterController
{
{
public struct PlayerCharacterInputs
public struct PlayerCharacterInputs
{
{
public float horizontal;
public float horizontal;
public bool JumpDown;
public bool JumpDown;
}
}
Copy
Copied
Copy
Copied
public class
MyCharacterController
: BaseCharacterController
public class
KinematicCharacter
: BaseCharacterController
{
{
Copy
Copied
Copy
Copied
[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")]
Copy
Copied
Copy
Copied
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;
Copy
Copied
Copy
Copied
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;
Copy
Copied
Copy
Copied
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;
}
}
}
}
Copy
Copied
Copy
Copied
/// <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;
}
}
}
}
Copy
Copied
Copy
Copied
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)
{
{
}
}
Copy
Copied
Copy
Copied
public override void
ProcessHitStabilityReport(Collider hitCollider, Vector3 hitNormal, Vector3 hitPoint, Vector3 atCharacterPosition, Quaternion atCharacterRotation, ref HitStabilityReport hitStabilityReport)
public override void
PostGroundingUpdate(float deltaTime)
{
{
}
}
}
}
}
}
Copy
Copied
Copy
Copied
Saved diffs
Original text
Open file
using System.Collections; using System.Collections.Generic; using UnityEngine; using KinematicCharacterController; using System; namespace KinematicCharacterController.Walkthrough.WallJumping { public struct PlayerCharacterInputs { public float horizontal; public bool JumpDown; } public class MyCharacterController : BaseCharacterController { [Header("Stable Movement")] public float MaxStableMoveSpeed = 10f; public float StableMovementSharpness = 15; public float rotateSpeed = 10; [Header("Air Movement")] public float MaxAirMoveSpeed = 10f; public float AirAccelerationSpeed = 5f; public float Drag = 0.1f; [Header("Jumping")] public bool AllowJumpingWhenSliding = false; public bool AllowDoubleJump = false; public bool AllowWallJump = false; public float JumpSpeed = 10f; public float JumpPreGroundingGraceTime = 0f; public float JumpPostGroundingGraceTime = 0f; [Header("Misc")] public Vector3 Gravity = new Vector3(0, -30f, 0); public Transform MeshRoot; private bool _jumpRequested = false; private bool _jumpConsumed = false; private bool _jumpedThisFrame = false; private float _timeSinceJumpRequested = Mathf.Infinity; private float _timeSinceLastAbleToJump = 0f; private bool _doubleJumpConsumed = false; private bool _canWallJump = false; private Vector3 _wallJumpNormal; float inputAmount, Angle; Vector3 moveDirection; Transform DirectionReference; private void Start() { DirectionReference = new GameObject("Player's Direction Reference").transform; } /// <summary> /// This is called every frame by MyPlayer in order to tell the character what its inputs are /// </summary> public void SetInputs(ref PlayerCharacterInputs inputs) { // Clamp input float inputMagnitude = Mathf.Abs(inputs.horizontal); inputAmount = Mathf.Clamp01(inputMagnitude); // base movement on direction reference Vector3 correctedHorizontal = inputs.horizontal * DirectionReference.transform.right; moveDirection = new Vector3((correctedHorizontal).normalized.x, 0, (correctedHorizontal).normalized.z); // Jumping input if (inputs.JumpDown) { _timeSinceJumpRequested = 0f; _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) { } /// <summary> /// (Called by KinematicCharacterMotor during its update cycle) /// 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 /// </summary> public override void UpdateRotation(ref Quaternion currentRotation, float deltaTime) { // rotate player to movement direction if (moveDirection != Vector3.zero) { Angle = Vector3.Angle(transform.forward, DirectionReference.right); Quaternion rot = Quaternion.LookRotation(moveDirection); Quaternion targetRotation = Quaternion.Slerp(transform.rotation, rot, deltaTime * inputAmount * rotateSpeed); currentRotation = targetRotation; } else { if (Angle < 90) { Quaternion rot = Quaternion.LookRotation(DirectionReference.right); Quaternion targetRotation = Quaternion.Slerp(transform.rotation, rot, deltaTime * rotateSpeed); currentRotation = targetRotation; } else { Quaternion rot = Quaternion.LookRotation(-DirectionReference.right); Quaternion targetRotation = Quaternion.Slerp(transform.rotation, rot, deltaTime * rotateSpeed); currentRotation = targetRotation; } } } /// <summary> /// (Called by KinematicCharacterMotor during its update cycle) /// 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 /// </summary> public override void UpdateVelocity(ref Vector3 currentVelocity, float deltaTime) { Vector3 targetMovementVelocity = Vector3.zero; if (Motor.GroundingStatus.IsStableOnGround) { // Reorient velocity on slope currentVelocity = Motor.GetDirectionTangentToSurface(currentVelocity, Motor.GroundingStatus.GroundNormal) * currentVelocity.magnitude; // Calculate target velocity Vector3 inputRight = Vector3.Cross(moveDirection, Motor.CharacterUp); Vector3 reorientedInput = Vector3.Cross(Motor.GroundingStatus.GroundNormal, inputRight).normalized * moveDirection.magnitude; targetMovementVelocity = reorientedInput * MaxStableMoveSpeed; // Smooth movement Velocity currentVelocity = Vector3.Lerp(currentVelocity, targetMovementVelocity, 1 - Mathf.Exp(-StableMovementSharpness * deltaTime)); } else { // Add move input if (moveDirection.sqrMagnitude > 0f) { targetMovementVelocity = moveDirection * MaxAirMoveSpeed; // Prevent climbing on un-stable slopes with air movement if (Motor.GroundingStatus.FoundAnyGround) { Vector3 perpenticularObstructionNormal = Vector3.Cross(Vector3.Cross(Motor.CharacterUp, Motor.GroundingStatus.GroundNormal), Motor.CharacterUp).normalized; targetMovementVelocity = Vector3.ProjectOnPlane(targetMovementVelocity, perpenticularObstructionNormal); } Vector3 velocityDiff = Vector3.ProjectOnPlane(targetMovementVelocity - currentVelocity, Gravity); currentVelocity += velocityDiff * AirAccelerationSpeed * deltaTime; } // Gravity currentVelocity += Gravity * deltaTime; // Drag currentVelocity *= (1f / (1f + (Drag * deltaTime))); } // Handle jumping { _jumpedThisFrame = false; _timeSinceJumpRequested += deltaTime; if (_jumpRequested) { // Handle double jump if (AllowDoubleJump) { if (_jumpConsumed && !_doubleJumpConsumed && (AllowJumpingWhenSliding ? !Motor.GroundingStatus.FoundAnyGround : !Motor.GroundingStatus.IsStableOnGround)) { Motor.ForceUnground(); // Add to the return velocity and reset jump state currentVelocity += (Motor.CharacterUp * JumpSpeed) - Vector3.Project(currentVelocity, Motor.CharacterUp); _jumpRequested = false; _doubleJumpConsumed = true; _jumpedThisFrame = true; } } // See if we actually are allowed to jump if (_canWallJump || (!_jumpConsumed && ((AllowJumpingWhenSliding ? Motor.GroundingStatus.FoundAnyGround : Motor.GroundingStatus.IsStableOnGround) || _timeSinceLastAbleToJump <= JumpPostGroundingGraceTime))) { // Calculate jump direction before ungrounding Vector3 jumpDirection = Motor.CharacterUp; if (_canWallJump) { jumpDirection = _wallJumpNormal; } else if (Motor.GroundingStatus.FoundAnyGround && !Motor.GroundingStatus.IsStableOnGround) { jumpDirection = Motor.GroundingStatus.GroundNormal; } // 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. Motor.ForceUnground(); // Add to the return velocity and reset jump state currentVelocity += (jumpDirection * JumpSpeed) - Vector3.Project(currentVelocity, Motor.CharacterUp); _jumpRequested = false; _jumpConsumed = true; _jumpedThisFrame = true; } } // Reset wall jump _canWallJump = false; } } /// <summary> /// (Called by KinematicCharacterMotor during its update cycle) /// This is called after the character has finished its movement update /// </summary> public override void AfterCharacterUpdate(float deltaTime) { // Handle jump-related values { // Handle jumping pre-ground grace period if (_jumpRequested && _timeSinceJumpRequested > JumpPreGroundingGraceTime) { _jumpRequested = false; } if (AllowJumpingWhenSliding ? Motor.GroundingStatus.FoundAnyGround : Motor.GroundingStatus.IsStableOnGround) { // If we're on a ground surface, reset jumping values if (!_jumpedThisFrame) { _doubleJumpConsumed = false; _jumpConsumed = false; } _timeSinceLastAbleToJump = 0f; } else { // Keep track of time since we were last able to jump (for grace period) _timeSinceLastAbleToJump += deltaTime; } } } public override bool IsColliderValidForCollisions(Collider coll) { return true; } 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) { // 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) { _canWallJump = true; _wallJumpNormal = hitNormal; } } public override void PostGroundingUpdate(float deltaTime) { } public void AddVelocity(Vector3 velocity) { } public override void ProcessHitStabilityReport(Collider hitCollider, Vector3 hitNormal, Vector3 hitPoint, Vector3 atCharacterPosition, Quaternion atCharacterRotation, ref HitStabilityReport hitStabilityReport) { } } }
Changed text
Open file
using System.Collections; using System.Collections.Generic; using UnityEngine; using KinematicCharacterController; using System; namespace LezCharacterController { public struct PlayerCharacterInputs { public float horizontal; public bool JumpDown; } public class KinematicCharacter : BaseCharacterController { [Header("Movement")] public float MaxStableMoveSpeed = 10f; public float StableMovementSharpness = 15; public float rotateSpeed = 10; [Header("Air Movement")] public float MaxAirMoveSpeed = 10f; public float AirAccelerationSpeed = 5f; public float Drag = 0.1f; [Header("Jumping")] public bool AllowJumpingWhenSliding = false; public bool AllowDoubleJump = false; public bool AllowWallJump = false; public float JumpSpeed = 10f; public float JumpPreGroundingGraceTime = 0f; public float JumpPostGroundingGraceTime = 0f; [Header("Misc")] public bool RotationObstruction; public Vector3 Gravity = new Vector3(0, -30f, 0); public Transform MeshRoot; private Vector3 moveDirection; private float Angle; private float inputAmount; private bool _jumpRequested = false; private bool _jumpConsumed = false; private bool _jumpedThisFrame = false; private float _timeSinceJumpRequested = Mathf.Infinity; private float _timeSinceLastAbleToJump = 0f; private bool _doubleJumpConsumed = false; private bool _canWallJump = false; private Vector3 _wallJumpNormal; public Transform DirectionReference; private void Start() { DirectionReference = new GameObject("Player's Direction Reference").transform; } /// <summary> /// This is called every frame by MyPlayer in order to tell the character what its inputs are /// </summary> public void SetInputs(ref PlayerCharacterInputs inputs) { // Clamp input float inputMagnitude = Mathf.Abs(inputs.horizontal); inputAmount = Mathf.Clamp01(inputMagnitude); // base movement on direction reference Vector3 correctedHorizontal = inputs.horizontal * DirectionReference.transform.right; moveDirection = new Vector3((correctedHorizontal).normalized.x, 0, (correctedHorizontal).normalized.z); // Jumping input if (inputs.JumpDown) { _timeSinceJumpRequested = 0f; _jumpRequested = true; } } public override void BeforeCharacterUpdate(float deltaTime) { } /// <summary> /// (Called by KinematicCharacterMotor during its update cycle) /// 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 /// </summary> public override void UpdateRotation(ref Quaternion currentRotation, float deltaTime) { // rotate player to movement direction if (moveDirection != Vector3.zero) { Angle = Vector3.Angle(transform.forward, DirectionReference.right); Quaternion rot = Quaternion.LookRotation(moveDirection); Quaternion targetRotation = Quaternion.Slerp(transform.rotation, rot, deltaTime * inputAmount * rotateSpeed); currentRotation = targetRotation; } else { if (Angle < 90) { Quaternion rot = Quaternion.LookRotation(DirectionReference.right); Quaternion targetRotation = Quaternion.Slerp(transform.rotation, rot, deltaTime * rotateSpeed); currentRotation = targetRotation; } else { Quaternion rot = Quaternion.LookRotation(-DirectionReference.right); Quaternion targetRotation = Quaternion.Slerp(transform.rotation, rot, deltaTime * rotateSpeed); currentRotation = targetRotation; } } } /// <summary> /// (Called by KinematicCharacterMotor during its update cycle) /// 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 /// </summary> public override void UpdateVelocity(ref Vector3 currentVelocity, float deltaTime) { Vector3 targetMovementVelocity = Vector3.zero; if (Motor.GroundingStatus.IsStableOnGround) { // Reorient velocity on slope currentVelocity = Motor.GetDirectionTangentToSurface(currentVelocity, Motor.GroundingStatus.GroundNormal) * currentVelocity.magnitude; // Calculate target velocity Vector3 inputRight = Vector3.Cross(moveDirection, Motor.CharacterUp); Vector3 reorientedInput = Vector3.Cross(Motor.GroundingStatus.GroundNormal, inputRight).normalized * moveDirection.magnitude; targetMovementVelocity = reorientedInput * MaxStableMoveSpeed; // Smooth movement Velocity currentVelocity = Vector3.Lerp(currentVelocity, targetMovementVelocity, 1 - Mathf.Exp(-StableMovementSharpness * deltaTime)); } else { // Add move input if (moveDirection.sqrMagnitude > 0f) { targetMovementVelocity = moveDirection * MaxAirMoveSpeed; // Prevent climbing on un-stable slopes with air movement if (Motor.GroundingStatus.FoundAnyGround) { Vector3 perpenticularObstructionNormal = Vector3.Cross(Vector3.Cross(Motor.CharacterUp, Motor.GroundingStatus.GroundNormal), Motor.CharacterUp).normalized; targetMovementVelocity = Vector3.ProjectOnPlane(targetMovementVelocity, perpenticularObstructionNormal); } Vector3 velocityDiff = Vector3.ProjectOnPlane(targetMovementVelocity - currentVelocity, Gravity); currentVelocity += velocityDiff * AirAccelerationSpeed * deltaTime; } // Gravity currentVelocity += Gravity * deltaTime; // Drag currentVelocity *= (1f / (1f + (Drag * deltaTime))); } // Handle jumping { _jumpedThisFrame = false; _timeSinceJumpRequested += deltaTime; if (_jumpRequested) { // Handle double jump if (AllowDoubleJump) { if (_jumpConsumed && !_doubleJumpConsumed && (AllowJumpingWhenSliding ? !Motor.GroundingStatus.FoundAnyGround : !Motor.GroundingStatus.IsStableOnGround)) { Motor.ForceUnground(); // Add to the return velocity and reset jump state currentVelocity += (Motor.CharacterUp * JumpSpeed) - Vector3.Project(currentVelocity, Motor.CharacterUp); _jumpRequested = false; _doubleJumpConsumed = true; _jumpedThisFrame = true; } } // See if we actually are allowed to jump if (_canWallJump || (!_jumpConsumed && ((AllowJumpingWhenSliding ? Motor.GroundingStatus.FoundAnyGround : Motor.GroundingStatus.IsStableOnGround) || _timeSinceLastAbleToJump <= JumpPostGroundingGraceTime))) { // Calculate jump direction before ungrounding Vector3 jumpDirection = Motor.CharacterUp; if (_canWallJump) { jumpDirection = _wallJumpNormal; } else if (Motor.GroundingStatus.FoundAnyGround && !Motor.GroundingStatus.IsStableOnGround) { jumpDirection = Motor.GroundingStatus.GroundNormal; } // 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. Motor.ForceUnground(); // Add to the return velocity and reset jump state currentVelocity += (jumpDirection * JumpSpeed) - Vector3.Project(currentVelocity, Motor.CharacterUp); _jumpRequested = false; _jumpConsumed = true; _jumpedThisFrame = true; } } // Reset wall jump _canWallJump = false; } } /// <summary> /// (Called by KinematicCharacterMotor during its update cycle) /// This is called after the character has finished its movement update /// </summary> public override void AfterCharacterUpdate(float deltaTime) { // Handle jump-related values { // Handle jumping pre-ground grace period if (_jumpRequested && _timeSinceJumpRequested > JumpPreGroundingGraceTime) { _jumpRequested = false; } if (AllowJumpingWhenSliding ? Motor.GroundingStatus.FoundAnyGround : Motor.GroundingStatus.IsStableOnGround) { // If we're on a ground surface, reset jumping values if (!_jumpedThisFrame) { _doubleJumpConsumed = false; _jumpConsumed = false; } _timeSinceLastAbleToJump = 0f; } else { // Keep track of time since we were last able to jump (for grace period) _timeSinceLastAbleToJump += deltaTime; } } } public override bool IsColliderValidForCollisions(Collider coll) { return true; } 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) { // 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) { _canWallJump = true; _wallJumpNormal = hitNormal; } } public override void ProcessHitStabilityReport(Collider hitCollider, Vector3 hitNormal, Vector3 hitPoint, Vector3 atCharacterPosition, Quaternion atCharacterRotation, ref HitStabilityReport hitStabilityReport) { } public override void PostGroundingUpdate(float deltaTime) { } } }
Find difference