123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- using System;
- using System.Collections.Generic;
- using UnityEngine;
- using XGame;
- namespace FL.Battle
- {
- public interface ITargetHandle
- {
- IEntity Entity { get; }
- Vector3 Position { get; }
- /// <summary>
- /// 是否可选中
- /// </summary>
- bool IsCanSelected { get; }
- float Radius { get; }
- float AtkRange { get; }
- void SelectTarget(ITargetHandle target, int skillId);
- }
- public struct FindTargetArgs
- {
- public int entityId;
- public EEntityType entityType;
- /// <summary>
- /// 范围
- /// </summary>
- public float range;
- /// <summary>
- /// 为零表示普通攻击
- /// </summary>
- public int skillId;
- }
- /// <summary>
- /// 目标选择组件
- /// </summary>
- public class TargetSelector
- {
- private Dictionary<EEntityType, HashSet<ITargetHandle>> _typeToHandlesMap;
- private Dictionary<int, ITargetHandle> _idToHandlesMap;
- private Dictionary<ITargetHandle, FindTargetArgs> _waitingMap;
- private List<ITargetHandle> _tempLst = new List<ITargetHandle>();
- public void Register(ITargetHandle handle)
- {
- if (_typeToHandlesMap == null)
- {
- _typeToHandlesMap = new Dictionary<EEntityType, HashSet<ITargetHandle>>();
- _idToHandlesMap = new Dictionary<int, ITargetHandle>();
- }
- var type = handle.Entity.EntityType;
- if (!_typeToHandlesMap.TryGetValue(type, out var handles))
- {
- handles = new HashSet<ITargetHandle>();
- _typeToHandlesMap.Add(type, handles);
- }
- handles.Add(handle);
- _idToHandlesMap.Add(handle.Entity.EntityId, handle);
- }
- public void Unregister(ITargetHandle handle)
- {
- if (_typeToHandlesMap == null) return;
- foreach(var handles in _typeToHandlesMap.Values)
- {
- if (handles.Contains(handle))
- {
- handles.Remove(handle);
- break;
- }
- }
- _idToHandlesMap.Remove(handle.Entity.EntityId);
- _waitingMap?.Remove(handle);
- }
- public void Start(FindTargetArgs args)
- {
- if (_idToHandlesMap == null || _idToHandlesMap.TryGetValue(args.entityId, out var handle) == false)
- {
- return;
- }
- if (_waitingMap == null)
- {
- _waitingMap = new Dictionary<ITargetHandle, FindTargetArgs>();
- }
- _waitingMap[handle] = args;
- }
- public void Selects()
- {
- var count = _waitingMap?.Count ?? 0;
- if (count == 0)
- return;
- _tempLst.AddRange(_waitingMap.Keys);
- for(var i = 0; i < count; i++)
- {
- var director = _tempLst[i];
- if (!director.IsCanSelected)
- continue;
- if (!_waitingMap.TryGetValue(director, out var args))
- {
- continue;
- }
- if (!TryGetTargets(args.entityType, out var targets))
- {
- Log.Debug($"没有可选目标 Entity:{director.Entity.TableId} Relation:{director.Entity.EntityType} Target:{args.entityType}");
- continue;
- }
- ITargetHandle preTarget = null;
- var distanceMin = float.MaxValue;
- foreach (var target in targets)
- {
- if (!target.IsCanSelected)
- continue;
- if (IsInRange(director, target, args.range, out var distance))
- {
- if (preTarget == null || distanceMin > distance)
- {
- preTarget = target;
- distanceMin = distance;
- }
- }
- }
- if (preTarget != null)
- {
- try
- {
- director.SelectTarget(preTarget, args.skillId);
- _waitingMap.Remove(director);
- }
- catch (Exception ex)
- {
- Log.Exception(ex);
- }
- }
- }
- _tempLst.Clear();
- }
- private bool TryGetTargets(EEntityType entityType, out HashSet<ITargetHandle> targets)
- {
- if (_typeToHandlesMap != null && _typeToHandlesMap.TryGetValue(entityType, out targets))
- {
- return true;
- }
- targets = null;
- return false;
- }
- private bool IsInRange(ITargetHandle director, ITargetHandle target, float range, out float distance)
- {
- distance = Vector3.Distance(target.Position, director.Position);
- distance -= (director.Radius + target.Radius); // 去掉双方的半径
- return true;// range >= distance;
- }
- public void Clear()
- {
- _typeToHandlesMap?.Clear();
- _idToHandlesMap?.Clear();
- _waitingMap?.Clear();
- _tempLst?.Clear();
- }
-
- }
- }
|