using DG.Tweening; using Sirenix.OdinInspector; using SLSFramework.General; using UnityEngine; using UnityEngine.Serialization; namespace Cielonos.MainGame.Characters { public partial class MovementSubcontrollerBase : SubcontrollerBase { protected CharacterBase character => owner; protected float DeltaTime => owner.selfTimeSm.DeltaTime; [Tooltip("角色旋转方式,ByMovement为ARPG式默认移动旋转,ByAiming为八向移动")] public CharacterRotationType rotationType; [HideInEditorMode] public Transform characterTransform; public override void Initialize() { base.Initialize(); canMove = new CompoundVariable(true); canRotate = new CompoundVariable(true); canDash = true; canDodge = true; canJump = true; maxJumpCount = 1; 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 TurnToTarget(CharacterBase target, float duration = 0.2f) { characterTransform.DOLookAt(target.transform.position, duration, AxisConstraint.Y); } public void TurnToDirection(Vector3 direction, float duration = 0f) { Vector3 dashRotation = Vector3.zero; float angle = Vector3.SignedAngle(Vector3.forward, direction, Vector3.up); if (owner is Player player) { dashRotation.y = player.viewSc.isLockedOn ? player.viewSc.cameraRotationSm.cinemachineEndLockYaw + angle : player.viewSc.cameraRotationSm.cinemachineTargetYaw + angle; } else { dashRotation = new Vector3(0, angle, 0); } if (duration > 0) { characterTransform.DORotateQuaternion(Quaternion.Euler(dashRotation), duration); } else { characterTransform.rotation = Quaternion.Euler(dashRotation); } } } public partial class MovementSubcontrollerBase { [TitleGroup("Ground")] [Tooltip("留空以使用默认配置")] public GroundDetector groundDetector; public bool isOnGround; [TitleGroup("Movement")] public CompoundVariable canMove; public float moveSpeed; public float moveAcceleration; public float moveDeceleration; public bool isSprinting; public float sprintSpeedMultiplier = 1.5f; public float runningTime; [TitleGroup("Rush Stop")] public bool isRushStopping; public bool rushStopped; [TitleGroup("Rotation")] public CompoundVariable canRotate; public float targetRotation; public Vector3 targetDirection; public float rotationVelocity; public float rotationSmoothTime; [TitleGroup("Jump")] public bool canJump; public int maxJumpCount; public bool isJumping; public bool isExtraJumping; public float jumpVelocity; public float jumpTime; public float jumpHeldTime; public bool isJumpLanding; [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; [TitleGroup("Dodge")] public bool canDodge; public bool isDodging; public bool afterDodge; public float dodgeMoveMultiplier = 1; [TitleGroup("Root Motion")] public float rootMotionMoveXMultiplier = 1; public float rootMotionMoveYMultiplier = 1; public float rootMotionMoveZMultiplier = 1; [TitleGroup("Final Movement Calculation")] public Vector3 horizontalMovement; public float verticalMovement; public Vector3 gravitationalMovement; public Vector3 initiativeMovementVelocity; public Vector3 movementModifier; public Vector3 finalMovementVelocity; [TitleGroup("Temporary Variables")] public float jumpForce = 15f; public float jumpGravity = 60f; } public partial class MovementSubcontrollerBase { public enum CharacterRotationType { ByAiming, ByMovement, } } }