public override void Action(SoldierFSMSystem fsm) { // TODO 判断当前目标是否有效, 如果无效则重新寻路 // 目标是否已死亡 if (targetDisplay == null || targetDisplay.ClusterData == null) { ReFindPath(); } // TODO 检测是否可移动 var memberData = fsm.Display.ClusterData.AllData.MemberData; if (memberData.CouldMove) { // 如果能移动, 上一帧是否不可移动, 是则切换移动 if (!couldMoveLastTime) { StartMove(fsm); couldMoveLastTime = true; } } // 不能移动则停止移动但不切状态 else { // if (couldMoveLastTime) { StopMove(fsm); couldMoveLastTime = false; } } }
/// <summary> /// 检测变更目标 /// </summary> private void CheckChangeTarget(SoldierFSMSystem fsm) { var list = ClusterManager.Single.CheckRange(new Vector2(clusterData.X, clusterData.Y), clusterData.AllData.MemberData.SightRange, clusterData.AllData.MemberData.Camp, true); if (list != null && list.Count > 0) { var closeObj = list[0]; if (closeObj == null) { } var closeDistance = float.MaxValue; foreach (var item in list) { if (!(item is ClusterData)) { continue; } var newDistance = GetDistance(clusterData, item); if (closeDistance > newDistance) { closeObj = item; closeDistance = newDistance; } } // 有变更 if (fsm.EnemyTarget == null || fsm.EnemyTarget.ClusterData == null || !closeObj.AllData.MemberData.ObjID.Equals(fsm.EnemyTarget.ClusterData.AllData.MemberData.ObjID)) { //Debug.Log("变更目标."); fsm.EnemyTarget = DisplayerManager.Single.GetElementById(closeObj.AllData.MemberData.ObjID); } } }
private void MakeFSM() { mFSMSystem = new SoldierFSMSystem(); SoldierIdleState idleState = new global::SoldierIdleState(mFSMSystem, this); idleState.AddTransition(SoldierTransition.SeeEnemy, SoldierStateID.Chase); SoldierChaseState chaseState = new global::SoldierChaseState(mFSMSystem, this); chaseState.AddTransition(SoldierTransition.NoEnemy_LostEnemy, SoldierStateID.Idle); chaseState.AddTransition(SoldierTransition.CanAttack, SoldierStateID.Attack); SoldierAttackState attactState = new global::SoldierAttackState(mFSMSystem, this); attactState.AddTransition(SoldierTransition.NoEnemy_LostEnemy, SoldierStateID.Idle); attactState.AddTransition(SoldierTransition.SeeEnemy, SoldierStateID.Chase); //mFSMSystem.AddState(idleState); //mFSMSystem.AddState(chaseState); //mFSMSystem.AddState(attactState); mFSMSystem.AddState(idleState, chaseState, attactState); }
/// <summary> /// 检查技能释放 /// </summary> /// <param name="fsm"></param> /// <returns></returns> public static bool CheckSkillRelease(SoldierFSMSystem fsm) { var searchData = fsm.Display.ClusterData; // 攻击范围内是否有敌人 var checkPos = new Vector2(fsm.Display.ClusterData.X, fsm.Display.ClusterData.Y); // 不可释放技能 if (!searchData.AllData.MemberData.CouldReleaseSkill) { return(false); } var list = TargetSelecter.TargetFilter(searchData, ClusterManager.Single.CheckRange(checkPos, searchData.AllData.MemberData.SkillRange, searchData.AllData.MemberData.Camp, true)); Utils.DrawGraphics(new CircleGraphics(checkPos, searchData.AllData.MemberData.SkillRange), Color.yellow); if (list != null && list.Count > 0) { // 攻击目标 fsm.TargetIsLoseEfficacy = false; // 检测技能 // TODO 技能的单位列表根据单位范围进行筛选 if (CheckSkill(fsm, list)) { fsm.IsCanInPutonggongji = false; fsm.IsCanInJinenggongji = true; return(true); } } return(false); }
public override void DoBeforeLeaving(SoldierFSMSystem fsm) { // 中断技能 if (skillTimer != null) { skillTimer.Kill(); } }
/// <summary> /// 退出技能状态 /// </summary> /// <param name="fsm"></param> private void Exist(SoldierFSMSystem fsm) { fsm.IsCanInJinenggongji = false; fsm.Skill = null; // 切换状态到行进状态 fsm.TargetIsLoseEfficacy = true; fsm.EnemyTarget = null; }
/// <summary> /// 设置目标单位 /// </summary> /// <param name="fsm"></param> /// <param name="res"></param> /// <returns></returns> private static bool SetTarget(SoldierFSMSystem fsm, IList <PositionObject> res) { // TODO 包装随机 // TODO 取最近的 var target = res[RandomPacker.Single.GetRangeI(0, res.Count)]; fsm.EnemyTarget = DisplayerManager.Single.GetElementByPositionObject(target); return(res.Count > 0); }
/// <summary> /// 初始化血条和寻路 士兵开始行走 /// </summary> /// <param name="fsm"></param> public override void DoBeforeEntering(SoldierFSMSystem fsm) { //Debug.Log("行进:" + fsm.Display.GameObj.name); base.DoBeforeEntering(fsm); fsm.Display.ClusterData.StopMove(); fsm.IsCanRun = true; // 切换动作 SwitchAnim(fsm, SoldierAnimConst.DAIJI, WrapMode.Loop); }
/// <summary> /// 检查是否可以切换状态 /// </summary> /// <param name="fsm"></param> /// <returns></returns> public static bool CheckChangeState(SoldierFSMSystem fsm) { // 检测是否可技能攻击与有可释放技能 if (CheckSkillRelease(fsm)) { return(true); } return(CheckNormalAttack(fsm)); }
public void StartFSM([NotNull] DisplayOwner obj) { //初始化状态机 fsm = new SoldierFSMSystem(); fsm.Display = obj; // 初始化行为状态机 InitState(obj.ClusterData.AllData.MemberData.BehaviorType); }
/// <summary> /// 是否需要重新寻路 /// </summary> /// <param name="fsm"></param> /// <returns></returns> private bool IsNeedReFindPath(SoldierFSMSystem fsm) { var targetClusterData = fsm.EnemyTarget.ClusterData; // 判断目标点与当前目标的距离 var distance = (Utils.WithOutY(targetPos) - Utils.WithOutY(targetClusterData.transform.position)).magnitude; var minDistance = clusterData.Diameter * ClusterManager.Single.UnitWidth * 0.5f + targetClusterData.Diameter * ClusterManager.Single.UnitWidth * 0.5f; return(distance > minDistance); }
/// <summary> /// 初始化血条和寻路 士兵开始行走 /// </summary> /// <param name="fsm"></param> private void StartMove(SoldierFSMSystem fsm) { fsm.Display.ClusterData.ContinueMove(); // 切换动作 SwitchAnim(fsm, SoldierAnimConst.XINGJIN, WrapMode.Loop); // TODO 重巡路条件 // 重新寻路 ReFindPath(); }
public override void Action(SoldierFSMSystem fsm) { if (!_stateIsLose) { // 范围内没有敌人 if (AdjustTargetIsInRange(fsm)) { fsm.IsCanInPutonggongji = false; fsm.TargetIsLoseEfficacy = true; } } }
public override void DoBeforeEntering(SoldierFSMSystem fsm) { // 单位转向目标 var clusterData = fsm.Display.ClusterData; if (clusterData != null && fsm.EnemyTarget != null && fsm.EnemyTarget.ClusterData != null) { clusterData.RotateToWithoutYAxis(fsm.EnemyTarget.ClusterData.transform.position); skillIsDone = false; // 被释放技能 var skill = fsm.Skill; if (skill == null) { throw new Exception("被释放技能为空."); } param = FormulaParamsPackerFactroy.Single.GetFormulaParamsPacker( fsm.Skill, fsm.Display, fsm.EnemyTarget); counter = 0; skill.IsDone = false; // 开始释放技能 if (skill.ReleaseTime > 0) { // 执行技能起始效果(Attach) SkillManager.Single.DoFormula(skill.GetAttachFormula(param)); skillTimer = new Timer(skill.IntervalTime, true); skillTimer.OnCompleteCallback(() => { ReleaseSkill(fsm); }) .OnKill(() => { fsm.Skill.IsDone = true; // 执行技能结束效果(Detach) SkillManager.Single.DoFormula(skill.GetDetachFormula(param)); }).Start(); } else { skillIsDone = true; ReleaseSkill(fsm); } // 设置技能进CD SkillManager.Single.SetSkillInCD(skill); } else { // 目标已死亡 Exist(fsm); } }
/// <summary> /// 设置目标单位 /// </summary> /// <param name="fsm"></param> /// <param name="res"></param> /// <returns></returns> public static bool SetTarget(SoldierFSMSystem fsm, IList <PositionObject> res) { //var ran = new System.Random(); if (res == null || res.Count == 0) { return(false); } // TODO 取最近的 var target = res[0]; fsm.EnemyTarget = DisplayerManager.Single.GetElementByPositionObject(target); return(fsm.EnemyTarget != null); }
/// <summary> /// 状态的改变发生在这里 /// </summary> public void CheckTrigger(SoldierFSMSystem fsm) { for (int i = 0; i < _fsmTrriggerList.Count; i++) { //if (_fsmTrriggerList[i].CheckTrigger(fsm)) if (_fsmTrriggerList[i].CheckTriggerFunc(fsm)) { var state = SoldierFSMFactory.GetStateIdByTrigger(_fsmTrriggerList[i].triggerId); fsm.ChangeState(state); //Debug.Log("切换状态:" + state); break; } } }
public override void DoBeforeLeaving(SoldierFSMSystem fsm) { fsm.IsCanInPutonggongji = false; fsm.TargetIsLoseEfficacy = true; if (_fireTimer != null) { _fireTimer.Kill(); } if (_reloadTimer != null) { _reloadTimer.Kill(); } _isDaiJi = false; }
/// <summary> /// 判断目标是否还在范围内 两种情况会脱离范围 跑出视野 或者血为0 /// </summary> /// <returns></returns> private bool AdjustTargetIsInRange(SoldierFSMSystem fsm) { // 验证单位是否有效 if (null == fsm.EnemyTarget || null == fsm.EnemyTarget.GameObj || null == fsm.EnemyTarget.ClusterData) { return(true); } var targetPos = fsm.EnemyTarget.ClusterData.Position; var myPos = fsm.Display.ClusterData.Position; var distance = AI_Math.V2Distance(targetPos.x, targetPos.z, myPos.x, myPos.z) - fsm.EnemyTarget.ClusterData.Diameter * ClusterManager.Single.UnitWidth * 0.5f - fsm.Display.ClusterData.Diameter * ClusterManager.Single.UnitWidth * 0.5f; return((distance > fsm.Display.ClusterData.AllData.MemberData.AttackRange) || (fsm.EnemyTarget.ClusterData.AllData.MemberData.CurrentHP <= 0)); }
public override void DoBeforeEntering(SoldierFSMSystem fsm) { _fireTimer = new Timer(fsm.Display.ClusterData.AllData.MemberData.AttackRate1, true); _fireTimer.OnCompleteCallback(() => { fire(fsm); }).Start(); _bulletCount = fsm.Display.ClusterData.AllData.MemberData.Clipsize1; //_bulletMax = fsm.Display.ClusterData.AllData.MemberData.Clipsize1; //_reloadTime = fsm.Display.ClusterData.AllData.MemberData.ReloadTime1; // 单位转向目标 var clusterData = fsm.Display.ClusterData; if (clusterData != null && fsm.EnemyTarget != null && fsm.EnemyTarget.ClusterData != null) { clusterData.RotateToWithoutYAxis(fsm.EnemyTarget.ClusterData.transform.position); } }
/// <summary> /// 是否可以技能攻击 /// </summary> /// <param name="fsm"></param> /// <param name="res">目标列表</param> /// <returns></returns> public static bool CheckSkill(SoldierFSMSystem fsm, IList <PositionObject> res) { var result = false; // 判断主动技能是否可释放, 可释放则释放技能, 否则普通攻击 var skillInfoList = fsm.Display.ClusterData.AllData.SkillInfoList; if (skillInfoList.Count > 0) { // 判断技能CD的长短, 释放技能最长的 foreach (var skill in skillInfoList) { // 技能目标选择器 // 是否为主动技能 // 技能没有在CD中 if (!skill.IsActive || CDTimer.Instance().IsInCD(skill.Num, fsm.Display.ClusterData.AllData.MemberData.ObjID.ID, skill.CDGroup)) { continue; } // 判断技能是否符合释放条件(范围内有适合的单位) if (skill.WeightData != null) { res = TargetSelecter.TargetFilter(skill.WeightData, skill.ReleaseMember.ClusterData, res); } if (res != null && res.Count > 0) { fsm.Skill = skill; result = true; break; } } } if (result) { // 确定释放技能, 设置目标 //System.Random ran = new System.Random(); var target = res[0]; fsm.EnemyTarget = DisplayerManager.Single.GetElementByPositionObject(target); } return(result); }
/// <summary> /// 进入改状态时执行 /// </summary> /// <param name="fsm"></param> public override void DoBeforeEntering(SoldierFSMSystem fsm) { // 加载当前数据 //Debug.Log("追击状态:" + fsm.Display.GameObj.name); clusterData = fsm.Display.ClusterData as ClusterData; targetPos = fsm.EnemyTarget.ClusterData.transform.position; // 切换动作 //var myself = fsm.Display.RanderControl; //myself.ModelRander.SetClip("run".GetHashCode()); ReFindPath(fsm); // 单位转向目标 if (clusterData != null && fsm.EnemyTarget != null && fsm.EnemyTarget.ClusterData != null) { clusterData.RotateToWithoutYAxis(fsm.EnemyTarget.ClusterData.transform.position); } }
private void makeFSM() { mFSMSystem = new SoldierFSMSystem(); SoldierIdleState idleState = new SoldierIdleState(mFSMSystem, this); idleState.addTransition(SoldierTransition.SeeEnemy, SoldierStateID.Chase); SoldierChaseState chaseState = new SoldierChaseState(mFSMSystem, this); chaseState.addTransition(SoldierTransition.NoEnemy, SoldierStateID.Idle); chaseState.addTransition(SoldierTransition.CanAttack, SoldierStateID.Attack); SoldierAttackState attackState = new SoldierAttackState(mFSMSystem, this); attackState.addTransition(SoldierTransition.NoEnemy, SoldierStateID.Idle); attackState.addTransition(SoldierTransition.SeeEnemy, SoldierStateID.Chase); mFSMSystem.addState(idleState, chaseState, attackState); }
///// <summary> ///// 检测条件 ///// </summary> ///// <param name="fsm"></param> ///// <returns></returns> //public override bool CheckTrigger(SoldierFSMSystem fsm) //{ // //// 状态检查路由 // //switch (fsm.CurrentStateID) // //{ // // // 行进追击切准备战斗 // // case SoldierStateID.Xingjin: // // case SoldierStateID.ZhuiJi: // // { // // return CheckChangeState(fsm); // // } // // // 技能攻击/普通攻击切准备战斗 // // case SoldierStateID.PutongGongji: // // case SoldierStateID.JinengGongji: // // { // // //// 如果有正在攻击目标则 不切换状态 // // //// 判断是否有正在攻击的目标 // // //if ((!fsm.IsCanInJinenggongji && !fsm.IsCanInPutonggongji) || fsm.TargetIsLoseEfficacy) // // //{ // // // // 可以切换 // // // return CheckChangeState(fsm); // // //} // // return false; // // } // //} // return Check(fsm); //} public static bool Check(SoldierFSMSystem fsm) { // 状态检查路由 switch (fsm.CurrentStateID) { // 行进追击切准备战斗 case SoldierStateID.Xingjin: case SoldierStateID.ZhuiJi: { return(CheckChangeState(fsm)); } // 技能攻击/普通攻击切准备战斗 case SoldierStateID.PutongGongji: { return(false); } } return(false); }
private void MakeFsm() { Fsm = new SoldierFSMSystem(); SoldierIdleState idle = new SoldierIdleState(Fsm, this); idle.AddTransition(SoldierTransition.SeeEnemy, SoldierStateID.Chase); SoldierChaseState chase = new SoldierChaseState(Fsm, this); chase.AddTransition(SoldierTransition.NoEnemy, SoldierStateID.Idle); chase.AddTransition(SoldierTransition.CanAttack, SoldierStateID.Attack); SoldierAttackState attack = new SoldierAttackState(Fsm, this); attack.AddTransition(SoldierTransition.NoEnemy, SoldierStateID.Idle); attack.AddTransition(SoldierTransition.SeeEnemy, SoldierStateID.Chase); Fsm.AddState(idle, chase, attack); }
/// <summary> /// 每帧检测 /// </summary> /// <param name="fsm"></param> public override void Action(SoldierFSMSystem fsm) { // 继续查找最近单位, 如果有更近的选择更近的 CheckChangeTarget(fsm); // 检测目标是否在追击范围内 if (TargetIsInScope(fsm)) { // 检测目标是否与当前目标点差距太大, 如果没有需用寻路, 如果有则重新寻路 if (IsNeedReFindPath(fsm)) { // 重巡路径 ReFindPath(fsm); } } else { // 切换行进状态 fsm.IsZhuiJi = false; fsm.TargetIsLoseEfficacy = true; } }
/// <summary> /// 是否超出追击范围 /// </summary> /// <returns></returns> private bool TargetIsInScope(SoldierFSMSystem fsm) { var result = false; var targetClusterData = fsm.EnemyTarget.ClusterData; if (targetClusterData != null) { var distance = (Utils.WithOutY(targetClusterData.transform.position) - Utils.WithOutY(clusterData.transform.position)).magnitude; result = distance - targetClusterData.Diameter * ClusterManager.Single.UnitWidth * 0.5f - clusterData.Diameter * ClusterManager.Single.UnitWidth * 0.5f < clusterData.AllData.MemberData.SightRange; // 判断目标是否存活, 如果死亡切行进 if (targetClusterData.AllData.MemberData.CurrentHP <= 0) { result = false; } } return(result); }
/// <summary> /// 准备战斗 作战单位停止运动 并且判断接下来是普通攻击或者技能攻击 /// </summary> /// <param name="fsm"></param> public override void DoBeforeEntering(SoldierFSMSystem fsm) { //Debug.Log("准备战斗状态:" + fsm.Display.GameObj.name); if (fsm.IsCanInPutonggongji || fsm.IsCanInJinenggongji) { //var myself = fsm.Display.RanderControl; //myself.ModelRander.SetClip("attack".GetHashCode()); fsm.Display.ClusterData.StopMove(); } // 状态切换路由 //if (fsm.EnemyTarget != null && fsm.Skill == null) //{ // fsm.IsCanInPutonggongji = true; //} //else if(fsm.Skill != null) //{ // fsm.IsCanInJinenggongji = true; //} }
private void MakeFSM() { mFSMSystem = new SoldierFSMSystem(); SoldierFSMState standbyState = new StateSoldierStandby(mFSMSystem, this); standbyState.AddTransition(SoldierTransition.SeeEnemy, SoldierStateID.ChaseState); SoldierFSMState chaseState = new StateSoldierChase(mFSMSystem, this); chaseState.AddTransition(SoldierTransition.DonotSeeEnemy, SoldierStateID.StandbyState); chaseState.AddTransition(SoldierTransition.EnemyInTheAttackRange, SoldierStateID.AttackState); SoldierFSMState attackState = new StateSoldierAttack(mFSMSystem, this); attackState.AddTransition(SoldierTransition.DonotSeeEnemy, SoldierStateID.StandbyState); attackState.AddTransition(SoldierTransition.EnemyOutOfTheAttackRange, SoldierStateID.ChaseState); mFSMSystem.AddState(standbyState); mFSMSystem.AddState(chaseState); mFSMSystem.AddState(attackState); }
/// <summary> /// 重巡路径 /// </summary> /// <param name="fsm"></param> private void ReFindPath(SoldierFSMSystem fsm) { //Debug.Log(""); // 重新寻路设置目标点 // 当前地图数据 int[][] mapData = null; // 当前地图数据 switch (clusterData.AllData.MemberData.GeneralType) { case Utils.GeneralTypeAir: mapData = LoadMap.Single.GetAirMapData(); break; case Utils.GeneralTypeSurface: mapData = LoadMap.Single.GetSurfaceMapData(); break; } // 当前单位位置映射 var startPos = Utils.PositionToNum(LoadMap.Single.MapPlane.transform.position, clusterData.transform.position, ClusterManager.Single.UnitWidth, ClusterManager.Single.MapWidth, ClusterManager.Single.MapHeight); // 当前目标位置映射 var endPos = Utils.PositionToNum(LoadMap.Single.MapPlane.transform.position, fsm.EnemyTarget.ClusterData.transform.position, ClusterManager.Single.UnitWidth, ClusterManager.Single.MapWidth, ClusterManager.Single.MapHeight); // 生成路径 var path = AStarPathFinding.SearchRoad(mapData, startPos[0], startPos[1], endPos[0], endPos[1], (int)clusterData.Diameter, (int)clusterData.Diameter + 1); if (path != null && path.Count > 0) { // 清空当前目标点 clusterData.ClearTarget(); targetPos = fsm.EnemyTarget.ClusterData.transform.position; clusterData.PushTargetList(Utils.NumToPostionByList(LoadMap.Single.MapPlane.transform.position, path, ClusterManager.Single.UnitWidth, ClusterManager.Single.MapWidth, ClusterManager.Single.MapHeight)); } else { Debug.Log("zhuiji 目标点不可达:start:" + startPos[0] + "," + startPos[1] + " end:" + endPos[0] + "," + endPos[1]); } }
///// <summary> ///// 检测条件 ///// </summary> ///// <param name="fsm"></param> ///// <returns></returns> //public override bool CheckTrigger(SoldierFSMSystem fsm) //{ // return Check(fsm); //} public static bool Check(SoldierFSMSystem fsm) { switch (fsm.CurrentStateID) { // 行进切追击 case SoldierStateID.Xingjin: { // 如果正在技能攻击或普通攻击则不进入追击状态 if (fsm.IsCanInJinenggongji || fsm.IsCanInPutonggongji) { return(false); } var clusterData = fsm.Display.ClusterData; //var objId = clusterData.MemberData.ObjID; // 视野范围内是否有敌人 var pos = new Vector2(clusterData.X, clusterData.Y); // 范围内符合阵营条件的单位列表 var scopeMemberList = ClusterManager.Single.CheckRange(pos, clusterData.AllData.MemberData.SightRange, clusterData.AllData.MemberData.Camp, true); // 按照权重与是否可攻击单位选择 var filtedlist = TargetSelecter.TargetFilter(clusterData, scopeMemberList); Utils.DrawGraphics(new CircleGraphics(pos, clusterData.AllData.MemberData.SightRange), Color.yellow); //fsm.Display.ClusterData.MemberData.SightRange if (filtedlist != null && filtedlist.Count > 0) { // 追击目标 // 设置状态 切追击状态 fsm.IsZhuiJi = true; return(SetTarget(fsm, filtedlist)); } return(fsm.IsZhuiJi); } } return(false); }