Compare commits
2
Commits
eb4dff803e
...
6732aef384
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6732aef384 | ||
|
|
ecff1e69cd |
No files matched your search
@@ -23,7 +23,11 @@ namespace Code.Configs
|
||||
);
|
||||
public float
|
||||
slideMinVelocityThreshold = 3f,
|
||||
slideCooldown = 1.5f;
|
||||
slideCooldown = 1.5f,
|
||||
slideColliderHeightScale = 0.5f,
|
||||
slideCameraOffsetY = -0.5f,
|
||||
slideEnterDuration = 0.2f,
|
||||
slideExitDuration = 0.25f;
|
||||
|
||||
public float
|
||||
leanAngle = 25f,
|
||||
|
||||
+143
-4
@@ -15,7 +15,7 @@ namespace Code.Gameplay.Character.Controller
|
||||
* Реализует физическое движение персонажа с использованием Kinematic Character Controller
|
||||
* Обрабатывает ввод пользователя, применяет движение и вращение с учетом поверхности
|
||||
*
|
||||
* Источник: Tvtig, https://www.youtube.com/watch?v=9ibpY64wBYM
|
||||
* Источник: Tvtig, https://www.youtube.com/watch?v=9ibpY64wBYM
|
||||
*/
|
||||
public class CustomCharacterController : MonoBehaviour, ICharacterController
|
||||
{
|
||||
@@ -25,6 +25,20 @@ namespace Code.Gameplay.Character.Controller
|
||||
|
||||
[SerializeField] private Transform characterTransform; // Трансформ персонажа (с точкой отслеживания камеры)
|
||||
|
||||
[SerializeField] private CapsuleCollider _capsuleCollider;
|
||||
[SerializeField] private Transform _cameraFollowPoint;
|
||||
private Vector3 _originalColliderCenter;
|
||||
private float _originalColliderHeight;
|
||||
private Vector3 _originalFollowPointLocalPosition;
|
||||
private bool _isEnteringSlide;
|
||||
private bool _isExitingSlide;
|
||||
private float _slideTransitionTime;
|
||||
private float _slideTransitionDuration;
|
||||
private float _currentColliderHeight;
|
||||
private Vector3 _currentColliderCenter;
|
||||
private Vector3 _currentFollowPointLocalPosition;
|
||||
private bool _wasSlidingLastFrame;
|
||||
|
||||
// Подсистемы
|
||||
private CharacterInputHandler _inputHandler;
|
||||
private DashMechanic _dashMechanic;
|
||||
@@ -92,6 +106,14 @@ namespace Code.Gameplay.Character.Controller
|
||||
motor.Transform.rotation; // Начальное вращение совпадает с персонажемс
|
||||
_wallLeanMechanic.SetModel(characterTransform);
|
||||
_wallRunningMechanic.Initialize(motor);
|
||||
|
||||
_originalColliderCenter = _capsuleCollider.center;
|
||||
_originalColliderHeight = _capsuleCollider.height;
|
||||
_originalFollowPointLocalPosition = _cameraFollowPoint.localPosition;
|
||||
|
||||
_currentColliderHeight = _originalColliderHeight;
|
||||
_currentColliderCenter = _originalColliderCenter;
|
||||
_currentFollowPointLocalPosition = _originalFollowPointLocalPosition;
|
||||
}
|
||||
|
||||
// Текущий режим камеры для адаптации поведения
|
||||
@@ -184,14 +206,32 @@ namespace Code.Gameplay.Character.Controller
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_slideMechanic.IsSliding)
|
||||
var wasSliding = _wasSlidingLastFrame;
|
||||
var isSlidingNow = _slideMechanic.IsSliding;
|
||||
|
||||
if (!isSlidingNow)
|
||||
{
|
||||
_slideMechanic.TryStartSlide(motor, _currentCameraMode, _inputHandler.FirstPersonCameraRotation, _inputHandler.LookInputVector);
|
||||
else
|
||||
isSlidingNow = _slideMechanic.IsSliding;
|
||||
}
|
||||
|
||||
switch (isSlidingNow)
|
||||
{
|
||||
case true when !wasSliding:
|
||||
EnterSlideState();
|
||||
break;
|
||||
case false when wasSliding:
|
||||
ExitSlideState();
|
||||
break;
|
||||
}
|
||||
|
||||
if (isSlidingNow)
|
||||
{
|
||||
_slideMechanic.HandleSlide(ref currentVelocity, deltaTime, motor);
|
||||
return;
|
||||
}
|
||||
|
||||
_wasSlidingLastFrame = isSlidingNow;
|
||||
|
||||
// === WALL RUNNING: обработка состояния ===
|
||||
if (_wallRunningMechanic.IsWallRunning)
|
||||
{
|
||||
@@ -226,6 +266,103 @@ namespace Code.Gameplay.Character.Controller
|
||||
isAbilitiesBlocked = true;
|
||||
abilityBlockTimer = duration;
|
||||
}
|
||||
|
||||
private void EnterSlideState()
|
||||
{
|
||||
_isEnteringSlide = true;
|
||||
_isExitingSlide = false;
|
||||
_slideTransitionTime = 0f;
|
||||
_slideTransitionDuration = _characterConfig.slideEnterDuration;
|
||||
}
|
||||
|
||||
private void ExitSlideState()
|
||||
{
|
||||
_isExitingSlide = true;
|
||||
_isEnteringSlide = false;
|
||||
_slideTransitionTime = 0f;
|
||||
_slideTransitionDuration = _characterConfig.slideExitDuration;
|
||||
}
|
||||
|
||||
private void UpdateSlideTransition(float deltaTime)
|
||||
{
|
||||
if (!_isEnteringSlide && !_isExitingSlide) return;
|
||||
|
||||
_slideTransitionTime += deltaTime;
|
||||
var t = Mathf.Clamp01(_slideTransitionTime / _slideTransitionDuration);
|
||||
|
||||
t = Mathf.SmoothStep(0f, 1f, t);
|
||||
|
||||
if (_isEnteringSlide)
|
||||
{
|
||||
var targetHeight = _originalColliderHeight * _characterConfig.slideColliderHeightScale;
|
||||
var targetCenterY = targetHeight * 0.5f - _originalColliderHeight * 0.5f;
|
||||
var targetCenter = _originalColliderCenter + Vector3.up * targetCenterY;
|
||||
|
||||
var targetFollowPos = _originalFollowPointLocalPosition + Vector3.up * _characterConfig.slideCameraOffsetY;
|
||||
|
||||
_currentColliderHeight = Mathf.Lerp(_originalColliderHeight, targetHeight, t);
|
||||
_currentColliderCenter = Vector3.Lerp(_originalColliderCenter, targetCenter, t);
|
||||
_currentFollowPointLocalPosition = Vector3.Lerp(_originalFollowPointLocalPosition, targetFollowPos, t);
|
||||
}
|
||||
else if (_isExitingSlide)
|
||||
{
|
||||
_currentColliderHeight = Mathf.Lerp(_originalColliderHeight * _characterConfig.slideColliderHeightScale, _originalColliderHeight, t);
|
||||
|
||||
var prevHeight = _originalColliderHeight * _characterConfig.slideColliderHeightScale;
|
||||
var prevCenterY = prevHeight * 0.5f - _originalColliderHeight * 0.5f;
|
||||
var prevCenter = _originalColliderCenter + Vector3.up * prevCenterY;
|
||||
|
||||
var prevFollowPos = _originalFollowPointLocalPosition + Vector3.up * _characterConfig.slideCameraOffsetY;
|
||||
|
||||
_currentColliderCenter = Vector3.Lerp(prevCenter, _originalColliderCenter, t);
|
||||
_currentFollowPointLocalPosition = Vector3.Lerp(prevFollowPos, _originalFollowPointLocalPosition, t);
|
||||
}
|
||||
|
||||
if (_capsuleCollider)
|
||||
{
|
||||
_capsuleCollider.height = _currentColliderHeight;
|
||||
_capsuleCollider.center = _currentColliderCenter;
|
||||
}
|
||||
|
||||
if (_cameraFollowPoint)
|
||||
{
|
||||
_cameraFollowPoint.localPosition = _currentFollowPointLocalPosition;
|
||||
}
|
||||
|
||||
if (!(t >= 1f)) return;
|
||||
|
||||
if (_isEnteringSlide)
|
||||
{
|
||||
_isEnteringSlide = false;
|
||||
if (_capsuleCollider)
|
||||
{
|
||||
_capsuleCollider.height = _originalColliderHeight * _characterConfig.slideColliderHeightScale;
|
||||
var h = _capsuleCollider.height;
|
||||
_capsuleCollider.center = _originalColliderCenter + Vector3.up * (h * 0.5f - _originalColliderHeight * 0.5f);
|
||||
}
|
||||
if (_cameraFollowPoint)
|
||||
{
|
||||
_cameraFollowPoint.localPosition = _originalFollowPointLocalPosition + Vector3.up * _characterConfig.slideCameraOffsetY;
|
||||
}
|
||||
}
|
||||
else if (_isExitingSlide)
|
||||
{
|
||||
_isExitingSlide = false;
|
||||
if (_capsuleCollider)
|
||||
{
|
||||
_capsuleCollider.height = _originalColliderHeight;
|
||||
_capsuleCollider.center = _originalColliderCenter;
|
||||
}
|
||||
if (_cameraFollowPoint)
|
||||
{
|
||||
_cameraFollowPoint.localPosition = _originalFollowPointLocalPosition;
|
||||
}
|
||||
}
|
||||
|
||||
_currentColliderHeight = _capsuleCollider ? _capsuleCollider.height : _originalColliderHeight;
|
||||
_currentColliderCenter = _capsuleCollider ? _capsuleCollider.center : _originalColliderCenter;
|
||||
_currentFollowPointLocalPosition = _cameraFollowPoint ? _cameraFollowPoint.localPosition : _originalFollowPointLocalPosition;
|
||||
}
|
||||
|
||||
public void BeforeCharacterUpdate(float deltaTime)
|
||||
{
|
||||
@@ -241,6 +378,8 @@ namespace Code.Gameplay.Character.Controller
|
||||
|
||||
public void AfterCharacterUpdate(float deltaTime)
|
||||
{
|
||||
UpdateSlideTransition(deltaTime);
|
||||
|
||||
_wallLeanMechanic.Update(
|
||||
_wallRunningMechanic.IsWallRunning,
|
||||
_wallRunningMechanic.GetWallNormal(),
|
||||
|
||||
@@ -173,6 +173,8 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Code.Gameplay.Player.CharacterController
|
||||
motor: {fileID: 8476708390679839925}
|
||||
characterTransform: {fileID: 4122797476271397740}
|
||||
_capsuleCollider: {fileID: 8541228187116599584}
|
||||
_cameraFollowPoint: {fileID: 1047840484662430186}
|
||||
--- !u!114 &3283650228831796584
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
Reference in new issue
Block a user