Diff
checker
テキスト
テキスト
画像
ドキュメント
Excel
フォルダ
Legal
Enterprise
デスクトップ
料金
ログイン
Diffchecker デスクトップのダウンロード
テキスト比較
2 つのテキスト ファイルの違いを見つける
ツール
履歴
ライブエディター
未変更行を折りたたむ
折り返しなし
レイアウト
分割
統合
比較精度
スマート
単語
文字
シンタックスハイライト
構文を選択
無視
テキスト変換
最初の差分へ移動
入力を編集
Diffchecker Desktop
Diffcheckerを実行する最も安全な方法。Diffchecker Desktopアプリを入手:あなたの差分はコンピューターから出ることはありません!
Desktopを入手
Untitled diff
作成日
7 年前
差分は期限切れになりません
クリア
エクスポート
共有
説明
17 削除
行
合計
削除
文字
合計
削除
この機能を引き続き使用するには、アップグレードしてください
Diff
checker
Pro
価格を見る
280 行
すべてコピー
12 追加
行
合計
追加
文字
合計
追加
この機能を引き続き使用するには、アップグレードしてください
Diff
checker
Pro
価格を見る
275 行
すべてコピー
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
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;
}
}
コピー
コピー済み
コピー
コピー済み
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)
{
{
}
}
}
}
}
}
コピー
コピー済み
コピー
コピー済み
保存された差分
原文
ファイルを開く
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) { } } }
変更されたテキスト
ファイルを開く
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) { } } }
違いを見つける