跳转至

过滤

BaseFilter,作为过滤的抽象类实现

 public abstract class BaseFilter
 {
     public BaseFilter()
     {

     }

     /// <summary>
     /// 返回True则过滤掉
     /// </summary>
     /// <param name="owner">搜索者</param>
     /// <param name="target">搜索判断目标</param>
     /// <param name="cfg"></param>
     /// <returns>返回True则过滤掉</returns>
     public abstract bool FilterTarget(Actor owner, Actor target, SearchFilterCfg cfg, List<int> paramList);


     /// <summary>
     /// 返回True则过滤点
     /// 没有Src的兼容方式
     /// </summary>
     /// <param name="target"></param>
     /// <param name="cfg"></param>
     /// <param name="paramList"></param>
     /// <returns></returns>
     public abstract bool FilterTargetNoSrc(Actor target, SearchFilterCfg cfg, List<int> paramList);

     /// <summary>
     /// 返回True则过滤掉
     /// </summary>
     /// <param name="owner">搜索者</param>
     /// <param name="target">搜索判断目标</param>
     /// <param name="cfg"></param>
     /// <returns>返回True则过滤掉</returns>
     public abstract bool FilterBullet(Actor owner, Bullet target, SearchFilterCfg cfg, List<int> paramList);

     /// <summary>
     /// 返回True则过滤点
     /// 没有Src的兼容方式
     /// </summary>
     /// <param name="target"></param>
     /// <param name="cfg"></param>
     /// <param name="paramList"></param>
     /// <returns></returns>
     public abstract bool FilterBulletNoSrc(Bullet target, SearchFilterCfg cfg, List<int> paramList);
 }

编辑器

#if UNITY_EDITOR

using System;
using System.Collections;
using System.Collections.Generic;
using MS.GameLevel;
using Sirenix.OdinInspector;
using Sirenix.OdinInspector.Editor;
using Sirenix.Utilities;
using Sirenix.Utilities.Editor;
using UnityEngine;
using UnityEditor;


namespace MS.Tool
{

    public class SearchFilterViewWindowSetUp : ScriptableObject
    {

        static public GameLevelMG GetTempLevelMG()
        {
            GameLevelMG levelMG = null;
#if MS_SERVER
            levelMG = GameLevelMG.UnsafeInstance;
#else
            levelMG = GameLevelMG.Instance;
#endif
            return levelMG;
        }

        [LabelText("角色")]
        [ValueDropdown( "GetAllActorNames")]
        public string actorName = string.Empty;

        [LabelText("搜索器ID")]
        [OnValueChanged("OnFilterIdChange")]
        public uint filterId;

        public void OnFilterIdChange()
        {
            if(!Application.isPlaying)
                return;
            var cfg = GameBaseConfig<PbProtocol.pbSearcherConfig>.Instance.Get(filterId);
            if (cfg == null)
            {
                return;
            }
            this.shapeType = cfg.ShapeType;
            this.shapeParam = cfg.ShapeParam;
        }

        [LabelText("显示Gizmos时长ms")]
        public int gizmosDuration = 1000;

        [BoxGroup("搜索器配置")] 
        [LabelText("搜索范围类型(0不判断:1、圆形;2、方形,3、扇形)")]
        [OnValueChanged("OnShapeConfigChange")]
        public uint shapeType=0;

        public string strShowName
        {

            get
            {
                var arr = shapeParam.Split(',');
                string result = "";
                switch (shapeType)
                {
                    case 0:
                        return "无";
                    case 1:
                        string[] attrs = new string[] { "半径", "偏移X", "偏移Y" };
                        for (int i = 0; i < attrs.Length && i<arr.Length ; i++)
                        {
                            result += attrs[i] + ":" + arr[i] + ";";
                        }
                        return result;
                    case 2:
                        string[] rectAttrs = new string[] { "长","宽", "偏移X", "偏移Y","方向跟随"};

                        for (int i = 0; i < rectAttrs.Length && i<arr.Length ; i++)
                        {
                            result += rectAttrs[i] + ":" + arr[i] + ";";
                        }
                        return result;
                    case 3:
                        string[] secAttrs = new string[] { "角度","半径", "偏移X", "偏移Y","方向跟随","向下偏移角度"};
                        for (int i = 0; i < secAttrs.Length && i<arr.Length ; i++)
                        {
                            result += secAttrs[i] + ":" + arr[i] + ";";
                        }
                        return result;
                }
                return result;
            }
        }

        [Title("$strShowName", titleAlignment: TitleAlignments.Left)]
        [LabelText("范围参数")]
        [OnValueChanged("OnShapeConfigChange")]
        public string shapeParam = "";
        public void OnShapeConfigChange()
        {
            if(!Application.isPlaying)
                return;
            var cfg = GameBaseConfig<PbProtocol.pbSearcherConfig>.Instance.Get(filterId);
            if (cfg == null)
            {
                return;
            }
            cfg.ShapeType = shapeType;
            cfg.ShapeParam = shapeParam;
        }

        [PropertyOrder(4)]
        [Button("搜索器预览", ButtonSizes.Medium)]
        private void OnPreview()
        {
            OnConfirm();
            var actor = GetSelectActor();
            if(actor == null)
                return;
            actor.m_GameLevelMG.GameSearcherManager.ShutDown();
            actor.m_GameLevelMG.GameSearcherManager = new GameSearcherManager(actor.m_GameLevelMG);
            BTUtil.SearchTargetByID(actor, (int)filterId);
        }

        public bool isOpenPreview
        {
            get
            {
                return (RuntimeGizmosManager.Instance.GizmosIsOpen & (int)LimitGizmosShowType.SearchRange) != 0;
            }
        }
        [PropertyOrder(4)]
        [EnableIf("isOpenPreview")]
        [Button("停止搜索器预览", ButtonSizes.Medium)]
        private void OnDisablePreview()
        {
            OnCancel();
            RuntimeGizmosManager.Instance.GizmosIsOpen = RuntimeGizmosManager.Instance.GizmosIsOpen & (~(int)LimitGizmosShowType.SearchRange);
        }

        [PropertyOrder(5)]
        [Button("开始监视", ButtonSizes.Medium)]
        private void OnConfirm()
        {
            uint ident = GetSelectActorIdent();
            if (ident > 0 && filterId > 0)
            {
                SearcherFilterView searcherFilterView = SearcherFilterViewHelper.GetFilterView();
                if (null != searcherFilterView)
                {
                    searcherFilterView.gizmosDuration = gizmosDuration;
                    if (searcherFilterView.OnInput(ident, filterId))
                    {

                    }
                    else
                    {
                        EditorUtility.DisplayDialog("错误", "请检查搜索器id", "OK");
                    }
                }
            }
            else
            {
                if (ident == 0)
                {
                    EditorUtility.DisplayDialog("错误", "请选择Actor", "OK");
                    return;
                }

                if (filterId == 0)
                {
                    EditorUtility.DisplayDialog("错误", "请设置查找的搜索器id", "OK");
                    return;
                }

            }
        }

        [PropertyOrder(6)]
        [Button("停止监视", ButtonSizes.Medium)]
        private void OnCancel()
        {  
            filterId = 0;
            SearcherFilterViewHelper.GetFilterView()?.OnInput(0, 0);
        }



        [ReadOnly]
        [PropertyOrder(8)]
        [GUIColor(1,0,0)]
        [LabelText("刷新时间")]
        public string resultFlushTime;


        [Serializable]
        public class LabelSearchResultFail
        {

            [ReadOnly]
            [LabelText("")]
            public string fail;

            public LabelSearchResultFail(string fail)
            {
                this.fail = fail;
            }
        }

        [Serializable]
        public class LabelSearchResultSuc
        {
            [GUIColor(0,1,0)]
            [ReadOnly]
            [LabelText("")]
            public string success;

            public LabelSearchResultSuc(string success)
            {
                this.success = success;
            }
        }

        [PropertyOrder(9)]
        [TableList(ShowIndexLabels = false, IsReadOnly = true, ShowPaging = true, AlwaysExpanded = true,DrawScrollView = true),
         LabelText("搜索成功的结果")]
        public List<LabelSearchResultSuc> searchResultsSucs = new List<LabelSearchResultSuc>()
        {

        };

        [PropertyOrder(10)]
        [TableList(ShowIndexLabels = false, IsReadOnly = true, ShowPaging = true, AlwaysExpanded = true,DrawScrollView = true),
         LabelText("搜索失败的结果")]
        public List<LabelSearchResultFail> searchResultsFails = new List<LabelSearchResultFail>()
        {

        };


        private int _cacheFrameIndex = int.MinValue;
        public void OnCustomUpdate()
        {  
            SearcherFilterView searcherFilterView = SearcherFilterViewHelper.GetFilterView();
            if (null != searcherFilterView)
            {
                int frameIndex = searcherFilterView.GetRecordFrameIndex();
                if (_cacheFrameIndex == frameIndex)
                {
                    return;
                }

                SearchFilterViewEditor.Dirty();
                _cacheFrameIndex = frameIndex;
                resultFlushTime = searcherFilterView.GetRecordDateTime().ToString("hh:mm:ss:fff");

                searchResultsFails.Clear();
                searchResultsSucs.Clear();

                GameLevelMG gameLevelMg = GetTempLevelMG();
                NBDict<uint, FilterLockViewOneTargetRecord> results = searcherFilterView.GetSearchResults();
                if (null != results)
                {
                    NBDictEnumerator<uint, FilterLockViewOneTargetRecord> itor = results.GetEnumerator();
                    while (itor.MoveNext())
                    {
                        if (itor.Current.Value.isSuc)
                        {
                            string msg = itor.Current.Value.GetShowResultMsg(itor.Current.Key, gameLevelMg);
                            searchResultsSucs.Add(new LabelSearchResultSuc(msg));
                        }
                        else
                        {
                            string msg = itor.Current.Value.GetShowResultMsg(itor.Current.Key, gameLevelMg);
                            searchResultsFails.Add(new LabelSearchResultFail(msg));
                        }

                    }
                }
            }
        }



        private uint GetSelectActorIdent()
        {
            GameLevelMG gameLevelMg = GetTempLevelMG();
            if (null != gameLevelMg)
            {
                ActorManager actorManager = gameLevelMg.ActorManager;
                if (null != actorManager)
                {
                    List<Actor> allActors = actorManager.GetAllActor();
                    for (int i = 0; i < allActors.Count; i++)
                    {
                        if (actorName == allActors[i].name)
                        {
                            return allActors[i].Ident;
                        }
                    }
                }
            }

            return 0;
        }
        private Actor GetSelectActor()
        {
            GameLevelMG gameLevelMg = GetTempLevelMG();
            if (null != gameLevelMg)
            {
                ActorManager actorManager = gameLevelMg.ActorManager;
                if (null != actorManager)
                {
                    List<Actor> allActors = actorManager.GetAllActor();
                    for (int i = 0; i < allActors.Count; i++)
                    {
                        if (actorName == allActors[i].name)
                        {
                            return allActors[i];
                        }
                    }
                }
            }

            return null;
        }


        private IEnumerable GetAllActorNames()
        {
            GameLevelMG gameLevelMg = GetTempLevelMG();
            if (null != gameLevelMg)
            {
                ActorManager actorManager = gameLevelMg.ActorManager;
                if (null != actorManager)
                {
                    List<Actor> allActors = actorManager.GetAllActor();
                    for (int i = 0; i < allActors.Count; i++)
                    {
                        yield return allActors[i].name;
                    }
                }
            }
        }

    }



    public class SearchFilterViewEditor : OdinMenuEditorWindow
    {

        private SearchFilterViewWindowSetUp _searchFilterViewWindowSetUp;
        protected override OdinMenuTree BuildMenuTree()
        {
            _searchFilterViewWindowSetUp = ScriptableObject.CreateInstance<SearchFilterViewWindowSetUp>();

            OdinMenuTree tree = new OdinMenuTree(supportsMultiSelect: true)
            {
                { "监视设置", _searchFilterViewWindowSetUp, EditorIcons.House },
            };
            return tree;
        }

        public void Update()
        {
            if (windowInstance != null)
            {
                if (null != _searchFilterViewWindowSetUp)
                {
                    _searchFilterViewWindowSetUp.OnCustomUpdate();
                }
            }
            else
            {
                windowInstance = GetWindow<SearchFilterViewEditor>();
                windowInstance.titleContent.text = "搜索器调试";
                windowInstance.position = GUIHelper.GetEditorWindowRect().AlignCenter(1300, 600);
            }
        }


        public static SearchFilterViewEditor windowInstance = null;
        [MSMenuItem_D("单局/搜索器调试")]
        static void OpenWindow()
        {
            if (windowInstance != null)
            {
                windowInstance.Focus();
            }
            else
            {
                windowInstance = GetWindow<SearchFilterViewEditor>();
                windowInstance.titleContent.text = "搜索器调试";
                windowInstance.position = GUIHelper.GetEditorWindowRect().AlignCenter(1300, 600);
            }
        }

        public static void Dirty()
        {
            if (windowInstance != null)
            {
                windowInstance.Repaint();
            }
        }

    }
}

#endif

搜索程序集

using System;
using System.Collections.Generic;
using PbProtocol;
using UnityEngine;
using MS.Framework;

namespace Test.GameLevel
{
    public class AssembledSearcher
    {
public enum FilterType
{
    [FilterTypeFailDescription("阵营判断")]
    [SearchFilter(typeof(TeamateFilter))]
    Teammate = 0,

    [FilterTypeFailDescription("Actor类型")]
    [SearchFilter(typeof(TargetTypeFilter))]
    TargetType = 1,

    [FilterTypeFailDescription("ActorState")]
    [SearchFilter(typeof(ActorStateFilter))]
    ActorState = 2,

    [FilterTypeFailDescription("子弹过滤器")]
    [SearchFilter(typeof(BulletFromFilter))]
    BulletFilter = 3, 

    [FilterTypeFailDescription("子弹标签 - 可破坏")]
    [SearchFilter(typeof(BulletTagFilter))]
    BulletTagFilter = 4,

    [FilterTypeFailDescription("根据身上的Buff过滤")]
    [SearchFilter(typeof(BuffFilter))]
    BuffFilter = 5,

    [FilterTypeFailDescription("敌人类型过滤器")]
    [SearchFilter(typeof(EnemyTypeFilter))]
    EnemyTypeFilter = 6,

    [FilterTypeFailDescription("敌人与玩家停留时间长?过滤器")]
    [SearchFilter(typeof(EnemyStayLongWithPlayerFilter))]
    EnemyStayLongWithPlayerFilter = 7,

    [FilterTypeFailDescription("标签过滤器")]
    [SearchFilter(typeof(ActorTagFilter))]
    TagFilter = 8,

    [FilterTypeFailDescription("HitAction类型过滤器")]
    [SearchFilter(typeof(HitActionTypeFilter))]
    HitActionTypeFilter = 9,

    [FilterTypeFailDescription("Alias名称过滤器")]
    [SearchFilter(typeof(AliasNameFilter))]
    AliasNameFilter = 10,

    [FilterTypeFailDescription("受击效果过滤器")]
    [SearchFilter(typeof(HurtEffectTypeFilter))]
    HurtEffectTypeFilter = 11,

    [FilterTypeFailDescription("召唤物过滤器")]
    [SearchFilter(typeof(SummonerFilter))]
    SummonerFilter = 12,

    [FilterTypeFailDescription("韧性状态?过滤器")]
    [SearchFilter(typeof(EndureStateFilter))]
    EndureStateFilter = 13,

    [FilterTypeFailDescription("召唤物创建者过滤器")]
    [SearchFilter(typeof(SummonCreatorFilter))]
    SummonCreatorFilter = 14,

    [FilterTypeFailDescription("凋落物拾取过滤器")]
    [SearchFilter(typeof(DropPickedFilter))]
    DropPickedFilter = 15,

    [FilterTypeFailDescription("站位搜索器")]
    [SearchFilter(typeof(StanceFilter))]
    StanceFilter = 16,

    [FilterTypeFailDescription("血量搜索器")]
    [SearchFilter(typeof(HpFilter))]
    HpFilter = 17,

    [FilterTypeFailDescription("黑暗空间过滤器")]
    [SearchFilter(typeof(DarkSpaceZoneFilter))]
    DarkSpaceZoneFilter = 18,

    [FilterTypeFailDescription("跟随目标过滤器")]
    [SearchFilter(typeof(FollowTargetFilter))]
    FollowTargetFilter = 19,

    [FilterTypeFailDescription("子弹类型")]
    [SearchFilter(typeof(BulletTypeFilter))]
    BulletTypeFilter = 20,

    [FilterTypeFailDescription("召唤者瞄准对象")]
    [SearchFilter(typeof(CreatorAimTargetFilter))]
    CreatorAimTargetFilter = 21,

    [FilterTypeFailDescription("buff 自定义标签搜索器")]
    [SearchFilter(typeof(BuffCustomTagFilter))]
    BuffCustomTagFilter = 22,

    [FilterTypeFailDescription("仇恨最高是我搜索器")]
    [SearchFilter(typeof(HatredFilter))]
    HatredFilter = 23,

    [FilterTypeFailDescription("特殊指定目标搜索器")]
    [SearchFilter(typeof(SpecialTargetFilter))]
    SpecialTargetFilter = 24,

    [FilterTypeFailDescription("掉落物搜索器")]
    [SearchFilter(typeof(DropFilter))]
    DropFilter = 25,

    [FilterTypeFailDescription("怪物唯一标签搜索器")]
    [SearchFilter(typeof(ActorMonsterUniqueTagFilter))]
    MonsterUniqueTagFilter = 26,

    [FilterTypeFailDescription("能量搜索器")]
    [SearchFilter(typeof(EnergyFilter))]
    EnergyFilter = 27,

    [FilterTypeFailDescription("ActorBaseID搜索器")]
    [SearchFilter(typeof(ActorBaseIDFilter))]
    ActorBaseIDFilter = 28,

    [FilterTypeFailDescription("专属搜土豆兄弟武器召唤物")]
    [SearchFilter(typeof(SummonerByBrotatoFilter))]
    SummonerByBrotatoFilter = 29,

    //range
    [FilterTypeFailDescription("方形搜索器")]
    [SearchFilter(typeof(SquareFilter))]
    SquareFilter = 100,

    [FilterTypeFailDescription("圆形搜索器")]
    [SearchFilter(typeof(CircleFilter))]
    CircleFilter = 101,

    [FilterTypeFailDescription("扇形搜索器")]
    [SearchFilter(typeof(SectorFilter))]
    SectorFilter = 102,

    [FilterTypeFailDescription("逻辑相机搜索器")]
    [SearchFilter(typeof(LogicCameraFilter))]
    LogicCameraFilter = 110,


    [FilterTypeFailDescription("职业搜索器")]
    [SearchFilter(typeof())]


    Max,
}




/////枚举类型:搜索目标类型,性质类型,目标选择类型,子弹类型




        public enum SearchTargetType
        {
            Actor,
            Bullet,
            All
        }

        public enum ShapeType
        {
            None,

            /// <summary>
            /// 圆
            /// </summary>
            Circle = 1,

            /// <summary>
            /// 方形
            /// </summary>
            Square = 2,


            /// <summary>
            /// 扇形
            /// </summary>
            Sector = 3,

            Max,
        }

        /// <summary>
        /// 目标的选择类型
        /// 
        /// </summary>
        public enum TargetSelectType
        {
            None = 0,
            Actor = 1 << 1, // actor
            Bullet = 1 << 2, // 子弹
            Substitute = 1 << 3,// 后台actor
        }


        public enum BulletFilterType
        {
            /// <summary>
            /// 不包括子弹
            /// </summary>
            FilterBullet = 0,


            /// <summary>
            /// 包含子弹,同时包括Actor
            /// </summary>
            IncludeBullet = 1,


            /// <summary>
            /// 只包含子弹
            /// </summary>
            OnlyIncludeBullet = 2,
        }

/*
- `` `_filterMap` ``: 一个私有的静态数组,用于存储`` `BaseFilter` ``类型的对象。
- `` `ID` ``: 一个公共的只读属性,返回一个`` `uint` ``类型的值。
- `` `m_ListFilterCfg` ``: 一个私有的列表,用于存储`` `SearchFilterCfg` ``类型的对象。
- `` `m_TargetListCache` ``: 一个私有的列表,用于存储`` `SearchFilterBase.ActorSearch` ``类型的对象,并在声明时初始化为空列表。
- `` `_targetTypeFilter` ``: 一个私有的`` `TargetSelectType` ``类型的变量。
- `` `_orderType` ``: 一个私有的`` `NBList<ENUM_SearchOrderType>` ``类型的变量,并在声明时初始化为一个新的实例。
- `` `_orderParam` ``: 一个私有的`` `uint` ``类型的变量。
- `` `_dummyName` ``: 一个私有的字符串变量。
- `` `_maxResultNum` ``: 一个私有的整数变量。
- `` `_bUseInputSrcPos` ``: 一个私有的静态布尔变量,默认值为`` `false` ``。
- `` `_InputSrcPos` ``: 一个私有的静态`` `Vector3` ``类型的变量,默认值为`` `Vector3.zero` ``。
- `` `_DummyNameTemp` ``: 一个私有的静态字符串变量,默认值为空字符串。
- `` `ResultTemp` ``: 一个公共的静态只读属性,返回一个新的`` `SearchFilterBase.ActorSearch` ``类型的实例。

**### 方法**

- `` `GetListFilterCfgs()` ``: 一个公共的方法,返回`` `m_ListFilterCfg` ``列表。
- `` `AssembledSearcher(pbSearcherConfig config, GameLevelMG gameLevelMG)` ``: 这是类的构造函数,它接受两个参数:`` `pbSearcherConfig` ``类型的`` `config` ``和`` `GameLevelMG` ``类型的`` `gameLevelMG` ``。构造函数中执行了以下操作:

- 设置`` `ID` ``属性。

- 初始化`` `m_ListFilterCfg` ``列表。

- 设置`` `_dummyName` ``和`` `_maxResultNum` ``变量。

- 调用一系列初始化方法来设置不同的过滤器配置。

- 遍历`` `config.Filter` ``列表,根据配置信息创建`` `SearchFilterCfg` ``对象并添加到`` `m_ListFilter.orgCfg` ``列表中。

- 调用`` `InitLimitFilter` ``和`` `InitShapeFilter` ``方法来初始化限制过滤器和形状过滤器。

- 清空`` `_orderType` ``列表,并根据`` `config.OrderType` ``列表添加新的`` `ENUM_SearchOrderType` ``值。

- 设置`` `_orderParam` ``变量。

这段代码的主要功能是根据传入的配置信息和游戏关卡管理器来初始化搜索器对象,设置各种过滤器和排序选项。这个类可能是用于游戏中的某种搜索或过滤逻辑。
*/


        private static BaseFilter[] _filterMap;

        public uint ID { get; private set; }

        private List<SearchFilterCfg> m_ListFilterCfg;

        private List<SearchFilterBase.ActorSearch> m_TargetListCache = new List<SearchFilterBase.ActorSearch>();


        public List<SearchFilterCfg> GetListFilterCfgs() { 
            return m_ListFilterCfg; 
        }
        //private BulletFilterType _bulletFilterType;

        private TargetSelectType _targetTypeFilter;

        private NBList<ENUM_SearchOrderType> _orderType = new NBList<ENUM_SearchOrderType>();
        private uint _orderParam;

        private string _dummyName;
        private int _maxResultNum;

        /// <summary>
        /// 使用外部传入的坐标
        /// </summary>
        private static bool _bUseInputSrcPos = false;
        private static Vector3 _InputSrcPos = Vector3.zero;
        private static string _DummyNameTemp = string.Empty;


        /// <summary>
        /// 刚开始设计的问题,没法获得搜索过程中的距离和目标点的Transform,弄一个Temp变量存这些数据
        /// </summary>
        public static readonly SearchFilterBase.ActorSearch ResultTemp = new SearchFilterBase.ActorSearch();

        public AssembledSearcher(pbSearcherConfig config, GameLevelMG gameLevelMG)
        {
            ID = config.ID;

            m_ListFilterCfg = new List<SearchFilterCfg>();

            _dummyName = config.ShapeDummy;
            _maxResultNum = config.MaxNum;

            //配置分成固定的Filter配置和自定义的
            InitTeamMateFilter(config);
            InitStateFilter(config);
            InitTypeFilter(config);
            InitBulletFilter(config);
            InitEndureState(config);

            //可选Filter参数
            for(int i = 0; i < config.Filter.Count; i++)
            {
                var filterInfo = config.Filter[i];
                if(filterInfo.Type > 0)
                {
                    string[] stringParam = null;
                    if (!string.IsNullOrEmpty(filterInfo.StringContent))
                    {
                        stringParam = filterInfo.StringContent.Split(',');
                    }

                    string param1 = filterInfo.Param.Count > 0 ? filterInfo.Param[0] : string.Empty;
                    string param2 = filterInfo.Param.Count > 1 ? filterInfo.Param[1] : string.Empty;

                    SearchFilterCfg filterCfg = new SearchFilterCfg(config, (int)filterInfo.Type, param1, param2, stringParam);
                    m_ListFilterCfg.Add(filterCfg);
                }
            }

            InitLimitFilter(config);

            //ShapeFilter放在最后,消耗大的判断最后做
            InitShapeFilter(config);
            this._orderType.Clear();
            for (int i = 0; i < config.OrderType.Count; ++i) {
                var t = config.OrderType[i];
                this._orderType.Add((ENUM_SearchOrderType)t);
            }
            _orderParam = config.OrderParam;
        }

        public static void InitFiler()
        {
            if (_filterMap != null)
            {
                return;
            }

            _filterMap = new BaseFilter[(int)FilterType.Max];

            for (int i = 0; i < (int)FilterType.Max; i++)
            {
                GetFilterByType((FilterType) i);
            }
        }

        #region

        private void InitLimitFilter(pbSearcherConfig config)
        {
            if (config.LimitType == 0)
            {
                return;
            }

            if (config.LimitType == 1)
            {
                SearchFilterCfg filterCfg = new SearchFilterCfg(config, (int)FilterType.LogicCameraFilter, 0);
                m_ListFilterCfg.Add(filterCfg);
            }
        }

        private void InitShapeFilter(pbSearcherConfig config)
        {
            if (config.ShapeType == (int) ShapeType.None)
            {
                return;
            }
            if(config.ShapeType == (int)ShapeType.Circle)
            {
                SearchFilterCfg filterCfg = new SearchFilterCfg(config, (int)FilterType.CircleFilter, config.CheckBlock);
                filterCfg.AddParam(config.ShapeParam);
                filterCfg.AddParam((int)config.ShapeCollider, filterCfg.Param2);
                filterCfg.AddParam((int)config.ShapeTriggerID, filterCfg.Param2);
                m_ListFilterCfg.Add(filterCfg);
            }
            else if(config.ShapeType == (int)ShapeType.Square)
            {
                SearchFilterCfg filterCfg = new SearchFilterCfg(config, (int)FilterType.SquareFilter, config.CheckBlock);
                filterCfg.AddParam(config.ShapeParam);
                filterCfg.AddParam((int)config.ShapeCollider, filterCfg.Param2);
                filterCfg.AddParam((int)config.ShapeTriggerID, filterCfg.Param2);
                m_ListFilterCfg.Add(filterCfg);
            }
            else if (config.ShapeType == (int)ShapeType.Sector)
            {
                SearchFilterCfg filterCfg = new SearchFilterCfg(config, (int)FilterType.SectorFilter, config.CheckBlock);
                filterCfg.AddParam(config.ShapeParam);
                m_ListFilterCfg.Add(filterCfg);
            }
            else
            {
                Logger.LogErrorD($"InitShapeFilter Failed: Invalid shape type  {config.ShapeType}");
            }
        }

        private void InitTeamMateFilter(pbSearcherConfig config)
        {
            //"0"代表全阵营,这里判断直接返回了
            if (string.IsNullOrEmpty(config.FilterFriend) || config.FilterFriend == "0")
            {
                return;
            }

            SearchFilterCfg filterCfg = new SearchFilterCfg(config,(int)FilterType.Teammate, config.FilterFriend,string.Empty);
            m_ListFilterCfg.Add(filterCfg);
        }

        private void InitStateFilter(pbSearcherConfig config)
        {
            if (config.CheckStateValue == string.Empty || config.CheckStateValue == "0")
            {
                return;
            }

            SearchFilterCfg filterCfg = new SearchFilterCfg(config, (int)FilterType.ActorState, config.CheckStateType);
            filterCfg.AddParam(config.CheckStateValue);
            m_ListFilterCfg.Add(filterCfg);
        }

        private void InitTypeFilter(pbSearcherConfig config)
        {
            if (config.CheckTargetValue == string.Empty || config.CheckTargetValue == "0")
            {
                return;
            }

            SearchFilterCfg filterCfg = new SearchFilterCfg(config, (int)FilterType.TargetType, config.CheckTargetType);
            filterCfg.AddParam(config.CheckTargetValue);
            m_ListFilterCfg.Add(filterCfg);
        }

        void AddTargetFilter(TargetSelectType f)
        {
            if((_targetTypeFilter & f) != 0)
            {
                Logger.LogErrorD($"[Searcher]搜索器{ID}的目标类型重复了! {f}");
                return;
            }

            _targetTypeFilter |= f;
        }
        bool ContainTargetType(TargetSelectType f)
        {
            if (f == TargetSelectType.Actor && _targetTypeFilter == 0) // 临时兼容actor类
                return true;

            return (_targetTypeFilter & f) != 0;
        }


        private void InitBulletFilter(pbSearcherConfig config)
        {
            //_bulletFilterType = (BulletFilterType)config.SearchBullet;

            _targetTypeFilter = TargetSelectType.None;

            var arr = config.SearchBullet?.Split(',');
            if(arr != null)
            {
                for (int i = 0; i < arr.Length; i++)
                {
                    if (int.TryParse(arr[i], out var intVal) && intVal != 0)
                        AddTargetFilter((TargetSelectType)(1 << intVal));
                }
            }

            if (config.BulletFromSkillId > 0)
            {
                SearchFilterCfg filterCfg = new SearchFilterCfg(config, (int)FilterType.BulletFilter, config.BulletFromSkillId);
                m_ListFilterCfg.Add(filterCfg);
            }

            if (config.BulletDestructible > 0)
            {
                SearchFilterCfg filterCfg = new SearchFilterCfg(config,(int)FilterType.BulletTagFilter, config.BulletDestructible);
                m_ListFilterCfg.Add(filterCfg);
            }

            if (config.BulletType > 0)
            {
                var filterCfg = new SearchFilterCfg(config, (int)FilterType.BulletTypeFilter, config.BulletType);
                m_ListFilterCfg.Add(filterCfg);
            }
        }

        private void InitEndureState(pbSearcherConfig config)
        {
            if ( string.IsNullOrEmpty(config.CheckEndureValue))
            {
                return;
            }

            SearchFilterCfg filterCfg = new SearchFilterCfg(config, (int)FilterType.EndureStateFilter, config.CheckEndureType);
            filterCfg.AddParam(config.CheckEndureValue);
            m_ListFilterCfg.Add(filterCfg);
        }

        #endregion

        public List<SearchFilterBase.ActorSearch> GetTargetList(Actor src, List<int> paramList,
            bool useInputPos, Vector3 inputPos, GameLevelMG gameLevelMG)
        {
            m_TargetListCache.Clear();

            _bUseInputSrcPos = useInputPos;
            _InputSrcPos = inputPos;
            _DummyNameTemp = _dummyName;

            if (src == null)
            {
                Logger.LogErrorD("SearchFailed: src is null!");
                return m_TargetListCache;
            }

            if (src.HasDestory)
            {
                Logger.LogInfo($"SearchFailed: src {src} has destory!");
                return m_TargetListCache;
            }


#if MS_ENABLE_DEBUG
            if (src.m_GameLevelMG != gameLevelMG)
            {
                Logger.LogErrorD($"SearchFailed: src{src} GameLevelMG != GameLevelMG {gameLevelMG.RoomNumber}!");
                return m_TargetListCache;
            }
#endif


            // if (src.DeadState == DeadState.Dead)
            // {
            //     Logger.LogInfo($"SearchFailed: src {src} is dead!");
            //     return m_TargetListCache;
            // }

            if(ContainTargetType(TargetSelectType.Actor))
                SearchActorTarget(src, paramList, gameLevelMG, out _, false);

            if(ContainTargetType(TargetSelectType.Bullet))
                SearchBulletTarget(src, paramList, gameLevelMG, out _, false);

            if(ContainTargetType(TargetSelectType.Substitute))
                SearchSubstituteActorTarget(src, paramList, gameLevelMG, out _, false);
            SearcherOderUtil.Order(src, m_TargetListCache, _orderType, _orderParam,this.ID);


            if (_maxResultNum > 0 && _maxResultNum <= m_TargetListCache.Count)
            {
                m_TargetListCache.RemoveRange(_maxResultNum, m_TargetListCache.Count - _maxResultNum);
                //m_TargetListCache = m_TargetListCache.GetRange(0, _maxResultNum);
            }

            return m_TargetListCache;
        }


        public List<SearchFilterBase.ActorSearch> GetTargetList(List<int> paramList, GameLevelMG gameLevelMG)
        {
            m_TargetListCache.Clear();

            _bUseInputSrcPos = false;
            _DummyNameTemp = _dummyName;

            if (ContainTargetType(TargetSelectType.Actor))
                SearchActorTarget(paramList, gameLevelMG);

            if (ContainTargetType(TargetSelectType.Bullet))
                SearchBulletTarget(paramList, gameLevelMG);

            if (ContainTargetType(TargetSelectType.Substitute))
                SearchSubstituteActorTarget(paramList, gameLevelMG);

            SearcherOderUtil.Order(m_TargetListCache, _orderType, _orderParam,this.ID);

            if (_maxResultNum > 0 && _maxResultNum <= m_TargetListCache.Count)
            {
                //m_TargetListCache = m_TargetListCache.GetRange(0, _maxResultNum);
                m_TargetListCache.RemoveRange(_maxResultNum, m_TargetListCache.Count - _maxResultNum);
            }

            return m_TargetListCache;
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="src"></param>
        /// <param name="paramList"></param>
        /// <param name="gameLevelMG"></param>
        /// <param name="firstResult">第一个结果</param>
        /// <param name="findFirstReturn">是否找到一个结果就返回</param>
        private void SearchActorTarget(Actor src, List<int> paramList, GameLevelMG gameLevelMG, out SearchFilterBase.ActorSearch firstResult, bool findFirstReturn = false)
        {
            firstResult = null;
            var actorList = gameLevelMG.ActorManager.GetAllActor();
            for (int i = 0, count = actorList.Count; i < count; i++)
            {
                var target = actorList[i];

                if (target.IsNullOrDestroyed() || target.IsClientViewPlayer)
                {
                    continue;
                }    

                bool bFilter = false;

                ResultTemp.Reset();

                for (int j = 0, searchCount = m_ListFilterCfg.Count; j < searchCount; j++)
                {
                    var filterCfg = m_ListFilterCfg[j];

                    var subSearchFilter = GetFilterByType((FilterType)filterCfg.Type);

                    if (subSearchFilter == null)
                    {
                        Logger.LogErrorD(string.Format("GetFilterByType {0} Failed!", (FilterType)filterCfg.Type));
                        bFilter = true;

                        if (SearcherFilterViewHelper.IsCommonFilterType((FilterType) filterCfg.Type))
                        {
                            SearcherFilterViewHelper.GetFilterView()?.AddSearchRecord(src.Ident, target.Ident, false, 
                                SearchFilterBase.ActorSearch.TargetType.Actor, SearchFilterFailureReason.CommonFilterType, (FilterType)filterCfg.Type);
                        }
                        break;
                    }

                    if (subSearchFilter.FilterTarget(src, target, filterCfg, paramList))
                    {
                        bFilter = true;

                        if (SearcherFilterViewHelper.IsCommonFilterType((FilterType) filterCfg.Type))
                        {
                            SearcherFilterViewHelper.GetFilterView()?.AddSearchRecord(src.Ident, target.Ident, false, 
                                SearchFilterBase.ActorSearch.TargetType.Actor, SearchFilterFailureReason.CommonFilterType, (FilterType)filterCfg.Type);
                        }
                        break;
                    }
                }

                if (bFilter)
                {
                    continue;
                }

                SearchFilterBase.ActorSearch actorSearch = new SearchFilterBase.ActorSearch();
                actorSearch.actor = target;
                actorSearch.m_distance = ResultTemp.m_distance;
                actorSearch.target = ResultTemp.target;

                m_TargetListCache.Add(actorSearch);

                SearcherFilterViewHelper.GetFilterView()?.AddSearchRecord(src.Ident, target.Ident, true, 
                    SearchFilterBase.ActorSearch.TargetType.Actor, SearchFilterFailureReason.None, FilterType.Max);

                if (findFirstReturn)
                {
                    firstResult = actorSearch;

                    ResultTemp.Reset();        
                    return;
                }
            }

            ResultTemp.Reset();
        }


        public void SearchActorTarget(List<int> paramList, GameLevelMG gameLevelMG)
        {
            var actorList = gameLevelMG.ActorManager.GetAllActor();
            for (int i = 0, count = actorList.Count; i < count; i++)
            {
                var target = actorList[i];

                if (target.IsNullOrDestroyed() || target.IsClientViewPlayer)
                {
                    continue;
                }

                bool bFilter = false;

                ResultTemp.Reset();

                for (int j = 0, searchCount = m_ListFilterCfg.Count; j < searchCount; j++)
                {
                    var filterCfg = m_ListFilterCfg[j];

                    var subSearchFilter = GetFilterByType((FilterType)filterCfg.Type);

                    if (subSearchFilter == null)
                    {
                        Logger.LogErrorD(string.Format("GetFilterByType {0} Failed!", (FilterType)filterCfg.Type));
                        bFilter = true;

                        if (SearcherFilterViewHelper.IsCommonFilterType((FilterType) filterCfg.Type))
                        {
                            SearcherFilterViewHelper.GetFilterView()?.AddSearchRecord(0, target.Ident, false, 
                                SearchFilterBase.ActorSearch.TargetType.Actor, SearchFilterFailureReason.CommonFilterType, (FilterType)filterCfg.Type);
                        }
                        break;
                    }

                    if (subSearchFilter.FilterTargetNoSrc(target, filterCfg, paramList))
                    {
                        bFilter = true;

                        if (SearcherFilterViewHelper.IsCommonFilterType((FilterType) filterCfg.Type))
                        {
                            SearcherFilterViewHelper.GetFilterView()?.AddSearchRecord(0, target.Ident, false, 
                                SearchFilterBase.ActorSearch.TargetType.Actor, SearchFilterFailureReason.CommonFilterType, (FilterType)filterCfg.Type);
                        }
                        break;
                    }
                }

                if (bFilter)
                {
                    continue;
                }

                SearchFilterBase.ActorSearch actorSearch = new SearchFilterBase.ActorSearch();
                actorSearch.actor = target;
                actorSearch.m_distance = ResultTemp.m_distance;
                actorSearch.target = ResultTemp.target;
                m_TargetListCache.Add(actorSearch);

                SearcherFilterViewHelper.GetFilterView()?.AddSearchRecord(0, target.Ident, true, 
                    SearchFilterBase.ActorSearch.TargetType.Actor, SearchFilterFailureReason.None, FilterType.Max);
            }

            ResultTemp.Reset();

        }


        private void SearchBulletTarget(Actor src, List<int> paramList, GameLevelMG gameLevelMG, out SearchFilterBase.ActorSearch firstResult, bool findFirstReturn = false)
        {
            firstResult = null;

            var bulletDic = gameLevelMG.BulletManager.GetAllBullet();

            if (bulletDic == null)
            {
                return;
            }

            var bulletEnumer = bulletDic.GetEnumerator();
            while (bulletEnumer.MoveNext())
            {
                var target = bulletEnumer.Current.Value;

                if (target.IsNullOrDestroyed())
                {
                    continue;
                }

                bool bFilter = false;
                ResultTemp.Reset();

                for (int j = 0, searchCount = m_ListFilterCfg.Count; j < searchCount; j++)
                {
                    var filterCfg = m_ListFilterCfg[j];

                    var subSearchFilter = GetFilterByType((FilterType)filterCfg.Type);

                    if (subSearchFilter == null)
                    {
                        Logger.LogErrorD(string.Format("GetFilterByType {0} Failed!", (FilterType)filterCfg.Type));
                        bFilter = true;

                        if (SearcherFilterViewHelper.IsCommonFilterType((FilterType) filterCfg.Type))
                        {
                            SearcherFilterViewHelper.GetFilterView()?.AddSearchRecord(src.Ident, (uint)target.Ident, false, 
                                SearchFilterBase.ActorSearch.TargetType.Bullet, SearchFilterFailureReason.CommonFilterType, (FilterType)filterCfg.Type);
                        }
                        break;
                    }

                    if (subSearchFilter.FilterBullet(src, target, filterCfg, paramList))
                    {
                        bFilter = true;

                        if (SearcherFilterViewHelper.IsCommonFilterType((FilterType) filterCfg.Type))
                        {
                            SearcherFilterViewHelper.GetFilterView()?.AddSearchRecord(src.Ident, (uint)target.Ident, false, 
                                SearchFilterBase.ActorSearch.TargetType.Bullet, SearchFilterFailureReason.CommonFilterType, (FilterType)filterCfg.Type);
                        }
                        break;
                    }
                }

                if (bFilter)
                {
                    continue;
                }

                SearchFilterBase.ActorSearch actorSearch = new SearchFilterBase.ActorSearch();
                actorSearch.bullet = target;
                actorSearch.m_distance = ResultTemp.m_distance;
                actorSearch.target = ResultTemp.target;
                actorSearch.m_targetType = SearchFilterBase.ActorSearch.TargetType.Bullet;
                m_TargetListCache.Add(actorSearch);

                SearcherFilterViewHelper.GetFilterView()?.AddSearchRecord(src.Ident, (uint)target.Ident, true, 
                    SearchFilterBase.ActorSearch.TargetType.Bullet, SearchFilterFailureReason.None, FilterType.Max);

                if (findFirstReturn)
                {
                    firstResult = actorSearch;
                    ResultTemp.Reset();
                    return;
                }
            }

            ResultTemp.Reset();
        }

        private void SearchBulletTarget(List<int> paramList, GameLevelMG gameLevelMG)
        {
            var bulletDic = gameLevelMG.BulletManager.GetAllBullet();

            if (bulletDic == null)
            {
                return;
            }

            var bulletEnumer = bulletDic.GetEnumerator();
            while (bulletEnumer.MoveNext())
            {
                var target = bulletEnumer.Current.Value;

                if (target.IsNullOrDestroyed())
                {
                    continue;
                }

                bool bFilter = false;
                ResultTemp.Reset();

                for (int j = 0, searchCount = m_ListFilterCfg.Count; j < searchCount; j++)
                {
                    var filterCfg = m_ListFilterCfg[j];

                    var subSearchFilter = GetFilterByType((FilterType)filterCfg.Type);

                    if (subSearchFilter == null)
                    {
                        Logger.LogErrorD(string.Format("GetFilterByType {0} Failed!", (FilterType)filterCfg.Type));
                        bFilter = true;

                        if (SearcherFilterViewHelper.IsCommonFilterType((FilterType) filterCfg.Type))
                        {
                            SearcherFilterViewHelper.GetFilterView()?.AddSearchRecord(0, (uint)target.Ident, false, 
                                SearchFilterBase.ActorSearch.TargetType.Bullet, SearchFilterFailureReason.CommonFilterType, (FilterType)filterCfg.Type);
                        }
                        break;
                    }

                    if (subSearchFilter.FilterBulletNoSrc(target, filterCfg, paramList))
                    {
                        bFilter = true;

                        if (SearcherFilterViewHelper.IsCommonFilterType((FilterType) filterCfg.Type))
                        {
                            SearcherFilterViewHelper.GetFilterView()?.AddSearchRecord(0, (uint)target.Ident, false, 
                                SearchFilterBase.ActorSearch.TargetType.Bullet, SearchFilterFailureReason.CommonFilterType, (FilterType)filterCfg.Type);
                        }
                        break;
                    }
                }

                if (bFilter)
                {
                    continue;
                }

                SearchFilterBase.ActorSearch actorSearch = new SearchFilterBase.ActorSearch();
                actorSearch.bullet = target;
                actorSearch.m_distance = ResultTemp.m_distance;
                actorSearch.target = ResultTemp.target;
                actorSearch.m_targetType = SearchFilterBase.ActorSearch.TargetType.Bullet;
                m_TargetListCache.Add(actorSearch);

                SearcherFilterViewHelper.GetFilterView()?.AddSearchRecord(0, (uint)target.Ident, true, 
                    SearchFilterBase.ActorSearch.TargetType.Bullet, SearchFilterFailureReason.None, FilterType.Max);
            }

            ResultTemp.Reset();
        }

        // 从替补席中筛选目标
        private void SearchSubstituteActorTarget(Actor src, List<int> paramList, GameLevelMG gameLevelMG, out SearchFilterBase.ActorSearch firstResult, bool findFirstReturn = false)
        {
            firstResult = null;

            var actorList = gameLevelMG.SubstituteManager.GetAllActor();
            for (int i = 0, count = actorList.Count; i < count; i++)
            {
                var target = actorList[i];

                if (target.IsNullOrDestroyed() || target.IsClientViewPlayer)
                {
                    continue;
                }

                bool bFilter = false;

                ResultTemp.Reset();

                for (int j = 0, searchCount = m_ListFilterCfg.Count; j < searchCount; j++)
                {
                    var filterCfg = m_ListFilterCfg[j];
                    var filterType = (FilterType)filterCfg.Type;
                    if (filterType == FilterType.CircleFilter || filterType == FilterType.SquareFilter || filterType == FilterType.SectorFilter)
                    {
                        //后台英雄不检查范围
                        continue;
                    }
                    var subSearchFilter = GetFilterByType((FilterType)filterCfg.Type);

                    if (subSearchFilter == null)
                    {
                        Logger.LogErrorD(string.Format("GetFilterByType {0} Failed!", (FilterType)filterCfg.Type));
                        bFilter = true;

                        if (SearcherFilterViewHelper.IsCommonFilterType((FilterType) filterCfg.Type))
                        {
                            SearcherFilterViewHelper.GetFilterView()?.AddSearchRecord(src.Ident, target.Ident, false, 
                                SearchFilterBase.ActorSearch.TargetType.Actor, SearchFilterFailureReason.CommonFilterType, (FilterType)filterCfg.Type);
                        }
                        break;
                    }

                    if (subSearchFilter.FilterTarget(src, target, filterCfg, paramList))
                    {
                        bFilter = true;

                        if (SearcherFilterViewHelper.IsCommonFilterType((FilterType) filterCfg.Type))
                        {
                            SearcherFilterViewHelper.GetFilterView()?.AddSearchRecord(src.Ident, target.Ident, false, 
                                SearchFilterBase.ActorSearch.TargetType.Actor, SearchFilterFailureReason.CommonFilterType, (FilterType)filterCfg.Type);
                        }
                        break;
                    }
                }

                if (bFilter)
                {
                    continue;
                }

                SearchFilterBase.ActorSearch actorSearch = new SearchFilterBase.ActorSearch();
                actorSearch.actor = target;
                actorSearch.m_distance = ResultTemp.m_distance;
                actorSearch.target = ResultTemp.target;

                m_TargetListCache.Add(actorSearch);

                SearcherFilterViewHelper.GetFilterView()?.AddSearchRecord(src.Ident, target.Ident, true, 
                    SearchFilterBase.ActorSearch.TargetType.Actor, SearchFilterFailureReason.None, FilterType.Max);

                if (findFirstReturn)
                {
                    firstResult = actorSearch;
                    ResultTemp.Reset();

                    return;
                }
            }

            ResultTemp.Reset();
        }
        private void SearchSubstituteActorTarget(List<int> paramList, GameLevelMG gameLevelMG)
        {
            var actorList = gameLevelMG.SubstituteManager.GetAllActor();
            for (int i = 0, count = actorList.Count; i < count; i++)
            {
                var target = actorList[i];

                if (target.IsNullOrDestroyed() || target.IsClientViewPlayer)
                {
                    continue;
                }

                bool bFilter = false;

                ResultTemp.Reset();

                for (int j = 0, searchCount = m_ListFilterCfg.Count; j < searchCount; j++)
                {
                    var filterCfg = m_ListFilterCfg[j];

                    var subSearchFilter = GetFilterByType((FilterType)filterCfg.Type);

                    if (subSearchFilter == null)
                    {
                        Logger.LogErrorD(string.Format("GetFilterByType {0} Failed!", (FilterType)filterCfg.Type));
                        bFilter = true;

                        if (SearcherFilterViewHelper.IsCommonFilterType((FilterType) filterCfg.Type))
                        {
                            SearcherFilterViewHelper.GetFilterView()?.AddSearchRecord(0, target.Ident, false, 
                                SearchFilterBase.ActorSearch.TargetType.Actor, SearchFilterFailureReason.CommonFilterType, (FilterType)filterCfg.Type);
                        }
                        break;
                    }

                    if (subSearchFilter.FilterTargetNoSrc(target, filterCfg, paramList))
                    {
                        bFilter = true;

                        if (SearcherFilterViewHelper.IsCommonFilterType((FilterType) filterCfg.Type))
                        {
                            SearcherFilterViewHelper.GetFilterView()?.AddSearchRecord(0, target.Ident, false, 
                                SearchFilterBase.ActorSearch.TargetType.Actor, SearchFilterFailureReason.CommonFilterType, (FilterType)filterCfg.Type);
                        }
                        break;
                    }
                }

                if (bFilter)
                {
                    continue;
                }

                SearchFilterBase.ActorSearch actorSearch = new SearchFilterBase.ActorSearch();
                actorSearch.actor = target;
                actorSearch.m_distance = ResultTemp.m_distance;
                actorSearch.target = ResultTemp.target;
                m_TargetListCache.Add(actorSearch);

                SearcherFilterViewHelper.GetFilterView()?.AddSearchRecord(0, target.Ident, true, 
                    SearchFilterBase.ActorSearch.TargetType.Actor, SearchFilterFailureReason.None, FilterType.Max);

            }

            ResultTemp.Reset();
        }

        private static BaseFilter GetFilterByType(FilterType filterType)
        {
            int filterTypeIndex = (int)filterType;

            if (_filterMap == null)
            {
                Logger.LogErrorD("Get Filter Failed: FilterMap is null!");
                return null;
            }

            if (filterTypeIndex >= _filterMap.Length || filterTypeIndex < 0)
            {
                Logger.LogErrorD(string.Format("Get Filter Failed: filterType is {0}, map length is {1}", (FilterType)filterType, _filterMap.Length));
                return null;
            }

            if (_filterMap[filterTypeIndex] == null)
            {
                System.Reflection.FieldInfo fieldInfo = filterType.GetType().GetField(filterType.ToString());
                if (fieldInfo != null)
                {
                    var attributes = (SearchFilterAttribute[])fieldInfo.GetCustomAttributes(typeof(SearchFilterAttribute), false);
                    if (attributes.Length > 0)
                    {
                        _filterMap[filterTypeIndex] = Activator.CreateInstance(attributes[0].Type) as BaseFilter;
                    }
                }
            }

            return _filterMap[filterTypeIndex];
        }

        /// <summary>
        /// 过滤筛选目标
        /// </summary>
        /// <param name="source"></param>
        /// <param name="target"></param>
        /// <param name="paramList"></param>
        /// <returns></returns>
        public bool FilterTarget(Actor source, Actor target, List<int> paramList)
        {
            ResultTemp.Reset();
            bool bFilter = false;
            uint scrIdent = source!= null? source.Ident:0;
            for (int j = 0, searchCount = m_ListFilterCfg.Count; j < searchCount; j++)
            {
                var filterCfg = m_ListFilterCfg[j];

                var subSearchFilter = GetFilterByType((FilterType)filterCfg.Type);

                if (subSearchFilter == null)
                {
                    Logger.LogErrorD(string.Format("GetFilterByType {0} Failed!", (FilterType)filterCfg.Type));
                    bFilter = true;

                    if (SearcherFilterViewHelper.IsCommonFilterType((FilterType) filterCfg.Type))
                    {
                        SearcherFilterViewHelper.GetFilterView()?.AddSearchRecord(scrIdent, target.Ident, false, 
                            SearchFilterBase.ActorSearch.TargetType.Actor, SearchFilterFailureReason.CommonFilterType, (FilterType)filterCfg.Type);
                    }
                    break;
                }

                if (source == null)
                {
                    if (subSearchFilter.FilterTargetNoSrc(target, filterCfg, paramList))
                    {
                        bFilter = true;

                        if (SearcherFilterViewHelper.IsCommonFilterType((FilterType) filterCfg.Type))
                        {
                            SearcherFilterViewHelper.GetFilterView()?.AddSearchRecord(scrIdent, target.Ident, false, 
                                SearchFilterBase.ActorSearch.TargetType.Actor, SearchFilterFailureReason.CommonFilterType, (FilterType)filterCfg.Type);
                        }
                        break;
                    }
                }
                else
                {
                    if (source.IsDead)
                    {
                        Logger.LogWarning($"GetFilterByType {(FilterType) filterCfg.Type} Failed:{source} is Dead!");
                        break;
                    }

                    if (subSearchFilter.FilterTarget(source, target, filterCfg, paramList))
                    {
                        bFilter = true;

                        if (SearcherFilterViewHelper.IsCommonFilterType((FilterType) filterCfg.Type))
                        {
                            SearcherFilterViewHelper.GetFilterView()?.AddSearchRecord(scrIdent, target.Ident, false, 
                                SearchFilterBase.ActorSearch.TargetType.Actor, SearchFilterFailureReason.CommonFilterType, (FilterType)filterCfg.Type);
                        }
                        break;
                    }
                }
            }

            if (!bFilter)
            {
                SearcherFilterViewHelper.GetFilterView()?.AddSearchRecord(scrIdent, target.Ident, true, 
                    SearchFilterBase.ActorSearch.TargetType.Actor, SearchFilterFailureReason.None, FilterType.Max);
            }

            ResultTemp.Reset();
            return bFilter;
        }

        public static bool CheckBlock(Actor checkActor, Vector3 from, Vector3 to, GameLevelMG gameLevelMG, bool onlyCheckBullet = false)
        {
            var vec = to - from;
            var direction = vec.normalized;
            var distance = vec.magnitude;
            var hitCount = gameLevelMG.PhysicsManager.RaycastAllNoGC(from, direction, distance, PhysicsUtil.BulletBlockLayer, PhysicsUtil.tempResult);
            if (hitCount > 0)
            {
                for (int i = 0; i < hitCount; ++i)
                {
                    var hit = PhysicsUtil.tempResult[i];
                    var collider = hit.collider;
                    var go = collider.gameObject;
                    var sceneFloor = go.GetComponentCache<SceneFloorInfo>();
                    if (sceneFloor == null)
                    {
                        continue;
                    }
                    //归属于检测目标自己的局部动线直接忽略
                    if (checkActor != null && sceneFloor.Actor != null && sceneFloor.Actor == checkActor)
                    {
                        continue;
                    }
                    if ((!onlyCheckBullet || (sceneFloor.collisionTag.collidesWith & CollisionBelongDefine.Bullet) != 0))
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        public static Vector3 GetSrcPoint(Actor src)
        {
            if (_bUseInputSrcPos)
            {
                return _InputSrcPos;
            }
            else
            {
                if (!string.IsNullOrEmpty(_DummyNameTemp))
                {
                    var dummyPoint = src.ActorDummy.FindDummy(_DummyNameTemp);
                    if (dummyPoint != null)
                    {
                        Vector3 _pos = dummyPoint.transform.position;
                        _pos.z = 0f;
                        return _pos;
                    }
                }

                Transform srcPoint = src.ActorExpAttribute.m_AimPoint;
                Vector3 srcPos = srcPoint != null ? srcPoint.position : src.ActorPos;
                srcPos.z = 0f;
                return srcPos;
            }
        }

        public static void GetSrcPointAndDirection(Actor src, out Vector3 pos, out Vector3 forwardDir, out Vector3 upDir)
        {
            pos = Vector3.zero;
            forwardDir = Vector3.zero;
            upDir = Vector3.zero;

            if (_bUseInputSrcPos)
            {
                pos = _InputSrcPos;
                return;
            }
            else
            {
                if (!string.IsNullOrEmpty(_DummyNameTemp))
                {
                    var dummyPoint = src.ActorDummy.FindDummy(_DummyNameTemp);
                    if (dummyPoint != null)
                    {
                        Vector3 _pos = dummyPoint.transform.position;
                        _pos.z = 0f;
                        pos = _pos;
                        forwardDir = dummyPoint.transform.forward;
                        forwardDir.z = 0;
                        upDir = dummyPoint.transform.up;
                        upDir.z = 0;
                        return;
                    }
                }

                Transform srcPoint = src.ActorExpAttribute.m_AimPoint;
                Vector3 srcPos = srcPoint != null ? srcPoint.position : src.ActorPos;
                srcPos.z = 0f;
                pos = srcPos;               
            }
        }



        public SearchFilterBase.ActorSearch GetOneTarget(Actor src, List<int> paramList,
            bool useInputPos, Vector3 inputPos, GameLevelMG gameLevelMG)
        {
            if (SearcherOderUtil.CheckMuitOrderListVaild(_orderType))
            {
                // 需要排序,没法优化,需要获取整个list,再进行筛选
                var lst = GetTargetList(src, paramList, useInputPos, inputPos, gameLevelMG);
                if (lst != null && lst.Count > 0)
                {
                    return lst[0];
                }
                return null;
            }


            // 只要取到第一个合适的,就return,减少遍历次数

            _bUseInputSrcPos = useInputPos;
            _InputSrcPos = inputPos;
            _DummyNameTemp = _dummyName;

            if (src == null)
            {
                Logger.LogErrorD("SearchOneTarget  Failed: src is null!");
                return null;
            }

            if (src.HasDestory)
            {
                Logger.LogInfo($"SearchOneTarget Failed: src {src} has destory!");
                return null;
            }


#if MS_ENABLE_DEBUG
            if (src.m_GameLevelMG != gameLevelMG)
            {
                Logger.LogErrorD($"SearchOneTarget Failed: src{src} GameLevelMG != GameLevelMG {gameLevelMG.RoomNumber}!");
                return null;
            }
#endif

            SearchFilterBase.ActorSearch result = null;
            if (ContainTargetType(TargetSelectType.Actor))
            {
                SearchActorTarget(src, paramList, gameLevelMG, out result, true);
                if (result != null)
                    return result;
            }


            if (ContainTargetType(TargetSelectType.Bullet))
            {
                SearchBulletTarget(src, paramList, gameLevelMG, out result, true);
                if (result != null)
                    return result;                
            }


            if (ContainTargetType(TargetSelectType.Substitute))
            {
                SearchSubstituteActorTarget(src, paramList, gameLevelMG, out result, true);
                if (result != null)
                    return result;
            }


            return null;
        }


    }

}