2025-08-28 16:20:24 +08:00
|
|
|
|
using System.Collections.Generic;
|
2025-09-28 15:02:57 +08:00
|
|
|
|
using Base;
|
2025-10-10 14:08:23 +08:00
|
|
|
|
using Managers;
|
|
|
|
|
|
using Prefab;
|
2025-07-21 13:58:58 +08:00
|
|
|
|
using UnityEngine;
|
2025-07-25 19:16:58 +08:00
|
|
|
|
using UnityEngine.Events;
|
2025-10-10 14:08:23 +08:00
|
|
|
|
using Utils;
|
2025-07-21 13:58:58 +08:00
|
|
|
|
|
|
|
|
|
|
namespace Entity
|
|
|
|
|
|
{
|
2025-07-25 19:16:58 +08:00
|
|
|
|
public class Outline : MonoBehaviour
|
2025-07-21 13:58:58 +08:00
|
|
|
|
{
|
2025-10-10 14:08:23 +08:00
|
|
|
|
// 边界的最小尺寸
|
|
|
|
|
|
public static readonly Vector2 MinimumBoundsSize = new(0.5f, 0.5f);
|
|
|
|
|
|
|
2025-10-03 00:31:34 +08:00
|
|
|
|
// 实体身体的游戏对象
|
2025-07-21 13:58:58 +08:00
|
|
|
|
public GameObject body;
|
2025-10-03 00:31:34 +08:00
|
|
|
|
|
|
|
|
|
|
// 描边渲染器
|
2025-07-21 13:58:58 +08:00
|
|
|
|
public SpriteRenderer outlineRenderer;
|
2025-10-03 00:31:34 +08:00
|
|
|
|
|
|
|
|
|
|
// 描边碰撞体
|
2025-07-21 13:58:58 +08:00
|
|
|
|
public CapsuleCollider2D outlineCollider;
|
2025-10-03 00:31:34 +08:00
|
|
|
|
|
|
|
|
|
|
// 进度条预制件
|
2025-08-19 20:22:10 +08:00
|
|
|
|
public ProgressBarPrefab progressBarPrefab;
|
2025-07-21 13:58:58 +08:00
|
|
|
|
|
2025-10-03 00:31:34 +08:00
|
|
|
|
// 关联的实体
|
2025-07-25 19:16:58 +08:00
|
|
|
|
public Entity entity;
|
2025-08-28 16:20:24 +08:00
|
|
|
|
|
2025-10-03 00:31:34 +08:00
|
|
|
|
// 缓存身体纹理大小
|
|
|
|
|
|
private Vector2 _cachedBodyTextureSize;
|
|
|
|
|
|
|
|
|
|
|
|
// 缓存碰撞体大小
|
|
|
|
|
|
private Vector2 _cachedColliderSize;
|
|
|
|
|
|
|
|
|
|
|
|
// 缓存碰撞体偏移
|
|
|
|
|
|
private Vector2 _cachedOffset;
|
|
|
|
|
|
|
|
|
|
|
|
// 缓存是否已初始化标志 (明确它管理的是数据缓存状态)
|
|
|
|
|
|
private bool _isDataCacheInitialized; // 修改部分1:变量更名
|
2025-07-25 19:16:58 +08:00
|
|
|
|
|
2025-10-03 00:31:34 +08:00
|
|
|
|
// 是否可以显示描边
|
|
|
|
|
|
public bool CanShow => Setting.Instance.CurrentSettings.developerMode && entity.canSelect &&
|
|
|
|
|
|
!UIInputControl.Instance.HasWindowOpen;
|
2025-09-28 15:02:57 +08:00
|
|
|
|
|
2025-10-03 00:31:34 +08:00
|
|
|
|
/// <summary>
|
2025-10-10 14:08:23 +08:00
|
|
|
|
/// 当鼠标进入描边区域时调用。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
protected virtual void OnMouseEnter()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!CanShow)
|
|
|
|
|
|
return;
|
|
|
|
|
|
Show();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 当鼠标离开描边区域时调用。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
protected virtual void OnMouseExit()
|
|
|
|
|
|
{
|
|
|
|
|
|
Hide();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 当鼠标停留在描边区域时每帧调用。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
protected virtual void OnMouseOver()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!Program.Instance.CanOpenRightMenu || !CanShow)
|
|
|
|
|
|
return;
|
|
|
|
|
|
// 检测是否按下的是鼠标右键
|
|
|
|
|
|
if (Input.GetMouseButtonDown(1)) RightMenuManager.GenerateRightMenu(GetMenu(), Input.mousePosition);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 确保描边尺寸相关数据缓存已初始化。如果未初始化,则会计算并缓存。
|
|
|
|
|
|
/// 此方法保证内部的尺寸计算只执行一次。
|
2025-10-03 00:31:34 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void EnsureDataCacheInitialized() // 修改部分2:新增私有方法
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_isDataCacheInitialized) return; // 如果数据缓存已初始化,则直接返回
|
|
|
|
|
|
// 计算并缓存所有必要尺寸
|
|
|
|
|
|
_cachedBodyTextureSize = CalculateBodyTextureSize();
|
|
|
|
|
|
_cachedColliderSize = CalculateColliderSize();
|
|
|
|
|
|
_cachedOffset = CalculateOffset();
|
|
|
|
|
|
_isDataCacheInitialized = true; // 标记数据缓存已初始化
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2025-10-10 14:08:23 +08:00
|
|
|
|
/// 初始化描边,将计算出的尺寸应用于描边渲染器、碰撞体和进度条。
|
|
|
|
|
|
/// 此方法确保数据缓存已初始化,并可以被重复调用以重新应用设置。
|
2025-10-03 00:31:34 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
public virtual void Init() // 修改部分4:修改 Init 方法
|
2025-07-21 13:58:58 +08:00
|
|
|
|
{
|
2025-10-03 00:31:34 +08:00
|
|
|
|
// 首先确保尺寸数据是可用的。这个调用会立即返回如果数据缓存已初始化。
|
|
|
|
|
|
EnsureDataCacheInitialized();
|
|
|
|
|
|
// 使用缓存值设置OutlineRenderer
|
|
|
|
|
|
outlineRenderer.size = _cachedBodyTextureSize;
|
|
|
|
|
|
// 使用缓存值设置OutlineCollider
|
|
|
|
|
|
var colliderSize = _cachedColliderSize; // 使用缓存值
|
|
|
|
|
|
outlineCollider.direction = colliderSize.x > colliderSize.y
|
|
|
|
|
|
? CapsuleDirection2D.Horizontal
|
|
|
|
|
|
: CapsuleDirection2D.Vertical;
|
|
|
|
|
|
outlineCollider.size = colliderSize;
|
|
|
|
|
|
outlineCollider.offset = _cachedOffset; // 使用缓存值
|
|
|
|
|
|
// 使用缓存值调整ProgressBarPrefab
|
2025-08-19 20:22:10 +08:00
|
|
|
|
if (progressBarPrefab)
|
|
|
|
|
|
{
|
2025-10-03 00:31:34 +08:00
|
|
|
|
// 确保每次 Init 调用都能正确设置位置而不重复累加。
|
|
|
|
|
|
progressBarPrefab.transform.localPosition =
|
|
|
|
|
|
new Vector3(0f, colliderSize.y * 2 / 3, 0f); // 逻辑修改:将 += 改为 =
|
|
|
|
|
|
progressBarPrefab.transform.localScale = new Vector3(colliderSize.x, 1f / 10f, 1);
|
2025-08-19 20:22:10 +08:00
|
|
|
|
}
|
2025-07-21 13:58:58 +08:00
|
|
|
|
}
|
2025-07-25 19:16:58 +08:00
|
|
|
|
|
2025-10-03 00:31:34 +08:00
|
|
|
|
/// <summary>
|
2025-10-10 14:08:23 +08:00
|
|
|
|
/// 显示描边。
|
2025-10-03 00:31:34 +08:00
|
|
|
|
/// </summary>
|
2025-07-21 13:58:58 +08:00
|
|
|
|
public void Show()
|
|
|
|
|
|
{
|
2025-10-03 00:31:34 +08:00
|
|
|
|
if (CanShow)
|
|
|
|
|
|
outlineRenderer.enabled = true;
|
2025-07-21 13:58:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-03 00:31:34 +08:00
|
|
|
|
/// <summary>
|
2025-10-10 14:08:23 +08:00
|
|
|
|
/// 隐藏描边。
|
2025-10-03 00:31:34 +08:00
|
|
|
|
/// </summary>
|
2025-07-21 13:58:58 +08:00
|
|
|
|
public void Hide()
|
|
|
|
|
|
{
|
2025-07-25 19:16:58 +08:00
|
|
|
|
outlineRenderer.enabled = false;
|
2025-07-21 13:58:58 +08:00
|
|
|
|
}
|
2025-07-25 19:16:58 +08:00
|
|
|
|
|
2025-07-21 13:58:58 +08:00
|
|
|
|
/// <summary>
|
2025-10-10 14:08:23 +08:00
|
|
|
|
/// 获取当前实体的碰撞体大小。在首次调用时自动计算并缓存。
|
2025-10-03 00:31:34 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns>碰撞体大小的Vector2。</returns>
|
|
|
|
|
|
public Vector2 GetColliderSize() // 修改部分3:修改 GetColliderSize 方法
|
|
|
|
|
|
{
|
|
|
|
|
|
EnsureDataCacheInitialized(); // 确保数据缓存已初始化
|
|
|
|
|
|
return _cachedColliderSize;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2025-10-10 14:08:23 +08:00
|
|
|
|
/// 获取身体的纹理总大小。在首次调用时自动计算并缓存。
|
2025-10-03 00:31:34 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns>身体纹理大小的Vector2。</returns>
|
|
|
|
|
|
public Vector2 GetBodyTextureSize() // 修改部分3:修改 GetBodyTextureSize 方法
|
|
|
|
|
|
{
|
|
|
|
|
|
EnsureDataCacheInitialized(); // 确保数据缓存已初始化
|
|
|
|
|
|
return _cachedBodyTextureSize;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2025-10-10 14:08:23 +08:00
|
|
|
|
/// 获取当前实体的碰撞体偏移。在首次调用时自动计算并缓存。
|
2025-07-21 13:58:58 +08:00
|
|
|
|
/// </summary>
|
2025-10-03 00:31:34 +08:00
|
|
|
|
/// <returns>碰撞体偏移的Vector2。</returns>
|
|
|
|
|
|
public Vector2 GetOffset() // 修改部分3:修改 GetOffset 方法
|
2025-09-28 15:02:57 +08:00
|
|
|
|
{
|
2025-10-03 00:31:34 +08:00
|
|
|
|
EnsureDataCacheInitialized(); // 确保数据缓存已初始化
|
|
|
|
|
|
return _cachedOffset;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2025-10-10 14:08:23 +08:00
|
|
|
|
/// 计算并返回碰撞体大小。此方法是内部实现细节。
|
2025-10-03 00:31:34 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns>碰撞体大小的Vector2。</returns>
|
|
|
|
|
|
private Vector2 CalculateColliderSize()
|
|
|
|
|
|
{
|
|
|
|
|
|
return !string.IsNullOrEmpty(entity.entityDef?.colliderSize)
|
2025-10-10 14:08:23 +08:00
|
|
|
|
? StringUtils.StringToVector2(entity.entityDef.colliderSize)
|
2025-10-03 00:31:34 +08:00
|
|
|
|
: CalculateBodyTextureSize();
|
2025-09-28 15:02:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-03 00:31:34 +08:00
|
|
|
|
/// <summary>
|
2025-10-10 14:08:23 +08:00
|
|
|
|
/// 计算并返回身体纹理的总大小。此方法是内部实现细节。
|
2025-10-03 00:31:34 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns>身体纹理总大小的Vector2。</returns>
|
|
|
|
|
|
private Vector2 CalculateBodyTextureSize()
|
2025-07-21 13:58:58 +08:00
|
|
|
|
{
|
2025-08-07 16:44:43 +08:00
|
|
|
|
// 获取所有子对象的 Renderer 组件
|
2025-10-03 00:31:34 +08:00
|
|
|
|
var renderers = body.GetComponentsInChildren<Renderer>(true);
|
|
|
|
|
|
// 如果没有找到任何 Renderer,返回一个默认值
|
2025-10-10 14:08:23 +08:00
|
|
|
|
if (renderers.Length == 0) return MinimumBoundsSize;
|
2025-07-25 19:16:58 +08:00
|
|
|
|
|
2025-08-07 16:44:43 +08:00
|
|
|
|
// 初始化 totalBounds 为第一个 Renderer 的 bounds
|
2025-07-21 13:58:58 +08:00
|
|
|
|
var totalBounds = renderers[0].bounds;
|
2025-08-07 16:44:43 +08:00
|
|
|
|
// 遍历剩余的 Renderer,将它们的 bounds 合并到 totalBounds 中
|
2025-10-10 14:08:23 +08:00
|
|
|
|
for (var i = 1; i < renderers.Length; i++) totalBounds.Encapsulate(renderers[i].bounds);
|
2025-07-25 19:16:58 +08:00
|
|
|
|
|
2025-10-03 00:31:34 +08:00
|
|
|
|
// 获取合并后的包围盒的XY大小
|
|
|
|
|
|
var size = new Vector2(totalBounds.size.x, totalBounds.size.y);
|
|
|
|
|
|
// 确保每个维度的大小都不小于最小限制
|
|
|
|
|
|
size.x = Mathf.Max(size.x, MinimumBoundsSize.x);
|
|
|
|
|
|
size.y = Mathf.Max(size.y, MinimumBoundsSize.y);
|
2025-07-21 13:58:58 +08:00
|
|
|
|
return size;
|
|
|
|
|
|
}
|
2025-07-25 19:16:58 +08:00
|
|
|
|
|
2025-10-03 00:31:34 +08:00
|
|
|
|
/// <summary>
|
2025-10-10 14:08:23 +08:00
|
|
|
|
/// 计算并返回碰撞体偏移。此方法是内部实现细节。
|
2025-10-03 00:31:34 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns>碰撞体偏移的Vector2。</returns>
|
|
|
|
|
|
private Vector2 CalculateOffset()
|
2025-07-25 19:16:58 +08:00
|
|
|
|
{
|
2025-10-03 00:31:34 +08:00
|
|
|
|
return string.IsNullOrEmpty(entity.entityDef?.colliderPosition)
|
2025-09-28 15:02:57 +08:00
|
|
|
|
? Vector2.zero
|
2025-10-10 14:08:23 +08:00
|
|
|
|
: StringUtils.StringToVector2(entity.entityDef.colliderPosition);
|
2025-09-28 15:02:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-03 00:31:34 +08:00
|
|
|
|
/// <summary>
|
2025-10-10 14:08:23 +08:00
|
|
|
|
/// 获取右键菜单项列表。
|
2025-10-03 00:31:34 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns>包含菜单项名称和对应回调函数的列表。</returns>
|
2025-09-28 15:02:57 +08:00
|
|
|
|
protected virtual List<(string name, UnityAction callback)> GetMenu()
|
2025-07-25 19:16:58 +08:00
|
|
|
|
{
|
|
|
|
|
|
var result = new List<(string name, UnityAction callback)>();
|
2025-08-07 16:44:43 +08:00
|
|
|
|
if (entity.PlayerControlled)
|
|
|
|
|
|
result.Add(("结束操控", EndControl));
|
2025-07-25 19:16:58 +08:00
|
|
|
|
else
|
2025-08-07 16:44:43 +08:00
|
|
|
|
result.Add(("手动操控", StartControl));
|
|
|
|
|
|
result.Add(("杀死", () => entity.Kill()));
|
|
|
|
|
|
result.Add(("变成笨蛋", BecomeDefault));
|
2025-07-25 19:16:58 +08:00
|
|
|
|
return result;
|
|
|
|
|
|
}
|
2025-08-07 16:44:43 +08:00
|
|
|
|
|
2025-10-03 00:31:34 +08:00
|
|
|
|
/// <summary>
|
2025-10-10 14:08:23 +08:00
|
|
|
|
/// 将当前实体变为默认实体。
|
2025-10-03 00:31:34 +08:00
|
|
|
|
/// </summary>
|
2025-09-28 15:02:57 +08:00
|
|
|
|
protected void BecomeDefault()
|
2025-08-07 16:44:43 +08:00
|
|
|
|
{
|
2025-10-03 00:31:34 +08:00
|
|
|
|
entity?.Kill();
|
2025-10-10 14:08:23 +08:00
|
|
|
|
if (entity)
|
2025-10-03 00:31:34 +08:00
|
|
|
|
EntityManager.Instance.GenerateDefaultEntity(Program.Instance.FocusedDimensionId, entity.Position);
|
2025-08-07 16:44:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-03 00:31:34 +08:00
|
|
|
|
/// <summary>
|
2025-10-10 14:08:23 +08:00
|
|
|
|
/// 开始玩家对实体的操控。
|
2025-10-03 00:31:34 +08:00
|
|
|
|
/// </summary>
|
2025-09-28 15:02:57 +08:00
|
|
|
|
protected void StartControl()
|
2025-08-07 16:44:43 +08:00
|
|
|
|
{
|
|
|
|
|
|
entity.PlayerControlled = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-03 00:31:34 +08:00
|
|
|
|
/// <summary>
|
2025-10-10 14:08:23 +08:00
|
|
|
|
/// 结束玩家对实体的操控。
|
2025-10-03 00:31:34 +08:00
|
|
|
|
/// </summary>
|
2025-09-28 15:02:57 +08:00
|
|
|
|
protected void EndControl()
|
2025-08-07 16:44:43 +08:00
|
|
|
|
{
|
|
|
|
|
|
entity.PlayerControlled = false;
|
|
|
|
|
|
}
|
2025-07-21 13:58:58 +08:00
|
|
|
|
}
|
2025-10-10 14:08:23 +08:00
|
|
|
|
}
|