feat(): 大量更新

This commit is contained in:
2025-10-15 21:31:13 +08:00
parent 546f08c53a
commit 668bfe12eb
178 changed files with 11318 additions and 446 deletions

View File

@@ -0,0 +1,101 @@
using Core;
using UnityEngine;
using Input;
namespace Gameplay.Player
{
/// <summary>
/// 玩家第一人称相机控制器
/// 挂到相机或相机父物体playerBody 指向角色的根 Transform用于左右旋转
/// </summary>
public class PlayerCameraController : MonoBehaviour
{
[Header("References")]
[Tooltip("角色根 Transform用于水平旋转yaw")]
public Transform playerBody;
[Tooltip("如果相机不是挂载在同一物体上,可以指定相机 Transform可选")]
public Transform cameraTransform;
[Header("Sensitivity & Invert")]
[Tooltip("鼠标灵敏度")]
[Range(0.01f, 1f)]
public float mouseSensitivity = 0.2f;
[Tooltip("反转垂直轴")]
public bool invertY = false;
[Header("Vertical Limits")]
[Tooltip("向上最大仰角(度)")]
public float maxUpAngle = 60f;
[Tooltip("向下最大俯角(度)")]
public float maxDownAngle = 60f;
[Header("Smoothing")]
public bool enableSmoothing = false;
[Tooltip("旋转平滑时间(秒)")]
public float smoothTime = 0.05f;
// internal state
private float xRotation = 0f; // 垂直角pitch
private float yaw = 0f; // 水平角yaw
private float smoothVelocityPitch = 0f;
private float smoothVelocityYaw = 0f;
void Start()
{
if (cameraTransform == null)
cameraTransform = transform;
// 初始化当前角度以避免跳变
Vector3 euler = cameraTransform.localEulerAngles;
xRotation = NormalizeAngle(euler.x);
yaw = NormalizeAngle(playerBody ? playerBody.eulerAngles.y : transform.eulerAngles.y);
}
void Update()
{
Vector2 mouse = InputManager.Instance.Look;
// ✅ 不要乘 Time.deltaTime因为 Look 已经是每帧的增量
float mouseX = mouse.x * mouseSensitivity;
float mouseY = mouse.y * mouseSensitivity;
float invert = invertY ? 1f : -1f;
yaw += mouseX;
xRotation += mouseY * invert;
// 限制垂直角度
xRotation = Mathf.Clamp(xRotation, -maxDownAngle, maxUpAngle);
if (enableSmoothing)
{
float smoothPitch = Mathf.SmoothDampAngle(cameraTransform.localEulerAngles.x, xRotation, ref smoothVelocityPitch, smoothTime);
float smoothYaw = Mathf.SmoothDampAngle(playerBody ? playerBody.eulerAngles.y : transform.eulerAngles.y, yaw, ref smoothVelocityYaw, smoothTime);
cameraTransform.localRotation = Quaternion.Euler(smoothPitch, 0f, 0f);
if (playerBody)
playerBody.rotation = Quaternion.Euler(0f, smoothYaw, 0f);
else
transform.rotation = Quaternion.Euler(0f, smoothYaw, 0f);
}
else
{
cameraTransform.localRotation = Quaternion.Euler(xRotation, 0f, 0f);
if (playerBody)
playerBody.rotation = Quaternion.Euler(0f, yaw, 0f);
else
transform.rotation = Quaternion.Euler(0f, yaw, 0f);
}
}
// 将角度规范到 [-180,180] 范围,避免插值跳变
private float NormalizeAngle(float angle)
{
angle = (angle + 180f) % 360f - 180f;
return angle;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2525a4f94ebe4e789ed375bd17d6a1a7
timeCreated: 1760424747

View File

@@ -0,0 +1,9 @@
using UnityEngine;
namespace Gameplay.Player
{
public class PlayerConfig : MonoBehaviour
{
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6ff9e093e80541dc93d1186499dbfd79
timeCreated: 1760498762

View File

@@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Gameplay;
using Share;
using UnityEngine;
using Core;
namespace Gameplay.Player
{
public class PlayerController : MonoBehaviour, ICharacter
{
public int MaxHealth { get; set; } = 100;
public int CurrentHealth { get; private set; }
[SerializeField] private CardBookData cardBookData;
public CardBook MyCardBook { get; private set; }
public List<Card> Cards { get; private set; }
private int currentCardIndex = 0;
public bool IsFlight { get; private set; }
public bool IsDead { get; private set; }
private PlayerMoveController playerMoveController;
private PlayerCameraController playerCameraController;
private void Awake()
{
playerMoveController = GetComponent<PlayerMoveController>();
playerCameraController = GetComponent<PlayerCameraController>();
CurrentHealth = MaxHealth;
MyCardBook = new CardBook(cardBookData);
Cards = new List<Card>();
UIViewerControllerLocator.Instance.Register(this);
}
private void Start()
{
}
public void TakeDamage(int damage)
{
CurrentHealth -= damage;
}
public void Heal(int heal)
{
CurrentHealth += heal;
if (CurrentHealth > MaxHealth)
{
CurrentHealth = MaxHealth;
}
}
public void StartCombat()
{
Debug.Log("Player StartCombat");
IsFlight = true;
playerMoveController.SetSpeed(0.5f);
}
public void EndFlight()
{
Debug.Log("Player EndFlight");
IsFlight = false;
playerMoveController.ResetSpeed();
}
public bool HasCardsLeft()
{
return currentCardIndex < Cards.Count;
}
public Card GetNextCard()
{
if (!HasCardsLeft())
{
return null;
}
return Cards[currentCardIndex++];
}
public void InitializeDeckCycle()
{
Cards = MyCardBook.GetCards().ToList();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d7071907d14f433789ea37a8367b584a
timeCreated: 1760495717

View File

@@ -0,0 +1,58 @@
using UnityEngine;
using Share;
using System;
using Input;
namespace Gameplay.Player
{
public class PlayerInteractorController : MonoBehaviour
{
[SerializeField] private float interactRange = 15f;
[SerializeField] private LayerMask interactableLayer;
[SerializeField] private Camera playerCamera;
private IInteractable currentTarget;
void Start()
{
playerCamera = GameObject.FindWithTag("MainCamera").GetComponent<Camera>();
}
void Update()
{
DetectInteractable();
if (currentTarget != null && InputManager.Instance.InteractPressed)
{
currentTarget.Interact(this.gameObject);
}
}
void DetectInteractable()
{
Ray ray = new Ray(playerCamera.transform.position, playerCamera.transform.forward);
if (Physics.Raycast(ray, out RaycastHit hit, interactRange, interactableLayer))
{
currentTarget = hit.collider.GetComponent<IInteractable>();
if (currentTarget != null)
{
// 这里可以显示交互提示UI例如 “E - 开门”
Debug.Log(currentTarget.GetInteractPrompt());
}
}
else
{
currentTarget = null;
}
}
void OnDrawGizmos()
{
if (playerCamera == null) return;
Gizmos.color = Color.green;
Vector3 origin = playerCamera.transform.position;
Vector3 direction = playerCamera.transform.forward * interactRange;
Gizmos.DrawLine(origin, origin + direction);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: dc03712b5c254b8380471356f3bac151
timeCreated: 1760516273

View File

@@ -0,0 +1,89 @@
using System;
using Core;
using Input;
using Map;
using UnityEngine;
namespace Gameplay.Player
{
public class PlayerMoveController : MonoBehaviour
{
[Header("Movement Settings")]
[Tooltip("移动速度(米/秒)")]
public float speed = 5f;
[Tooltip("跳跃高度(米)")]
public float jumpHeight = 2f;
[Tooltip("重力加速度(米/秒²)")]
public float gravity = -9.81f;
[Header("Ground Check")]
[Tooltip("检测地面的位置(通常为角色脚下)")]
public Transform groundCheck;
[Tooltip("地面检测半径")]
public float groundDistance = 0.4f;
[Tooltip("地面层LayerMask")]
public LayerMask groundMask;
private float initSpeed;
private CharacterController characterController;
private Vector3 velocity;
private bool isGrounded;
private IInputManager inputManager;
private void Awake()
{
characterController = GetComponent<CharacterController>();
if (characterController == null)
Debug.LogError("PlayerMoveController 需要 CharacterController 组件!");
initSpeed = speed;
}
private void Start()
{
inputManager = InputManager.Instance;
}
private void Update()
{
// 地面检测
if (groundCheck != null)
isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
else
isGrounded = characterController.isGrounded;
if (isGrounded && velocity.y < 0)
velocity.y = -2f; // 保持贴地
Vector2 inputMove = inputManager.Move;
// 获取输入
float x = inputMove.x;
float z = inputMove.y;
// 按玩家朝向移动
Vector3 move = transform.right * x + transform.forward * z;
characterController.Move(move * speed * Time.deltaTime);
// 跳跃
if (isGrounded && inputManager.JumpPressed)
{
velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
}
// 重力
velocity.y += gravity * Time.deltaTime;
characterController.Move(velocity * Time.deltaTime);
}
public void SetSpeed(float newSpeed)
{
speed = newSpeed;
}
public void ResetSpeed()
{
speed = initSpeed;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 14c86d6b22344680a9eba4de056d3b53
timeCreated: 1760424128