BehaveResult Tick(Tree sender)
        {
            if (!GetData <Data>(sender, ref m_Data))
            {
                return(BehaveResult.Failure);
            }

            if (entity.IsDeath())
            {
                return(BehaveResult.Failure);
            }

            if (!IsNpc || !IsNpcFollower || IsNpcFollowerWork || IsNpcFollowerCut)
            {
                if (IsOnVCCarrier)
                {
                    GetOff();
                }

                if (IsOnRail)
                {
                    GetOffRailRoute();
                }

                SetNpcState(ENpcState.UnKnown);
                return(BehaveResult.Failure);
            }

            SetNpcAiType(ENpcAiType.NpcFollower);
            PeTrans tr = NpcMaster.peEntity.peTrans;

            EatSth();

            if (IsSkillCast)
            {
                SetNpcState(ENpcState.UnKnown);
                return(BehaveResult.Failure);
            }


            if (IsMotionRunning(PEActionType.HoldShield))
            {
                EndAction(PEActionType.HoldShield);
            }


            if (!IsOnVCCarrier && !IsOnRail && Time.time - m_Data.StartSearchGatherTime > m_Data.SearchGatherTime)
            {
                if (CanCather())//|| LootItemDropPeEntity.HasLootEntity()
                {
                    return(BehaveResult.Failure);
                }
                else
                {
                    m_Data.StartSearchGatherTime = Time.time;
                }
            }

            if (entity.isRagdoll || entity.IsDeath())
            {
                return(BehaveResult.Running);
            }

            Vector3       targetVelocity  = Vector3.zero;
            PassengerCmpt passengerTarget = NpcMaster.Entity.passengerCmpt;

            if (passengerTarget != null && passengerTarget.IsOnVCCarrier)
            {
                //玩家在载具上NPC上车选座:跟随任务NPC优先
                int index = passengerTarget.drivingController.FindEmptySeatIndex();
                if (index >= 0 && !IsOnVCCarrier && (index - NpcMaster.RQFollowersIndex >= 0))
                {
                    GetOn(passengerTarget.drivingController, index);
                    MoveToPosition(Vector3.zero);
                }
                else
                {
                    //等到玩家entity移动速度
                    if (NpcMaster != null && NpcMaster.Entity.motionMove != null)
                    {
                        targetVelocity = NpcMaster.Entity.motionMove.velocity;
                    }
                }
            }
            else if (passengerTarget != null && passengerTarget.IsOnRail)
            {
                Railway.Route route = Railway.Manager.Instance.GetRoute(passengerTarget.railRouteId);
                if (route != null && route.train != null && route.train.HasEmptySeat() && !IsOnRail)
                {
                    GetOn(passengerTarget.railRouteId, entity.Id, true);
                }
                else
                {
                    if (NpcMaster != null && NpcMaster.Entity.motionMove != null)
                    {
                        targetVelocity = NpcMaster.Entity.motionMove.velocity;
                    }
                }
            }
            else
            {
                //玩家不在载具上时,NPC下载具
                if (passengerTarget != null && !passengerTarget.IsOnVCCarrier && IsOnVCCarrier)
                {
                    GetOff();
                }

                //下轻轨
                if (passengerTarget != null && !passengerTarget.IsOnRail && IsOnRail)
                {
                    GetOffRailRoute();
                }

                if (NpcMaster != null && NpcMaster.Entity.motionMove != null)
                {
                    targetVelocity = NpcMaster.Entity.motionMove.velocity;
                }
            }



            Vector3 avoidDir0 = Vector3.zero;
            Vector3 avoidDir1 = Vector3.zero;
            Vector3 avoidDir2 = Vector3.zero;
            Vector3 avoidDir3 = Vector3.zero;

            bool _IsnearLeague   = entity.NpcCmpt.HasNearleague;
            bool _IsBlockBrush   = AiUtil.CheckBlockBrush(entity, out avoidDir0);
            bool _IsnearDig      = AiUtil.CheckDig(entity, NpcMaster.Entity, out avoidDir1);
            bool _IsDragging     = AiUtil.CheckDraging(entity, out avoidDir2);
            bool _IsNearCreation = AiUtil.CheckCreation(entity, out avoidDir3);

            bool _needAvoid = _IsnearLeague || _IsnearDig || _IsBlockBrush || _IsDragging || _IsNearCreation;
            //bool _needAvoid0 = _IsnearDig || _IsBlockBrush || _IsDragging || _IsNearCreation;
            bool _Isstay       = IsNpcFollowerSentry && !_needAvoid;
            bool _IsOnCreation = IsOnVCCarrier || IsOnRail;

            bool _InfirR = m_Data.InRadius(position, tr.position, 0.0f, m_Data.firRadius, true);
            bool _InsndR = m_Data.InRadius(position, tr.position, m_Data.firRadius, m_Data.sndRadius, true);
            //bool _InthdR = m_Data.InRadius(position, tr.position, m_Data.sndRadius, m_Data.thdRadius * 2.0f, true);

            Vector3 avoidplayer = position - tr.trans.position;
            Vector3 avoid0      = avoidDir0 != Vector3.zero ? position - avoidDir0 : Vector3.zero;
            Vector3 avoid1      = avoidDir1 != Vector3.zero ? position - avoidDir1 : Vector3.zero;
            Vector3 avoid2      = avoidDir2 != Vector3.zero ? position - avoidDir2 : Vector3.zero;
            Vector3 avoid3      = avoidDir3 != Vector3.zero ? position - avoidDir3 : Vector3.zero;
            Vector3 _AvoidDir   = avoidplayer + avoid0 + avoid1 + avoid2 + avoid3 + existent.forward;

            bool _IsInSpSence = RandomDunGenUtil.IsInDungeon(entity);//(Pathea.PeGameMgr.IsAdventure && RandomDungenMgr.Instance != null && RandomDungenMgrData.dungeonBaseData != null);
            //|| (Pathea.PeGameMgr.IsStory && Pathea.PeGameMgr.IsSingle && Pathea.SingleGameStory.curType != Pathea.SingleGameStory.StoryScene.MainLand)
            //|| (Pathea.PeGameMgr.IsStory && Pathea.PeGameMgr.IsTutorial && Pathea.SingleGameStory.curType != Pathea.SingleGameStory.StoryScene.MainLand)
            //|| (Pathea.PeGameMgr.IsStory && Pathea.PeGameMgr.IsMulti && PlayerNetwork.mainPlayer != null && PlayerNetwork.mainPlayer._curSceneId != (int)Pathea.SingleGameStory.StoryScene.MainLand);

            //在建筑内跟随:检测头上是否有碰撞,保持和玩家的Y值差,不用找点方式寻路
            bool _underBlock     = PETools.PEUtil.IsUnderBlock(entity);
            bool _IsForwardBlock = _IsInSpSence ? false : _underBlock?PETools.PEUtil.IsForwardBlock(entity, entity.peTrans.forward, 2.0f) : false;

            //NPC不在载具上时跟随
            if (!_IsOnCreation)
            {
                //超出跟随距离snd_thd
                if (!_InfirR && !_InsndR)
                {
                    if (GameConfig.IsMultiMode)
                    {
                        if (Stucking(1.0f) || IsNpcFollowerSentry)
                        {
                            Vector3 fixedPos = GetFixedPosition(PETools.PEUtil.MainCamTransform.position, -PETools.PEUtil.MainCamTransform.forward, tr.position, -tr.forward, tr.bound.size.y);
                            if (PEUtil.CheckErrorPos(fixedPos))
                            {
                                SetPosition(fixedPos);
                                MoveToPosition(Vector3.zero);
                            }
                        }
                        else
                        {
                            m_Data.CalculateAnchor(position, PETools.PEUtil.MainCamTransform.position, -PETools.PEUtil.MainCamTransform.forward);
                        }
                    }
                    else
                    {
                        if (Stucking(1.0f) || _IsForwardBlock) // || IsNpcFollowerStand 单人放哨时 不跟随传送原地待命 || !_canPointMove
                        {
                            Vector3 fixedPos = GetFixedPosition(PETools.PEUtil.MainCamTransform.position, -PETools.PEUtil.MainCamTransform.forward, tr.position, -tr.forward, tr.bound.size.y);
                            float   dy       = Mathf.Abs(tr.position.y - fixedPos.y);
                            if (PEUtil.CheckErrorPos(fixedPos) && dy <= 3.0f)
                            {
                                SetPosition(fixedPos);
                                MoveToPosition(Vector3.zero);
                            }
                        }
                        else
                        {
                            m_Data.CalculateAnchor(position, PETools.PEUtil.MainCamTransform.position, -PETools.PEUtil.MainCamTransform.forward);
                        }

                        m_Data.startPralTime = Time.time;
                    }
                }

                //在内圈
                if (_InfirR && !m_Data.InRadius(position, tr.trans.position + m_Data.Anchor, m_Data.firRadius, m_Data.sndRadius, true))
                {
                    m_Data.ResetCalculated();
                    m_Data.CalculateAnchor(position, PETools.PEUtil.MainCamTransform.position, -PETools.PEUtil.MainCamTransform.forward);
                    m_Data.startPralTime = Time.time;
                }

                bool needCdTime = _IsInSpSence ?  !_InsndR : true;
                if (needCdTime && Time.time - m_Data.startPralTime >= m_Data.waitPralTime)
                {
                    m_Data.startPralTime = Time.time;
                    m_Data.CalculateAnchor(position, PETools.PEUtil.MainCamTransform.position, -PETools.PEUtil.MainCamTransform.forward);
                    m_Data.ResetCalculatedDir();
                }
                bool _nearAnchor   = IsReached(position, tr.trans.position + m_Data.Anchor, true, 2.0f);
                bool _InPralCdTime = Time.time - m_Data.startPralTime < m_Data.waitPralTime;
                bool _moveWait     = _InPralCdTime && _nearAnchor && !_needAvoid; //

                if (!_Isstay)
                {
                    if (!_needAvoid)
                    {
                        if (_moveWait)
                        {
                            if (_IsForwardBlock || Stucking(1.0f))
                            {
                                if (_IsInSpSence)
                                {
                                    m_Data.ResetCalculatedDir();
                                }

                                m_Data.GetCanMoveDirtion(entity, 30.0f);
                                if (m_Data.GetAnchorDir() != Vector3.zero)
                                {
                                    m_Data.ResetCalculated();
                                    m_Data.CalculateAnchor(position, PETools.PEUtil.MainCamTransform.position, -PETools.PEUtil.MainCamTransform.forward);
                                    FaceDirection(m_Data.GetAnchorDir());
                                }
                            }
                            StopMove();
                            m_Data.ResetCalculated();
                        }
                        else
                        {
                            if (_IsForwardBlock || Stucking(1.0f))
                            {
                                if (_IsInSpSence)
                                {
                                    m_Data.ResetCalculatedDir();
                                }

                                m_Data.GetCanMoveDirtion(entity, 30.0f);
                                if (m_Data.GetAnchorDir() != Vector3.zero)
                                {
                                    m_Data.ResetCalculated();
                                    m_Data.CalculateAnchor(position, PETools.PEUtil.MainCamTransform.position, -PETools.PEUtil.MainCamTransform.forward);
                                    FaceDirection(m_Data.GetAnchorDir());
                                }
                                StopMove();
                            }
                            else
                            {
                                Vector3    followPos = m_Data.GetFollowPosition(tr.trans, targetVelocity);
                                Vector3    speedPos  = _underBlock ? tr.trans.position : followPos;
                                SpeedState speed     = m_Data.CalculateSpeedState(PEUtil.SqrMagnitudeH(position, speedPos));
                                // if (speed == SpeedState.Walk && _needAvoid) speed = SpeedState.Run;
                                if (IsReached(position, tr.trans.position + m_Data.Anchor, false))
                                {
                                    //on the bridgew
                                    Vector3 pos0 = tr.trans.position + m_Data.Anchor;
                                    float   Y    = pos0.y - position.y;
                                    float   dy   = Mathf.Abs(Y);
                                    if (dy >= 1.0f)
                                    {
                                        if (Y > 0)
                                        {
                                            pos0 = PETools.PEUtil.CorrectionPostionToStand(pos0);
                                        }
                                        else
                                        {
                                            pos0 = PETools.PEUtil.CorrectionPostionToStand(pos0, 6.0f, 8.0f);
                                        }

                                        SetPosition(pos0);
                                        m_Data.ResetCalculated();
                                        m_Data.CalculateAnchor(position, PETools.PEUtil.MainCamTransform.position, -PETools.PEUtil.MainCamTransform.forward);
                                    }
                                }
                                MoveToPosition(followPos, speed);
                            }
                        }
                    }
                    else
                    {
                        m_Data.ResetCalculated();
                        m_Data.CalculateAnchor(position, tr.trans.position, _AvoidDir);
                        //Vector3 pos = _AvoidDir * 5.0f + position;
                        MoveDirection(_AvoidDir, SpeedState.Run);
                    }
                }
                else
                {
                    StopMove();
                }
            }

            //有怪物时,NPC不在载具上即退出此行为-切换为攻击
            if (attackEnemy != null && !IsOnVCCarrier && !IsOnRail)
            {
                return(BehaveResult.Failure);
            }

            return(BehaveResult.Running);
        }