feat(): 大量更新
This commit is contained in:
101
Assets/Script/Gameplay/Player/PlayerCameraController.cs
Normal file
101
Assets/Script/Gameplay/Player/PlayerCameraController.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2525a4f94ebe4e789ed375bd17d6a1a7
|
||||
timeCreated: 1760424747
|
||||
9
Assets/Script/Gameplay/Player/PlayerConfig.cs
Normal file
9
Assets/Script/Gameplay/Player/PlayerConfig.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Gameplay.Player
|
||||
{
|
||||
public class PlayerConfig : MonoBehaviour
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
3
Assets/Script/Gameplay/Player/PlayerConfig.cs.meta
Normal file
3
Assets/Script/Gameplay/Player/PlayerConfig.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6ff9e093e80541dc93d1186499dbfd79
|
||||
timeCreated: 1760498762
|
||||
92
Assets/Script/Gameplay/Player/PlayerController.cs
Normal file
92
Assets/Script/Gameplay/Player/PlayerController.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Script/Gameplay/Player/PlayerController.cs.meta
Normal file
3
Assets/Script/Gameplay/Player/PlayerController.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d7071907d14f433789ea37a8367b584a
|
||||
timeCreated: 1760495717
|
||||
58
Assets/Script/Gameplay/Player/PlayerInteractorController.cs
Normal file
58
Assets/Script/Gameplay/Player/PlayerInteractorController.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dc03712b5c254b8380471356f3bac151
|
||||
timeCreated: 1760516273
|
||||
89
Assets/Script/Gameplay/Player/PlayerMoveController.cs
Normal file
89
Assets/Script/Gameplay/Player/PlayerMoveController.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 14c86d6b22344680a9eba4de056d3b53
|
||||
timeCreated: 1760424128
|
||||
Reference in New Issue
Block a user