187 lines
6.8 KiB
C#
187 lines
6.8 KiB
C#
using DG.Tweening;
|
||
using Sirenix.OdinInspector;
|
||
using SLSUtilities.General;
|
||
using UnityEngine;
|
||
using UnityEngine.Serialization;
|
||
|
||
namespace Cielonos.MainGame.Characters
|
||
{
|
||
public partial class MovementSubcontrollerBase : SubcontrollerBase<CharacterBase>
|
||
{
|
||
protected CharacterBase character => owner;
|
||
protected float DeltaTime => owner.selfTimeSm.DeltaTime;
|
||
|
||
[Tooltip("角色旋转方式,ByMovement为ARPG式默认移动旋转,ByAiming为八向移动")]
|
||
public CharacterRotationType rotationType;
|
||
|
||
public ImpulseSubmodule impulseSm;
|
||
|
||
[HideInEditorMode]
|
||
public Transform characterTransform;
|
||
|
||
|
||
public override void Initialize()
|
||
{
|
||
base.Initialize();
|
||
impulseSm ??= new ImpulseSubmodule(this);
|
||
|
||
canMove = new CompoundBool(true);
|
||
canRotate = new CompoundBool(true);
|
||
canDash = true;
|
||
canDodge = true;
|
||
canJump = true;
|
||
maxJumpCount = 1;
|
||
currentJumpCount = 0;
|
||
isApplyingGravity = true;
|
||
|
||
characterTransform = character.transform;
|
||
|
||
if (owner is Player)
|
||
{
|
||
var groundMasks = LayerMask.GetMask("Default", "Enemy", "Wall", "Ground", "FadableEnvironment", "UnfadableEnvironment");
|
||
groundDetector ??= new GroundDetector(owner, 0.1f, 0.1f, 0.05f, groundMasks);
|
||
}
|
||
else
|
||
{
|
||
groundDetector ??= new GroundDetector(owner, 0.1f, 0.1f, 0.05f,
|
||
LayerMask.GetMask("Default", "Wall", "Ground", "FadableEnvironment", "UnfadableEnvironment"));
|
||
}
|
||
}
|
||
|
||
public void SmartTurnToTarget(CharacterBase target, float maxTurnAngle = 360f)
|
||
{
|
||
Vector3 directionToTarget = (target.centerPoint.position - owner.centerPoint.position).Flatten();
|
||
if (directionToTarget.sqrMagnitude < 0.001f) return;
|
||
|
||
float angleToTarget = Vector3.SignedAngle(owner.transform.forward, directionToTarget, Vector3.up);
|
||
float absAngle = Mathf.Abs(angleToTarget);
|
||
|
||
// 超过最大角度不转身
|
||
if (absAngle > maxTurnAngle) return;
|
||
|
||
// 小角度瞬间转身
|
||
if (absAngle <= 45f)
|
||
{
|
||
owner.transform.rotation = Quaternion.LookRotation(directionToTarget);
|
||
}
|
||
// 大角度平滑转身
|
||
else
|
||
{
|
||
float duration = Mathf.Lerp(0.1f, 0.2f, (absAngle - 45f) / 135f);
|
||
owner.transform.DORotateQuaternion(Quaternion.LookRotation(directionToTarget), duration).Play();
|
||
}
|
||
}
|
||
|
||
public void TurnToTargetByAngle(CharacterBase target, float angularSpeed)
|
||
{
|
||
Vector3 directionToTarget = (target.transform.position - characterTransform.position).Flatten();
|
||
if (directionToTarget == Vector3.zero) return;
|
||
|
||
float targetAngle = Mathf.Atan2(directionToTarget.x, directionToTarget.z) * Mathf.Rad2Deg;
|
||
float currentAngle = characterTransform.eulerAngles.y;
|
||
float newAngle = Mathf.MoveTowardsAngle(currentAngle, targetAngle, angularSpeed * DeltaTime);
|
||
characterTransform.rotation = Quaternion.Euler(0, newAngle, 0);
|
||
}
|
||
|
||
public void TurnToDirection(Vector3 direction, float duration = 0f)
|
||
{
|
||
Vector3 targetDirection = direction.Flatten();
|
||
if (targetDirection == Vector3.zero) return;
|
||
|
||
Quaternion targetRotation = Quaternion.LookRotation(targetDirection);
|
||
characterTransform.DORotateQuaternion(targetRotation, duration).Play();
|
||
}
|
||
}
|
||
|
||
public partial class MovementSubcontrollerBase
|
||
{
|
||
[TitleGroup("Ground")]
|
||
[Tooltip("留空以使用默认配置")]
|
||
public GroundDetector groundDetector;
|
||
public bool isOnGround;
|
||
|
||
[TitleGroup("XZ Movement")]
|
||
public CompoundBool canMove;
|
||
public bool is8WayMovement;
|
||
public float moveSpeed;
|
||
public float moveAcceleration;
|
||
public float moveDeceleration;
|
||
public bool isSprinting;
|
||
public float sprintSpeedMultiplier = 1.5f;
|
||
public float runningTime;
|
||
|
||
[TitleGroup("Y Movement & Jump")]
|
||
public bool canJump;
|
||
public int maxJumpCount;
|
||
/// <summary> 当前已使用的跳跃次数(含首次跳跃),落地时重置为 0。 </summary>
|
||
public int currentJumpCount;
|
||
public float jumpForce = 15f;
|
||
public float normalGravity = 40f;
|
||
public float jumpGravity = 60f;
|
||
public bool isStartJumping;
|
||
public bool isJumping;
|
||
public bool isExtraJumping;
|
||
public float jumpVelocity;
|
||
public float jumpTime;
|
||
public float jumpHeldTime;
|
||
public bool isJumpLanding;
|
||
|
||
[TitleGroup("Rush Stop")]
|
||
public bool isRushStopping;
|
||
public bool rushStopped;
|
||
|
||
[TitleGroup("Rotation")]
|
||
public CompoundBool canRotate;
|
||
public float targetRotation;
|
||
public Vector3 targetDirection;
|
||
public float rotationVelocity;
|
||
public float rotationSmoothTime;
|
||
|
||
|
||
[TitleGroup("Gravity")]
|
||
public bool isApplyingGravity;
|
||
public Vector3 currentGravity;
|
||
public float gravityMultiplier = 1;
|
||
|
||
[TitleGroup("Dash")]
|
||
public bool canDash;
|
||
public bool isDashing;
|
||
public bool afterDash;
|
||
public float dashMoveMultiplier = 3;
|
||
public float overrideDashMoveMultiplier = -1;
|
||
|
||
[TitleGroup("Dodge")]
|
||
public bool canDodge;
|
||
public bool isDodging;
|
||
public bool afterDodge;
|
||
public float dodgeMoveMultiplier = 1;
|
||
public float overrideDodgeMoveMultiplier = -1;
|
||
/// <summary> 闪避/冲刺间隔剩余冷却时间(秒),> 0 时禁止新的闪避/冲刺 </summary>
|
||
public float dodgeIntervalTimer;
|
||
|
||
[TitleGroup("Root Motion")]
|
||
public Vector3 rootMotionMultiplier = Vector3.one;
|
||
//public float rootMotionMoveXMultiplier = 1;
|
||
//public float rootMotionMoveYMultiplier = 1;
|
||
//public float rootMotionMoveZMultiplier = 1;
|
||
|
||
[TitleGroup("Final Movement Calculation")]
|
||
public Vector3 horizontalMovement;
|
||
public Vector3 verticalMovement;
|
||
public float verticalMoveMultiplier = 1;
|
||
public Vector3 jumpMovement;
|
||
public Vector3 gravitationalMovement;
|
||
public Vector3 initiativeMovementVelocity;
|
||
public Vector3 movementModifier;
|
||
public Vector3 finalMovementVelocity;
|
||
}
|
||
|
||
public partial class MovementSubcontrollerBase
|
||
{
|
||
public enum CharacterRotationType
|
||
{
|
||
ByAiming,
|
||
ByMovement,
|
||
}
|
||
}
|
||
} |