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); }