一、数据定义
(一)、刷怪规则定义:
namespace Common.Data
{public class SpawnRuleDefine{public int ID { get; set; }public int MapID { get; set; }public int SpawnMonID { get; set; }public int SpawnLevel{ get;set; }public SPAWN_TYPE SpawnType { get; set; }public int SpawnPoint { get; set; }public int SpawnPoints { get; set; }public float SpawnPeriod { get; set; }}
}
(二)、DataManger读取EXCEL配置的信息
public class DataManager : Singleton<DataManager>
{public Dictionary<int,Dictionary<int, SpawnPointDefine>> SpawnPoints = null;json = File.ReadAllText(this.DataPath + "SpawnRuleDefine.txt");this.SpawnPoints = JsonConvert.DeserializeObject<Dictionary<int,Dictionary<int, SpawnPointDefine>>>(json);
}
(三)、刷怪点定义
namespace Common.Data
{public class SpawnPointDefine{public int ID { get; set; }//刷怪点IDpublic int MapID { get; set;}public NVector3 Position { get; set; }//位置public NVector3 Direction { get; set; }//朝向}
}
(四)、导出地图中刷怪点的位置信息脚本
[MenuItem("Map Tools/Export SpawnPoints")]public static void ExportSpawnPoints(){DataManager.Instance.Load();Scene current = EditorSceneManager.GetActiveScene();string currentScene = current.name;if (current.isDirty){EditorUtility.DisplayDialog("提示", "请先保存当前场景", "确定");return;}if (DataManager.Instance.SpawnPoints == null)DataManager.Instance.SpawnPoints = new Dictionary<int, Dictionary<int, SpawnPointDefine>>();foreach (var map in DataManager.Instance.Maps){string sceneFile = "Assets/Scenes/" + map.Value.Resource + ".unity";if (!System.IO.File.Exists(sceneFile)){Debug.LogWarningFormat("Scene {0} not existed!", sceneFile);continue;}EditorSceneManager.OpenScene(sceneFile, OpenSceneMode.Single);SpawnPoint[] SpawnPoints = GameObject.FindObjectsOfType<SpawnPoint>();if (DataManager.Instance.SpawnPoints.ContainsKey(map.Value.ID)){DataManager.Instance.SpawnPoints[map.Value.ID] = new Dictionary<int, SpawnPointDefine>();}foreach (var sp in SpawnPoints){if (!DataManager.Instance.SpawnPoints[map.Value.ID].ContainsKey(sp.ID)){DataManager.Instance.SpawnPoints[map.Value.ID][sp.ID] = new SpawnPointDefine();}SpawnPointDefine def = DataManager.Instance.SpawnPoints[map.Value.ID][sp.ID];def.ID = sp.ID;def.MapID = map.Value.ID;def.Position = GameObjectTool.WorldToLogicN(sp.transform.position);def.Direction = GameObjectTool.WorldToLogicN(sp.transform.forward);}}DataManager.Instance.SaveSpawnPoints();EditorSceneManager.OpenScene("Assets/Scenes/" + currentScene + ".unity");EditorUtility.DisplayDialog("提示", "刷怪点导出完成", "确定");}
二、服务器逻辑
需要有刷怪管理器和怪物管理器,并在Map类中对其进行初始化
1、怪物管理器
namespace GameServer.Managers
{class MonsterManager{private Map Map;public Dictionary<int, Monster> Monsters = new Dictionary<int, Monster>();public void Init(Map map){this.Map = map;}internal Monster Create(int spawnMonID,int spawnLevel,NVector3 position,NVector3 direction){Monster monster = new Monster(spawnMonID, spawnLevel, position, direction);EntityManager.Instance.AddEntity(this.Map.ID, monster);monster.Info.Id = monster.entityId;monster.Info.Mapid = this.Map.ID;Monsters[monster.Id] = monster;this.Map.MonsterEnter(monster);//怪物进入场景 通知客户端刷新怪物return monster;}}
}
2.刷怪管理器
刷怪管理器会根据配置来更新不同地图的刷怪任务
namespace GameServer.Managers
{class SpawnManager{private List<Spawner> Rules = new List<Spawner>();private Map Map;public void Init(Map map){this.Map = map;if (DataManager.Instance.SpawnRules.ContainsKey(map.Define.ID)){foreach(var define in DataManager.Instance.SpawnRules[map.Define.ID].Values){this.Rules.Add(new Spawner(define, this.Map));}}}public void Update(){if (Rules.Count == 0) return;for(int i = 0; i < this.Rules.Count; i++){this.Rules[i].Update();}}}
}
3.刷怪器
class Spawner{public SpawnRuleDefine Define { get; set; }private Map Map;//刷新时间private float spawnTime = 0;//消失时间private float unspawnTime = 0;private bool spawned = false;//刷怪点位置信息 根据客户端刷怪点信息脚本获取private SpawnPointDefine spawnPoint = null;public Spawner(SpawnRuleDefine define,Map map){this.Define = define;this.Map = map;if (DataManager.Instance.SpawnPoints.ContainsKey(this.Map.ID)){spawnPoint = DataManager.Instance.SpawnPoints[this.Map.ID][this.Define.SpawnPoint];}else{Log.ErrorFormat("SpawnRule[{0}] SpawnPoint[{1}] not existed", this.Define.ID, this.Define.SpawnPoint);}}public void Update(){if (this.CanSpawn()){this.spawn();}}private void spawn(){this.spawned = true;Log.InfoFormat("Map[{0}] Spawn[{1}:Mon:{2},Lv:{3}] at Point:{4}",this.Define.MapID, this.Define.ID, this.Define.SpawnMonID, this.Define.SpawnLevel, this.spawnPoint);//创建怪物this.Map.MonsterManager.Create(this.Define.SpawnMonID, this.Define.SpawnLevel,this.spawnPoint.Position,this.spawnPoint.Direction);}private bool CanSpawn(){if (this.spawned) return false;//上次消失时间+周期 是否大于当前时间if (this.unspawnTime + this.Define.SpawnPeriod > Time.time) return false;return true;}}
4.修改地图管理器
在CharacterEnter方法中加入怪物信息,并通知客户端
class Map{/// <summary>/// 怪物进入地图/// </summary>/// <param name="character"></param>//广播怪物信息internal void MonsterEnter(Monster monster){Log.InfoFormat("MonsterEnter: Map:{0} monsterId:{1}", this.Define.ID, monster.Id);foreach (var kv in this.MapCharacters){this.AddCharacterEnterMap(kv.Value.connection, monster.Info);}}void AddCharacterEnterMap(NetConnection<NetSession> conn, NCharacterInfo character){if (conn.Session.Response.mapCharacterEnter == null){conn.Session.Response.mapCharacterEnter = new MapCharacterEnterResponse();conn.Session.Response.mapCharacterEnter.mapId = this.Define.ID;}conn.Session.Response.mapCharacterEnter.Characters.Add(character);conn.SendResponse();}//单个角色进入时、也需要添加怪物信息internal void CharacterEnter(NetConnection<NetSession> conn, Character character){//角色进入地图响应conn.Session.Response.mapCharacterEnter = new MapCharacterEnterResponse();conn.Session.Response.mapCharacterEnter.mapId = this.Define.ID;//添加怪物信息foreach (var kv in this.MonsterManager.Monsters){conn.Session.Response.mapCharacterEnter.Characters.Add(kv.Value.Info);}//发送角色进入消息conn.SendResponse();}}