Files
zeling_v2/Assets/_Game/Scripts/Player/PlayerWallDetector.cs

71 lines
2.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using UnityEngine;
namespace BaseGames.Player
{
/// <summary>
/// 独立墙壁检测组件(架构 05_PlayerModule §13
/// ⚠️ 不嵌入 PlayerMovement以保持单一职责。
/// 每侧发两根射线Top + Bottom两根均命中才视为接触墙壁防卡角误判
/// WallSlideState / WallJumpState 通过 PlayerController.WallDetector 访问。
/// </summary>
[RequireComponent(typeof(PlayerMovement))]
public class PlayerWallDetector : MonoBehaviour
{
[SerializeField] private PlayerMovementConfigSO _config;
[Header("墙壁 Layer默认使用 \"Wall\" + \"Ground\"")]
[SerializeField] private LayerMask _wallLayer;
/// <summary>当前是否正在触碰墙壁。</summary>
public bool IsTouchingWall { get; private set; }
/// <summary>触碰到的墙壁方向:+1 = 右墙,-1 = 左墙0 = 无墙。</summary>
public int WallDirection { get; private set; }
private void Awake()
{
Debug.Assert(_config != null, "[PlayerWallDetector] _config 未赋值,请在 Inspector 中指定 PlayerMovementConfigSO。", this);
}
private void FixedUpdate()
{
bool rightWall = CheckSide(Vector2.right);
bool leftWall = CheckSide(Vector2.left);
IsTouchingWall = rightWall || leftWall;
WallDirection = rightWall ? 1 : (leftWall ? -1 : 0);
}
/// <summary>
/// 每侧发两根射线TopRay + BottomRay两根均命中才返回 true。
/// </summary>
private bool CheckSide(Vector2 dir)
{
Vector2 center = transform.position;
float len = _config.WallRayLength;
float oy = _config.WallRayOffsetY;
int layer = _wallLayer != 0 ? (int)_wallLayer : LayerMask.GetMask("Wall", "Ground");
bool top = Physics2D.Raycast(center + Vector2.up * oy, dir, len, layer);
bool bot = Physics2D.Raycast(center + Vector2.down * oy, dir, len, layer);
return top && bot;
}
private void OnDrawGizmosSelected()
{
if (_config == null) return;
float len = _config.WallRayLength;
float oy = _config.WallRayOffsetY;
Vector2 center = transform.position;
Gizmos.color = IsTouchingWall ? Color.red : Color.cyan;
// 右侧两根射线
Gizmos.DrawRay(center + Vector2.up * oy, Vector2.right * len);
Gizmos.DrawRay(center + Vector2.down * oy, Vector2.right * len);
// 左侧两根射线
Gizmos.DrawRay(center + Vector2.up * oy, Vector2.left * len);
Gizmos.DrawRay(center + Vector2.down * oy, Vector2.left * len);
}
}
}