(client) chore

This commit is contained in:
m0_75251201
2025-08-26 16:00:58 +08:00
parent efbf4f824a
commit f04c89046b
51 changed files with 2390 additions and 617 deletions

View File

@ -0,0 +1,27 @@
using Data;
namespace Entity
{
public class Attributes
{
public int health = 10;
public float moveSpeed = 1;
public int attack = 1;
public int defense = 0;
public int attackSpeed = 2;
public int attackRange = 3;
public int attackTargetCount = 1;
public Attributes(AttributesDef def)
{
health = def.health;
moveSpeed = def.moveSpeed;
attack = def.attack;
defense = def.defense;
attackSpeed = def.attackSpeed;
attackRange = def.attackRange;
attackTargetCount = def.attackTargetCount;
}
public Attributes()
{}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9a009acc975a4e4b993eaa4b853f7109
timeCreated: 1756184938

View File

@ -1,7 +1,4 @@
using System;
using System.Linq;
using AI;
using Base;
using Data;
using UnityEngine;
@ -9,20 +6,74 @@ namespace Entity
{
public class Character : Entity
{
public CharacterDef characterDef;
private void Start()
// ------------- 新增 / 修改部分 START -------------
// 声明 Inventory 字段。更改为 private set 以确保 Inventory 实例只能在 Character 内部设置。
public Inventory Inventory { get; private set; }
public override void Init(EntityDef entityDef)
{
aiTree = new JobGiver_RandomWander();
attributes = new AttributesDef();
base.Init(entityDef);
// 1. 初始化背包:
// 在这里创建并初始化 Inventory 实例。
// 'this' 指的是当前 Character 实例,作为 Inventory 的拥有者。
// 容量可以根据 entityDef 或一个默认值来设定。这里使用默认值 20。
Inventory = new Inventory(this, 3);
// (可选) 可以在此订阅背包事件,以便 Character 对背包变化做出响应,
// 例如更新角色状态、播放音效或更新UI。
// Inventory.OnItemAdded += HandleItemAddedToInventory;
// Inventory.OnItemRemoved += HandleItemRemovedFromInventory;
// Inventory.OnInventoryChanged += HandleInventoryChanged;
}
public void Init()
/// <summary>
/// 尝试将指定物品添加到角色的背包中。
/// </summary>
/// <param name="itemResource">要尝试添加的物品资源。</param>
/// <param name="quantity">要尝试添加的数量。</param>
/// <returns>未成功添加到背包的物品数量。
/// 如果返回0表示所有物品都成功添加
/// 如果返回quantity表示未能添加任何物品
/// 如果返回一个介于0和quantity之间的值表示部分物品被添加。</returns>
public int TryPickupItem(Item.ItemResource itemResource, int quantity)
{
if (characterDef == null)
return;
if (Inventory == null)
{
Debug.LogError($"Character '{this.name}' inventory is not initialized. Cannot pickup item.");
return quantity; // 如果背包未初始化,则视为未能添加任何物品
}
// 直接调用 Inventory 实例的 AddItem 方法。
// AddItem 方法已经包含了严谨的逻辑来处理物品堆叠、新槽位分配、容量检查以及无效输入的警告。
int remainingQuantity = Inventory.AddItem(itemResource, quantity);
return remainingQuantity;
}
// (可选) 示例事件处理方法,用于展示如何响应背包事件
// private void HandleItemAddedToInventory(Item.ItemResource item, int count)
// {
// Debug.Log($"{DefName} picked up {count} x {item.Name}. Current total: {Inventory.GetItemCount(item)}");
// // 例如更新UI、播放音效、完成任务等
// }
// private void HandleItemRemovedFromInventory(Item.ItemResource item, int count)
// {
// Debug.Log($"{DefName} removed {count} x {item.Name}. Current total: {Inventory.GetItemCount(item)}");
// // 例如更新UI、播放音效、更新制作状态等
// }
// private void HandleInventoryChanged()
// {
// Debug.Log($"{DefName}'s inventory changed. Occupied slots: {Inventory.OccupiedSlotsCount}/{Inventory.Capacity}");
// // 例如通知背包UI刷新显示
// }
// ------------- 新增 / 修改部分 END -------------
public override void TryAttack()
{
if (IsAttacking)
@ -35,4 +86,4 @@ namespace Entity
dir - Position, this);
}
}
}
}

View File

@ -7,7 +7,6 @@ using Base;
using Data;
using Prefab;
using UnityEngine;
using UnityEngine.Serialization;
namespace Entity
@ -29,7 +28,9 @@ namespace Entity
public ProgressBarPrefab healthBarPrefab;
public VisionRangeDetector visionRangeDetector;
public EntityPrefab entityPrefab;
public EntityDef entityDef;
/// <summary>
/// 人工智能行为树,定义实体的行为逻辑。
/// </summary>
@ -43,8 +44,7 @@ namespace Entity
/// <summary>
/// 实体的属性定义,包括生命值、攻击力、防御力等。
/// </summary>
public AttributesDef attributes = new();
public Attributes attributes=new();
/// <summary>
/// 实体当前的移动方向。
/// </summary>
@ -69,7 +69,8 @@ namespace Entity
/// 表示实体是否处于追逐状态(影响移动速度)。
/// </summary>
public bool IsChase { set; get; } = true;
public string currentDimensionId = null;
@ -149,7 +150,6 @@ namespace Entity
// 协程引用
private Coroutine _attackCoroutine;
protected EntityDef entityDef;
[SerializeField] private float _hitBarUIShowTime = 5;
@ -163,7 +163,7 @@ namespace Entity
/// <param name="entityDef">实体的定义数据。</param>
public virtual void Init(EntityDef entityDef)
{
attributes = entityDef.attributes.Clone();
attributes = new Attributes(entityDef.attributes);
aiTree = Utils.BehaviorTree.ConvertToAIBase(entityDef.behaviorTree);
affiliation = entityDef.affiliation?.defName;
InitBody(entityDef.drawingOrder);
@ -227,7 +227,7 @@ namespace Entity
var animators = targetObj.GetComponentsInChildren<SpriteAnimator>();
if (animators.Length > 0)
{
animatorsForOrientation.AddRange(animators.Cast<ITick>());
animatorsForOrientation.AddRange(animators);
}
stateAnimNodes[orientation] = animatorsForOrientation;
}

View File

@ -0,0 +1,24 @@
using Base;
using Data;
using Item;
using UnityEngine;
namespace Entity
{
public class Pickup:Entity
{
public ItemResource itemResource;
protected override void AutoBehave()
{
}
private void OnTriggerEnter2D(Collider2D other)
{
var entity = other.GetComponent<Character>();
if (entity == null) return;
if (entity.TryPickupItem(itemResource, 1) == 0)
{
Kill();
}
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4e65cb3d0f8440c599399cefd9a3a5d7
timeCreated: 1756191938

View File

@ -1,188 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using Data;
using Managers;
using UnityEngine;
namespace Entity
{
/// <summary>
/// 视野范围检测器组件。
/// 挂载到包含触发器碰撞体的GameObject上用于检测视野范围内的Entity。
/// </summary>
public class VisionRangeDetector : MonoBehaviour
{
// 允许在Inspector中手动指定Collider或在Awake时自动获取。
[SerializeField] [Tooltip("用于检测视野范围的触发器碰撞体。如果未指定将在Awake时自动获取。")]
private Collider2D _collider;
// 缓存所属的Entity组件用于获取派系信息。
private Entity _ownerEntity;
// 将List改为HashSet优化添加和移除的性能。
private HashSet<Entity> _entitiesInRange = new HashSet<Entity>(); // 维护在视野范围内的Entity集合
private Transform _myTransform; // 缓存Transform组件以提高性能
// 【逻辑修改】用于记录上次清理的帧数,避免在同一帧内重复清理。
private int _lastCleanupFrame = -1;
private void Awake()
{
_myTransform = transform; // 缓存自身Transform
// 1. 检查并确保GameObject上存在触发器碰撞体
if (_collider == null)
{
_collider = GetComponent<Collider2D>();
}
if (_collider == null)
{
Debug.LogError(
$"VisionRangeDetector on {gameObject.name} requires a Collider component. Please add one or assign it in the Inspector.",
this);
enabled = false; // 如果没有碰撞体,禁用此组件
return;
}
if (!_collider.isTrigger)
{
Debug.LogWarning(
$"VisionRangeDetector on {gameObject.name} works best with a Trigger Collider. Setting isTrigger to true.",
this);
_collider.isTrigger = true;
}
// 2. 检查AffiliationManager是否存在
if (AffiliationManager.Instance == null)
{
Debug.LogError(
"AffiliationManager.Instance is null. Please ensure an AffiliationManager exists in the scene.",
this);
enabled = false; // 如果没有派系管理器,禁用此组件
return; // 提前返回避免后续操作依赖于AffiliationManager
}
// 3. 获取所属的Entity组件并使用其affiliation。
_ownerEntity = GetComponentInParent<Entity>();
if (_ownerEntity == null)
{
_ownerEntity = GetComponent<Entity>();
}
if (_ownerEntity == null)
{
Debug.LogError(
$"VisionRangeDetector on {gameObject.name}: No Entity component found in parent or self. This component cannot determine its affiliation and will be disabled.",
this);
enabled = false;
return;
}
}
// 【逻辑修改】移除LateUpdate清理逻辑移至获取方法中。
// private void LateUpdate()
// {
// _entitiesInRange.RemoveWhere(e => e == null);
// }
/// <summary>
/// 【逻辑修改】在获取实体列表前,执行一次清理操作(每帧最多一次)。
/// </summary>
private void CleanEntitiesInRange()
{
// 只有当当前帧与上次清理的帧不同时才执行清理
if (Time.frameCount != _lastCleanupFrame)
{
_entitiesInRange.RemoveWhere(e => e == null);
_lastCleanupFrame = Time.frameCount; // 更新上次清理的帧数
// Debug.Log($"Cleaned _entitiesInRange in frame {Time.frameCount}. Current count: {_entitiesInRange.Count}");
}
}
/// <summary>
/// 当有其他碰撞体进入触发器范围时调用。
/// </summary>
/// <param name="other">进入触发器的碰撞体。</param>
private void OnTriggerEnter(Collider other)
{
Entity entity = other.GetComponent<Entity>();
if (entity != null)
{
if (entity.gameObject == _ownerEntity.gameObject || entity.transform.IsChildOf(_ownerEntity.transform))
{
return;
}
if (_entitiesInRange.Add(entity))
{
// Debug.Log($"Entity '{entity.name}' (Affiliation: {entity.affiliation}) entered range. Total: {_entitiesInRange.Count}");
}
}
}
/// <summary>
/// 当有其他碰撞体离开触发器范围时调用。
/// </summary>
/// <param name="other">离开触发器的碰撞体。</param>
private void OnTriggerExit(Collider other)
{
Entity entity = other.GetComponent<Entity>();
if (entity != null)
{
if (_entitiesInRange.Remove(entity))
{
// Debug.Log($"Entity '{entity.name}' (Affiliation: {entity.affiliation}) exited range. Total: {_entitiesInRange.Count}");
}
}
}
/// <summary>
/// 获取视野范围内最近的N个实体。
/// </summary>
/// <param name="n">要获取的实体数量。</param>
/// <returns>最近的N个实体列表。</returns>
public List<Entity> GetNearestNEntities(int n)
{
if (n <= 0) return new List<Entity>();
// 【逻辑修改】在获取前清理一次集合
CleanEntitiesInRange();
return _entitiesInRange
.OrderBy(e => Vector3.Distance(_myTransform.position, e.transform.position))
.Take(n)
.ToList();
}
/// <summary>
/// 获取视野范围内最近的N个指定关系的实体敌对、友好、中立
/// </summary>
/// <param name="n">要获取的实体数量。</param>
/// <param name="targetRelation">目标派系关系。</param>
/// <returns>最近的N个指定关系的实体列表。</returns>
public List<Entity> GetNearestNEntitiesByRelation(int n, Relation targetRelation)
{
if (AffiliationManager.Instance == null)
{
Debug.LogError(
"AffiliationManager.Instance is null. Cannot get entities by relation. VisionRangeDetector should have been disabled if this was an issue.",
this);
return new List<Entity>();
}
if (n <= 0) return new List<Entity>();
// 【逻辑修改】在获取前清理一次集合
CleanEntitiesInRange();
return _entitiesInRange
.Where(e => AffiliationManager.Instance.GetRelation(_ownerEntity.affiliation, e.affiliation) ==
targetRelation)
.OrderBy(e => Vector3.Distance(_myTransform.position, e.transform.position))
.Take(n)
.ToList();
}
}
}

View File

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: e33d58195dd8450a9ec468ede64c8635
timeCreated: 1756048545