/// <summary> /// 筛选对象 /// </summary> /// <param name="searchWeightData">搜索对象目标权重数据</param> /// <param name="searchPositionObject">搜索对象集群数据</param> /// <param name="dataList">搜索列表</param> /// <returns></returns> public static IList <FormulaParamsPacker> TargetFilter(SelectWeightData searchWeightData, PositionObject searchPositionObject, IList <FormulaParamsPacker> dataList) { IList <FormulaParamsPacker> result = null; if (searchPositionObject != null && searchPositionObject.AllData.MemberData != null && dataList != null) { if (searchWeightData != null) { result = new List <FormulaParamsPacker>(); for (var i = 0; i < dataList.Count; i++) { var item = dataList[i]; if (GetWeight(searchWeightData, searchPositionObject, item.ReceiverMenber.ClusterData) >= 0) { result.Add(item); } } } else { // 无筛选条件则返回所有单位 result = dataList; } } return(result); }
///// <summary> ///// 筛选对象 ///// </summary> ///// <param name="searchWeightData">搜索对象目标权重数据</param> ///// <param name="searchPositionObject">搜索对象集群数据</param> ///// <param name="dataList">搜索列表</param> ///// <returns></returns> //public static IList<FormulaParamsPacker> TargetFilter(SelectWeightData searchWeightData, PositionObject searchPositionObject, IList<FormulaParamsPacker> dataList) //{ // IList<FormulaParamsPacker> result = null; // if (searchPositionObject != null && searchPositionObject.AllData.MemberData != null && dataList != null) // { // if (searchWeightData != null) // { // result = new List<FormulaParamsPacker>(); // for (var i = 0; i < dataList.Count; i++) // { // var item = dataList[i]; // if (GetWeight(searchWeightData, searchPositionObject, item.ReceiverMenber.ClusterData) >= 0) // { // result.Add(item); // } // } // } // else // { // // 无筛选条件则返回所有单位 // result = dataList; // } // } // return result; //} /// <summary> /// 筛选对象 /// </summary> /// <param name="searchWeightData">搜索对象目标权重数据</param> /// <param name="searchPositionObject">搜索对象集群数据</param> /// <param name="dataList">搜索列表</param> /// <returns></returns> public static IList <T> TargetFilter <T>(SelectWeightData searchWeightData, T searchPositionObject, IList <T> dataList) where T : IAllDataHolder, IBaseMember, IGraphicsHolder { IList <T> result = null; if (searchPositionObject != null && searchPositionObject.AllData.MemberData != null && dataList != null) { if (searchWeightData != null) { // 目标列表Array var targetArray = new T[dataList.Count]; // 目标权重值 var weightKeyArray = new float[dataList.Count]; for (var i = 0; i < dataList.Count; i++) { var targetPositionObj = dataList[i]; var sumWeight = GetWeight(searchWeightData, searchPositionObject, targetPositionObj); // TODO 各项为插入式结构 // 比对列表中的值, 大于其中某项值则将其替换位置并讲其后元素向后推一位. for (var j = 0; j < weightKeyArray.Length; j++) { if (sumWeight > weightKeyArray[j]) { for (var k = weightKeyArray.Length - 1; k > j; k--) { weightKeyArray[k] = weightKeyArray[k - 1]; targetArray[k] = targetArray[k - 1]; } weightKeyArray[j] = sumWeight; targetArray[j] = targetPositionObj; break; } } } result = targetArray.Where(targetItem => targetItem != null).ToList(); } else { // 无筛选条件则返回所有单位 result = dataList; } } return(result); }
static int set_WeightData(IntPtr L) { object o = null; try { o = ToLua.ToObject(L, 1); SkillInfo obj = (SkillInfo)o; SelectWeightData arg0 = (SelectWeightData)ToLua.CheckObject(L, 2, typeof(SelectWeightData)); obj.WeightData = arg0; return(0); } catch (Exception e) { return(LuaDLL.toluaL_exception(L, e, o == null ? "attempt to index WeightData on a nil value" : e.Message)); } }
static int get_WeightData(IntPtr L) { object o = null; try { o = ToLua.ToObject(L, 1); SkillInfo obj = (SkillInfo)o; SelectWeightData ret = obj.WeightData; ToLua.PushObject(L, ret); return(1); } catch (Exception e) { return(LuaDLL.toluaL_exception(L, e, o == null ? "attempt to index WeightData on a nil value" : e.Message)); } }
/// <summary> /// 是否可以选择目标 /// </summary> /// <param name="selectWeightData">选择方权重数据</param> /// <param name="targetAllData">目标方基础数据</param> /// <returns>是否可以选择</returns> public static bool CouldSelectTarget(SelectWeightData selectWeightData, AllData targetAllData) { var result = true; var targetData = targetAllData.MemberData; // 如果不可攻击建筑并且是建筑 // 或不可攻击空中并且是空中 // 或不可攻击地面并且是地面 // 或处于死亡或假死状态 // 或目标是障碍物 // 则不能选择该单位 // 排除阵营 if ((selectWeightData.BuildWeight < 0 && targetData.GeneralType == Utils.GeneralTypeBuilding) || (selectWeightData.AirWeight < 0 && targetData.GeneralType == Utils.GeneralTypeAir) || (selectWeightData.SurfaceWeight < 0 && targetData.GeneralType == Utils.GeneralTypeSurface) || targetData.CurrentHP <= 0) { return(false); } // 判断阵营 if ((selectWeightData.CampWeight != 1 || targetData.Camp != 1) && (selectWeightData.CampWeight != 2 || targetData.Camp != 2) && selectWeightData.CampWeight != 0) { return(false); } // 判断生命区间 if (selectWeightData.HpScopeMaxValue >= 0 && selectWeightData.HpScopeMinValue >= 0) { // 区分判断类型 switch (selectWeightData.HpScopeType) { case 0: // 计算生命值百分比 var percent = targetData.CurrentHP / targetData.TotalHp; if (percent < selectWeightData.HpScopeMinValue || percent > selectWeightData.HpScopeMaxValue) { return(false); } break; case 1: if (targetData.CurrentHP < selectWeightData.HpScopeMinValue || targetData.CurrentHP > selectWeightData.HpScopeMaxValue) { return(false); } break; } } //// 判断负面buff //if (selectWeightData.DeBuffWeight > 0) //{ // // 必须有负面buff // result = targetAllData.BuffInfoList.Any(buff => !buff.IsBeneficial); //} //else if (selectWeightData.DeBuffWeight < 0) //{ // // 必须没有负面buff // result = targetAllData.BuffInfoList.All(buff => buff.IsBeneficial); //} //// 判断正面buff //if (selectWeightData.BuffWeight > 0) //{ // // 必须有正面buff // result = targetAllData.BuffInfoList.Any(buff => buff.IsBeneficial); //} //else if (selectWeightData.BuffWeight < 0) //{ // // 必须没有正面buff // result = targetAllData.BuffInfoList.All(buff => !buff.IsBeneficial); //} //// 如果目标隐形并且选择者反隐, 或者不隐形 //if ((targetData.IsHide && selectWeightData.HideWeight < 0)) //{ // result = false; //} return(result); }
/// <summary> /// 计算权重值 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="searchWeightData"></param> /// <param name="searchPositionObject"></param> /// <param name="targetPositionObject"></param> /// <returns></returns> public static float GetWeight <T>(SelectWeightData searchWeightData, T searchPositionObject, T targetPositionObject) where T : IAllDataHolder, IBaseMember, IGraphicsHolder { var sumWeight = 0f; var targetAllData = targetPositionObject.AllData; var targetMemberData = targetAllData.MemberData; var searchMemberData = searchPositionObject.AllData.MemberData; // 从列表中找到几项权重值最高的目标个数个单位 // 将各项值标准化, 然后乘以权重求和, 得到最高值 // -------------------------Level1----------------------------- // 排除不可攻击单位 if (!CouldSelectTarget(searchWeightData, targetAllData)) { return(-1); } // 计算空地属性权重 switch (targetMemberData.GeneralType) { case Utils.GeneralTypeAir: sumWeight += searchWeightData.AirWeight; break; case Utils.GeneralTypeBuilding: sumWeight += searchWeightData.BuildWeight; break; case Utils.GeneralTypeSurface: sumWeight += searchWeightData.SurfaceWeight; break; } // -------------------------Level2----------------------------- // 计算单位类型权重 //switch (targetMemberData.ArmyType) //{ // case Utils.MemberItemTypeHuman: // sumWeight += searchWeightData.HumanWeight; // break; // case Utils.MemberItemTypeOrc: // sumWeight += searchWeightData.OrcWeight; // break; // case Utils.MemberItemTypeOmnic: // sumWeight += searchWeightData.OmnicWeight; // break; //} // -------------------------Level3----------------------------- // 隐形单位 if (targetMemberData.IsHide) { if (searchWeightData.HideWeight <= 0) { return(-1); } sumWeight += searchWeightData.HideWeight; } // 嘲讽单位 if (targetMemberData.IsTaunt) { if (searchWeightData.TauntWeight < 0) { return(-1); } sumWeight += searchWeightData.TauntWeight; } // -------------------------Level4----------------------------- // 小生命权重, 血越少权重越高 if (searchWeightData.HealthMaxWeight > 0) { // 血量 (最大血量 - 当前血量)/最大血量 * 生命权重 sumWeight += searchWeightData.HealthMaxWeight * (targetMemberData.TotalHp - targetMemberData.CurrentHP) / targetMemberData.TotalHp; } // 大生命权重, 生命值越多权重越高 if (searchWeightData.HealthMinWeight > 0) { // 血量 当前血量/最大血量 * 生命权重 sumWeight += searchWeightData.HealthMinWeight * targetMemberData.CurrentHP / targetMemberData.TotalHp; } var distance = Utils.GetTwoPointDistance2D(searchPositionObject.X, searchPositionObject.Y, targetPositionObject.X, targetPositionObject.Y); // 长距离权重, 距离越远权重越大 if (searchWeightData.DistanceMinWeight > 0) { sumWeight += searchWeightData.DistanceMinWeight * (searchMemberData.AttackRange - distance) / searchMemberData.AttackRange; } // 短距离权重, 距离越远权重越小 if (searchWeightData.DistanceMaxWeight > 0) { sumWeight += searchWeightData.DistanceMaxWeight * distance / searchMemberData.AttackRange; } return(sumWeight); }
/// <summary> /// 创建测试单元 /// </summary> /// <param name="count">创建单元个数</param> private void CreateAllMember(int count) { var random = new System.Random(); // 测试 四叉树遇上超大目标 for (var i = 0; i < count; i++) { // TODO 创建数据 var memberData = new VOBase { SpaceSet = 10, MoveSpeed = 10, AttackRange = 20 }; var gameObj = GameObject.CreatePrimitive(PrimitiveType.Cube); var member = gameObj.AddComponent <ClusterData>(); var x = random.Next(0, MapWidth); var y = random.Next(0, MapHeight); memberData.SpaceSet = i % 5 + 1; memberData.CurrentHP = i % 5 + 1; memberData.AttackRange = 100; memberData.TotalHp = 10; memberData.GeneralType = (short)random.Next(1, 4); //member.IsSurface = random.Next(1) > 0; //member.IsAir = !member.IsSurface; //member.IsBuild = random.Next(1) > 0; memberData.ArmyType = (short)random.Next(1, 4); memberData.IsHide = random.Next(1) > 0; member.AllData.MemberData = memberData; // new VOBase() //{ // AttackRange = 20, // SpaceSet = 3, // ObjID = new ObjectID(ObjectID.ObjectType.MySoldier), // MoveSpeed = 60 //}; // TODO 物理信息中一部分来自于数据 member.MaxSpeed = 10; member.RotateSpeed = 10; member.transform.localPosition = new Vector3((i % 3) * 2 + x, 0, i / 3 * 2 + y); member.name = "item" + i; member.Diameter = (i) % 5 + 1; //member.Name = "member" + i; member.X = x; member.Y = y; //member.IsTaunt = random.Next(1) > 0; // 随机给方向 member.Direction = new Vector3(random.Next(1, 100), 0, random.Next(1, 100)); var fightData = member.AllData.SelectWeightData; fightData = new SelectWeightData(); // 选择目标数据 fightData.AirWeight = -1; fightData.BuildWeight = 100; fightData.SurfaceWeight = 100; fightData.HumanWeight = 10; fightData.OrcWeight = 10; fightData.OmnicWeight = 10; //member.TankWeight = 10; //member.LVWeight = 10; //member.CannonWeight = 10; //member.AirCraftWeight = 10; //member.SoldierWeight = 10; fightData.HideWeight = -1; fightData.TauntWeight = 1000; fightData.HealthMaxWeight = 0; fightData.HealthMinWeight = 10; //member.AngleWeight = 10; fightData.DistanceMaxWeight = 0; fightData.DistanceMinWeight = 10; member.AllData.MemberData.Accuracy = 0.9f; member.AllData.MemberData.SpreadRange = 10; //memberData.MultiAimMax = 10; MemberList.Add(member); if (i == 0) { _leader = member; } } }
/// <summary> /// 随机生成地图 /// </summary> /// <param name="x">地图宽度</param> /// <param name="y">地图高度</param> /// <returns>地图数据</returns> //int[][] RandomMap(int x, int y) //{ // var random = new Random(); // var map = new int[y][]; // for (var i = 0; i < y; i++) // { // if (map[i] == null) // { // map[i] = new int[x]; // } // for (var j = 0; j < x; j++) // { // map[i][j] = random.Next(RandomRate) > 1 ? Accessibility : Obstacle; // } // } // return map; //} /// <summary> /// 集群功能 /// 组建集群开始根据路径点移动 /// </summary> /// <param name="pathList">列表</param> /// <param name="map">地图信息</param> private void StartMoving(IList <Node> pathList, int[][] map, int startX, int startY) { if (pathList == null || pathList.Count == 0) { return; } foreach (var item in itemList) { Destroy(item); Destroy(item.gameObject); } itemList.Clear(); // 清除所有组 ClusterManager.Single.ClearAll(); GameObject schoolItem = null; ClusterData school = null; var cloneList = new List <Node>(pathList); var target = Utils.NumToPosition(LoadMap.transform.position, new Vector2(cloneList[cloneList.Count - 1].X, cloneList[cloneList.Count - 1].Y), UnitWidth, MapWidth, MapHeight); var start = Utils.NumToPosition(LoadMap.transform.position, new Vector2(startX, startY), UnitWidth, MapWidth, MapHeight); for (int i = 0; i < ItemCount; i++) { var objId = new ObjectID(ObjectID.ObjectType.MySoldier); schoolItem = GameObject.CreatePrimitive(PrimitiveType.Cube); school = schoolItem.AddComponent <ClusterData>(); school.AllData.MemberData = new VOBase() { AttackRange = 20, ObjID = objId, MoveSpeed = 60, GeneralType = 1, Camp = 1, Attack1 = 10 }; //school.GroupId = 1; // TODO 物理信息中一部分来自于数据 school.MaxSpeed = 10; school.RotateSpeed = 10; school.transform.localPosition = new Vector3((i % 3) * 2 + start.x, start.y, i / 3 * 2 + start.z); school.name = "item" + i; school.TargetPos = target; school.Diameter = (i == 0 ? 10 : 3); school.PushTargetList(Utils.NumToPostionByList(LoadMap.transform.position, cloneList, UnitWidth, MapWidth, MapHeight)); //school.Moveing = (a) => { Debug.Log(a.name + "Moving"); }; //school.Wait = (a) => { Debug.Log(a.name + "Wait"); }; //school.Complete = (a) => { Debug.Log(a.name + "Complete"); }; // 目标选择权重 var fightData = new SelectWeightData(); // 选择目标数据 fightData.AirWeight = 100; fightData.BuildWeight = 100; fightData.SurfaceWeight = 100; fightData.HumanWeight = 10; fightData.OrcWeight = 10; fightData.OmnicWeight = 10; //member.TankWeight = 10; //member.LVWeight = 10; //member.CannonWeight = 10; //member.AirCraftWeight = 10; //member.SoldierWeight = 10; fightData.HideWeight = -1; fightData.TauntWeight = 1000; fightData.HealthMaxWeight = 0; fightData.HealthMinWeight = 10; //member.AngleWeight = 10; fightData.DistanceMaxWeight = 0; fightData.DistanceMinWeight = 10; school.AllData.SelectWeightData = fightData; school.AllData.MemberData.CurrentHP = 99; school.AllData.MemberData.TotalHp = 100; // 创建测试技能 school.AllData.SkillInfoList = new List <SkillInfo>() { }; // 创建测试光环 school.AllData.RemainInfoList = new List <RemainInfo>() { //remain, }; itemList.Add(school); ClusterManager.Single.Add(school); var displayOwner = new DisplayOwner(schoolItem, school); DisplayerManager.Single.AddElement(objId, displayOwner); if (remain != null) { remain.ReleaseMember = displayOwner; } if (IsFSM) { // 加载RanderControl var randerControl = schoolItem.AddComponent <RanderControl>(); displayOwner.RanderControl = randerControl; // 挂载事件处理器 var triggerRunner = schoolItem.AddComponent <TriggerRunner>(); triggerRunner.Display = displayOwner; // TODO 为了适应状态机中的效果 var head = GameObject.CreatePrimitive(PrimitiveType.Cube); head.name = "head"; schoolItem.AddChild(head); } //Action<ClusterGroup> lam = (thisGroup) => //{ // // Debug.Log("GroupComplete:" + thisGroup.Target); // // 数据本地化 // // 数据结束 // if (cloneList.Count == 0) // { // return; // } // cloneList.RemoveAt(cloneList.Count - 1); // if (cloneList.Count == 0) // { // return; // } // //var node = cloneList[cloneList.Count - 1]; // //thisGroup.Target = Utils.NumToPosition(LoadMap.transform.position, new Vector2(node.X, node.Y), UnitWidth, MapWidth, MapHeight); //}; //school.Group.ProportionOfComplete = 1; //school.Group.Complete = lam; } // 设置搜寻单位 scaner = school; GameObject fixItem = null; FixtureData fix = null; // 遍历地图将障碍物加入列表 for (var i = 0; i < map.Length; i++) { var row = map[i]; for (int j = 0; j < row.Length; j++) { switch (row[j]) { case Utils.Obstacle: fixItem = GameObject.CreatePrimitive(PrimitiveType.Cube); fixItem.name += i; fix = fixItem.AddComponent <FixtureData>(); fix.AllData.MemberData = new VOBase() { SpaceSet = 1 }; fix.transform.localScale = new Vector3(UnitWidth, UnitWidth, UnitWidth); fix.transform.position = Utils.NumToPosition(transform.position, new Vector2(j, i), UnitWidth, MapWidth, MapHeight); fix.X = j * UnitWidth - MapWidth * UnitWidth * 0.5f; fix.Y = i * UnitWidth - MapHeight * UnitWidth * 0.5f; fix.Diameter = 1; itemList.Add(fix); ClusterManager.Single.Add(fix); break; } } } //school.Group.Target = Utils.NumToPosition(LoadMap.transform.position, new Vector2(cloneList[cloneList.Count - 1].X, cloneList[cloneList.Count - 1].Y), UnitWidth, MapWidth, MapHeight); //Action<ClusterGroup> lambdaComplete = (thisGroup) => //{ // // Debug.Log("GroupComplete:" + thisGroup.Target); // // 数据本地化 // // 数据结束 // if (cloneList.Count == 0) // { // return; // } // cloneList.RemoveAt(cloneList.Count - 1); // if (cloneList.Count == 0) // { // return; // } // var node = cloneList[cloneList.Count - 1]; // thisGroup.Target = Utils.NumToPosition(LoadMap.transform.position, new Vector2(node.X, node.Y), UnitWidth, MapWidth, MapHeight); //}; //school.Group.ProportionOfComplete = 1; //school.Group.Complete = lambdaComplete; }
/// <summary> /// 创建单位 /// </summary> private void CreateMember() { var objId = new ObjectID(ObjectID.ObjectType.MySoldier); var schoolItem = GameObject.CreatePrimitive(PrimitiveType.Cube); var school = schoolItem.AddComponent <ClusterData>(); school.AllData.MemberData = new VOBase() { AttackRange = 20, SpaceSet = 3, ObjID = objId, MoveSpeed = UnitWidth, CurrentHP = 99, TotalHp = 100, AttackType = 1, Attack1 = 10, ArmyType = 1, GeneralType = 1 }; school.RotateSpeed = 10; // 随机位置 school.transform.localPosition = new Vector3(random.Next(-MapWidth / 2, MapWidth / 2), 0, random.Next(-MapHeight / 2, MapHeight / 2)); // 单位名称 school.name = itemName + memberNum; //school.TargetPos = target; // 单位大小 school.Diameter = UnitWidth; // 挂载状态机运行器 var fsmRunner = schoolItem.AddComponent <TriggerRunner>(); fsmRunner.Display = new DisplayOwner(schoolItem, school); // 目标选择权重数据 var fightData = new SelectWeightData { AirWeight = 100, BuildWeight = 100, SurfaceWeight = 100, HumanWeight = 10, OrcWeight = 10, OmnicWeight = 10, HideWeight = -1, TauntWeight = 1000, HealthMaxWeight = 0, HealthMinWeight = 10, DistanceMaxWeight = 0, DistanceMinWeight = 10 }; school.AllData.SelectWeightData = fightData; // 创建测试技能 school.AllData.SkillInfoList = new List <SkillInfo>(); school.PushTarget(targetPos); // 挂载TriggerRunner var triggerRunner = schoolItem.AddComponent <TriggerRunner>(); triggerRunner.Display = new DisplayOwner(schoolItem, school, schoolItem.AddComponent <RanderControl>()); // 单位放入集群管理器 ClusterManager.Single.Add(school); DisplayerManager.Single.AddElement(objId, triggerRunner.Display); // 单位放入成员列表 memberList.Add(school); // 设置活动目标为最新创建目标 workingObj = school; memberNum++; }