using UnityEngine;
namespace AibisDream
{
///
/// 矩形区域组件
/// 用于划定一个矩形区域,并判断点是否在区域内
///
public class BoxArea : MonoBehaviour
{
[Header("Box尺寸设置")]
[SerializeField] private float width = 10f;
[SerializeField] private float height = 10f;
[Header("原点位置设置")]
[Tooltip("设置(0,0)点在Box中的位置")]
[SerializeField] private AnchorPoint anchorPoint = AnchorPoint.Center;
///
/// Box的宽度
///
public float Width
{
get => width;
set => width = value;
}
///
/// Box的高度
///
public float Height
{
get => height;
set => height = value;
}
///
/// 锚点位置
///
public AnchorPoint AnchorPoint
{
get => anchorPoint;
set => anchorPoint = value;
}
///
/// 获取Box的世界坐标边界
///
public Bounds WorldBounds
{
get
{
Vector3 center = GetWorldCenter();
Vector3 size = new Vector3(width, height, 0f);
return new Bounds(center, size);
}
}
///
/// 获取Box的本地坐标边界
///
public Rect LocalRect
{
get
{
Vector2 offset = GetAnchorOffset();
return new Rect(offset.x, offset.y, width, height);
}
}
///
/// 判断给定的世界坐标位置是否在Box内
///
/// 世界坐标位置
/// 如果位置在Box内返回true,否则返回false
public bool Contains(Vector3 worldPosition)
{
// 将世界坐标转换为本地坐标
Vector3 localPosition = transform.InverseTransformPoint(worldPosition);
// 获取本地坐标的矩形区域
Rect rect = LocalRect;
// 判断点是否在矩形内(只考虑X和Y轴,忽略Z轴)
return rect.Contains(new Vector2(localPosition.x, localPosition.y));
}
///
/// 判断给定的本地坐标位置是否在Box内
///
/// 本地坐标位置
/// 如果位置在Box内返回true,否则返回false
public bool ContainsLocal(Vector2 localPosition)
{
Rect rect = LocalRect;
return rect.Contains(localPosition);
}
///
/// 获取Box的世界坐标中心点
///
private Vector3 GetWorldCenter()
{
Vector2 anchorOffset = GetAnchorOffset();
Vector3 localCenter = new Vector3(anchorOffset.x + width * 0.5f, anchorOffset.y + height * 0.5f, 0f);
return transform.TransformPoint(localCenter);
}
///
/// 根据锚点位置获取偏移量
///
private Vector2 GetAnchorOffset()
{
return anchorPoint switch
{
AnchorPoint.BottomLeft => new Vector2(0f, 0f),
AnchorPoint.BottomCenter => new Vector2(-width * 0.5f, 0f),
AnchorPoint.BottomRight => new Vector2(-width, 0f),
AnchorPoint.CenterLeft => new Vector2(0f, -height * 0.5f),
AnchorPoint.Center => new Vector2(-width * 0.5f, -height * 0.5f),
AnchorPoint.CenterRight => new Vector2(-width, -height * 0.5f),
AnchorPoint.TopLeft => new Vector2(0f, -height),
AnchorPoint.TopCenter => new Vector2(-width * 0.5f, -height),
AnchorPoint.TopRight => new Vector2(-width, -height),
_ => new Vector2(-width * 0.5f, -height * 0.5f)
};
}
#if UNITY_EDITOR
///
/// 在Scene视图中绘制Box边界(选中时)
///
private void OnDrawGizmos()
{
// 保存原始颜色
Color originalColor = Gizmos.color;
// 设置Box边界颜色
Gizmos.color = Color.cyan;
// 获取Box的四个角点(世界坐标)
Vector2 offset = GetAnchorOffset();
Vector3[] corners = new Vector3[4]
{
transform.TransformPoint(new Vector3(offset.x, offset.y, 0f)), // 左下角
transform.TransformPoint(new Vector3(offset.x + width, offset.y, 0f)), // 右下角
transform.TransformPoint(new Vector3(offset.x + width, offset.y + height, 0f)), // 右上角
transform.TransformPoint(new Vector3(offset.x, offset.y + height, 0f)) // 左上角
};
// 绘制Box边界线
for (int i = 0; i < 4; i++)
{
int next = (i + 1) % 4;
Gizmos.DrawLine(corners[i], corners[next]);
}
// 绘制中心点标记
Gizmos.color = Color.green;
Vector3 center = GetWorldCenter();
Gizmos.DrawWireSphere(center, 0.15f);
// 恢复原始颜色
Gizmos.color = originalColor;
}
#endif
}
///
/// 锚点位置枚举
/// 定义(0,0)点在Box中的位置
///
public enum AnchorPoint
{
[Tooltip("左下角")]
BottomLeft,
[Tooltip("底部中心")]
BottomCenter,
[Tooltip("右下角")]
BottomRight,
[Tooltip("左侧中心")]
CenterLeft,
[Tooltip("中心")]
Center,
[Tooltip("右侧中心")]
CenterRight,
[Tooltip("左上角")]
TopLeft,
[Tooltip("顶部中心")]
TopCenter,
[Tooltip("右上角")]
TopRight
}
}