游戏开发的过程中,我们经常需要让某些物体按照固定的路线来移动,这时候就需要提供给策划同学们一个路径编辑器来让他们充分发挥"想象力"。。。

先来看下最终效果:

下面来简单说下实现过程

制作路径点

首先制作路径点,每一个路径点要记录自己都连接到哪些点,我们用一个数组来记录,所以路径点的脚本应该是这样:

public class MapWayPoint : MonoBehaviour {public List<GameObject> pointList;
}

然后制作预制体,随便创建一个空物体,或者任何你喜欢的物体,将这个脚本赋给这个物体,然后保存成为预制体即可。

绘制路径

接下来就是在这些路径点之间绘制出连接的带箭头的线:

创建一个脚本用来专门绘制这些线:MapDraw

这个脚本要引入命名空间:

#if UNITY_EDITOR
using UnityEditor;
#endif

这里要判断一下平台,因为在其它平台上是没有这个命名空间的

我们把绘制逻辑放在MonoBehaviour的OnDrawGizmos中:

 public void OnDrawGizmos(){#if UNITY_EDITORGizmos.color = Color.blue;Handles.color = Color.blue;//获取场景中全部道具Object[] objects = Object.FindObjectsOfType(typeof(GameObject));Dictionary<string, List<string>> post = new Dictionary<string, List<string>>();foreach (GameObject sceneObject in objects){if(sceneObject.name == "WayPoint"){foreach (Transform child in sceneObject.transform){MapWayPoint editor = child.GetComponent<MapWayPoint>();if(editor != null){for(int i = 0 ; i < editor.pointList.Count ; i ++){if(editor.pointList[i] == null){continue;}editor.transform.LookAt(editor.pointList[i].transform);DrawLine(editor.transform,editor.pointList[i].transform,Vector3.Distance(editor.transform.position,editor.pointList[i].transform.position));}}}}}#endif}

这里主要就是在场景中找到WayPoint对象,因为我们规定所有的路径点都要放到这个对象里边,所以我们遍历这个对象的所有子物体就找到了全部的路径点。然后遍历每个路径点所连接的所有目标点并调用绘制方法。

绘制方法:

 public void DrawLine(Transform t,Transform t2,float dis){#if UNITY_EDITORHandles.ArrowCap(0, t.position + (dis-Mathf.Min(1,dis)) * t.forward, t.rotation, Mathf.Min(1,dis));Gizmos.DrawLine(t.position,t2.position);#endif}

这里调用了2个系统的绘制方法,第一个是绘制箭头,第二个是绘制线,绘制箭头时处理了一下,保证箭头只有1个长度,否则箭头太大了特别丑。 绘制部分就这些内容,接下来看下数据的存储和读取

存储和读取路径数据

存储和读取放在MEMapWayPoint脚本中

首先保存数据:

[MenuItem("关卡编辑器/保存路径")]public static void SaveLevel(){//获取场景中全部道具Object[] objects = Object.FindObjectsOfType(typeof(GameObject));Dictionary<string, List<string>> post = new Dictionary<string, List<string>>();foreach (GameObject sceneObject in objects){if(sceneObject.name == "WayPoint"){foreach (Transform child in sceneObject.transform){MapWayPoint editor = child.GetComponent<MapWayPoint>();if(editor != null){if(editor.pointList.Count <= 0) Debug.LogError("The point child is null : " + child.transform.position );List<string > childlist = new List<string>();for(int i = 0 ; i < editor.pointList.Count ; i ++){if(editor.pointList[i] == null){continue;}childlist.Add(GetPosString(editor.pointList[i].transform.position));}post.Add(GetPosString(editor.transform.position),childlist);}}}}//保存文件string filePath = GetDataFilePath(mapname + ".text");byte[] byteArray = System.Text.Encoding.Default.GetBytes ( JsonMapper.ToJson(post) );WriteByteToFile(byteArray,filePath );Debug.Log(JsonMapper.ToJson(post));}

这里和绘制的时候差不多,遍历WayPoint下的所有路径点,这里所有路径点的信息都是以字符串的形式保存的,并且只保存坐标信息。坐标信息使用Dictionary记录,key为当前点坐标,value为路径列表,最用把 Dictionary转为json字符串进行存储。

下面是读取数据:

 [MenuItem("关卡编辑器/读取路径")]public static void LoadLevel(){List<GameObject> delarr = new List<GameObject>();GameObject WayPoint = null;foreach (GameObject sceneObject in Object.FindObjectsOfType(typeof(GameObject))){if( sceneObject.name == "WayPoint"){WayPoint = sceneObject;break;}}if(WayPoint == null){GameObject tGO = new GameObject("WayPoint");  tGO.AddComponent<MapDraw>();  WayPoint = tGO;}//读取文件byte[] pointData = ReadByteToFile(GetDataFilePath(mapname+".text"));if(pointData == null){return;}foreach (Transform child in WayPoint.transform){delarr.Add(child.gameObject);}//删除旧物体foreach(GameObject obj in delarr){DestroyImmediate(obj);}string str = System.Text.Encoding.Default.GetString ( pointData );Debug.Log(str);Dictionary<string, List<string>> post = JsonMapper.ToObject<Dictionary<string, List<string>>>(str);Dictionary<string,MapWayPoint> temp = new Dictionary<string,MapWayPoint>();foreach (KeyValuePair<string, List<string>> pair in post)  {  List<string> list = pair.Value;MapWayPoint obj = GetObj(WayPoint,temp,pair.Key);for(int i = 0 ; i < list.Count ; i ++){Debug.Log("add");MapWayPoint child = GetObj(WayPoint,temp,list[i]);obj.pointList.Add(child.gameObject);}}  //        Debug.Log(JsonMapper.ToJson(post["0"][0]));}

这里需要判断一下场景中是否存在WayPoint物理,不存在则创建一个,并挂上MapDraw脚本。数据直接用JsonMapper转会对象,然后在场景中生成物体就行了。

这里使用json字符串来进行数据存储并不是最好的方案,因为我做这个的时候,服务器端也需要使用到这个数据,所以才采用json,如果像我前篇给出的地图编辑器一样用二进制数据保存,服务器还要实现一套解析程序,太费事了。

下面给出MEMapWayPoint的完整代码:

public class MEMapWayPoint : Editor {public static string mapname = "mapway";[MenuItem("关卡编辑器/保存路径")]public static void SaveLevel(){// 场景路径/*string scenePath = AssetDatabase.GetAssetPath(selectObject);Debug.Log("=====================================");Debug.Log(sceneName + "   path : " + scenePath );// 打开这个关卡EditorApplication.OpenScene(scenePath);*///获取场景中全部道具Object[] objects = Object.FindObjectsOfType(typeof(GameObject));Dictionary<string, List<string>> post = new Dictionary<string, List<string>>();foreach (GameObject sceneObject in objects){if(sceneObject.name == "WayPoint"){foreach (Transform child in sceneObject.transform){MapWayPoint editor = child.GetComponent<MapWayPoint>();if(editor != null){if(editor.pointList.Count <= 0) Debug.LogError("The point child is null : " + child.transform.position );List<string > childlist = new List<string>();for(int i = 0 ; i < editor.pointList.Count ; i ++){if(editor.pointList[i] == null){continue;}childlist.Add(GetPosString(editor.pointList[i].transform.position));}post.Add(GetPosString(editor.transform.position),childlist);}}}}//保存文件string filePath = GetDataFilePath(mapname + ".text");byte[] byteArray = System.Text.Encoding.Default.GetBytes ( JsonMapper.ToJson(post) );WriteByteToFile(byteArray,filePath );Debug.Log(JsonMapper.ToJson(post));}public static void Save(string name){mapname = name;SaveLevel();}//================================读取================================[MenuItem("关卡编辑器/读取路径")]public static void LoadLevel(){List<GameObject> delarr = new List<GameObject>();GameObject WayPoint = null;foreach (GameObject sceneObject in Object.FindObjectsOfType(typeof(GameObject))){if( sceneObject.name == "WayPoint"){WayPoint = sceneObject;break;}}if(WayPoint == null){GameObject tGO = new GameObject("WayPoint");  tGO.AddComponent<MapDraw>();  WayPoint = tGO;}//读取文件byte[] pointData = ReadByteToFile(GetDataFilePath(mapname+".text"));if(pointData == null){return;}foreach (Transform child in WayPoint.transform){delarr.Add(child.gameObject);}//删除旧物体foreach(GameObject obj in delarr){DestroyImmediate(obj);}string str = System.Text.Encoding.Default.GetString ( pointData );Debug.Log(str);Dictionary<string, List<string>> post = JsonMapper.ToObject<Dictionary<string, List<string>>>(str);Dictionary<string,MapWayPoint> temp = new Dictionary<string,MapWayPoint>();foreach (KeyValuePair<string, List<string>> pair in post)  {  List<string> list = pair.Value;MapWayPoint obj = GetObj(WayPoint,temp,pair.Key);for(int i = 0 ; i < list.Count ; i ++){Debug.Log("add");MapWayPoint child = GetObj(WayPoint,temp,list[i]);obj.pointList.Add(child.gameObject);}}  //     Debug.Log(JsonMapper.ToJson(post["0"][0]));}public static void Load(string name){mapname = name;LoadLevel();}public static string GetPosString(Vector3 pos){return pos.x + "," + pos.y + "," + pos.z;}public static Vector3 GetPosByString(string pos){Vector3 ret = Vector3.zero;try{string[] s = pos.Split(',');ret.x = float.Parse(s[0]);ret.y = float.Parse(s[1]);ret.z = float.Parse(s[2]);}catch(System.Exception e){Debug.Log(e.Message);}return ret;}//加载路径点时,获取存档中的路径点,没有则创建public static MapWayPoint GetObj(GameObject parent, Dictionary<string,MapWayPoint> temp,string name){MapWayPoint obj;if(temp.ContainsKey(name)){obj = temp[name];}else{GameObject tempObj = Resources.Load("Prefabs/WayPoingUnit") as GameObject;tempObj = (GameObject)Instantiate(tempObj);tempObj.transform.parent = parent.transform;tempObj.transform.position = GetPosByString(name);obj = tempObj.GetComponent<MapWayPoint>();temp.Add(name,obj);}return obj;}/// <summary>/// 读取文件二进制数据 Reads the byte to file./// </summary>/// <returns>The byte to file.</returns>/// <param name="path">Path.</param>public static byte[] ReadByteToFile(string path){//如果文件不存在,就提示错误if (!File.Exists(path)){Debug.Log("读取失败!不存在此文件");return null;}FileStream fs = new FileStream(path, FileMode.Open);BinaryReader br = new BinaryReader(fs);byte[] data = br.ReadBytes((int)br.BaseStream.Length);fs.Close();fs.Dispose();br.Close();return data;}/// <summary>/// 二进制数据写入文件 Writes the byte to file./// </summary>/// <param name="data">Data.</param>/// <param name="tablename">path.</param>public static void WriteByteToFile(byte[] data, string path){FileStream fs = new FileStream(path, FileMode.Create);fs.Write(data, 0, data.Length);fs.Close();}public static string GetDataFilePath(string filename){return Application.dataPath + "/Resources/MapWayData/" + filename;}
}

unity地图路径编辑器相关推荐

  1. 视觉导航路径编辑器使用教程

    http://community.bwbot.org/topic/57/%E8%A7%86%E8%A7%89%E5%AF%BC%E8%88%AA%E8%B7%AF%E5%BE%84%E7%BC%96% ...

  2. Unity物体路径查询工具

    Unity物体路径查询工具 文章目录 Unity物体路径查询工具 前言 一.工具使用介绍 Editor 二.代码 1.复制代码 2.将代码放入Editor文件夹 三.使用 四.总结 五.结束语 前言 ...

  3. Unity引擎及编辑器C#源代码发布

    3月23日我们在GitHub上发布了Unity引擎和编辑器的C#源代码,仅供Unity学习参考使用. 为何如此决定 为了了解或改进自己的Unity项目,一直以来有用户对Unity .NET程序集反汇编 ...

  4. unity中脚本编辑器UnIDE

    引言 unity默认脚本编辑器是MonoDevelop,随着unity4.3面世,MonoDevelop (4.0.1)版本也随之而来,更新为界面更改和bug自动修复功能等,具体还未使用. 点击uni ...

  5. 直播笔记 | Unity中路径的疑难杂症剖析

    本文首发于洪流学堂微信公众号. 洪流学堂,学Unity快人几步 你好,我是郑洪智,你的技术探路者. 昨天我们直播剖析了Unity中路径的疑难杂症,以下是直播内容精华部分笔记. 完整录播:https:/ ...

  6. 关于调用高德地图路径规划清除问题解决方案【js】

    关于调用高德地图路径规划清除问题解决方案[js] 参考文章: (1)关于调用高德地图路径规划清除问题解决方案[js] (2)https://www.cnblogs.com/qk523/articles ...

  7. 3.蚁群算法求解格栅地图路径规划matlab代码

    往期: 1.Dijkstra算法求解格栅地图路径matlab代码_墨叔叔的博客-CSDN博客 2.A*搜索算法原理及matlab代码_墨叔叔的博客-CSDN博客 一.蚁群算法原理 原理:蚁群系统(An ...

  8. Unity存储路径具体位置整理(Win+Android+ios)

    Unity存储路径具体位置整理 一:Application.dataPath: 这个路径在Unity打包工程目录下.通过这个路径可以访问项目中任何文件夹中的资源, 只能在PC端使用. 二:persis ...

  9. 百度地图主题编辑器使用教程

    目录 使用流程 1. 打开官网 2. 添加样式规则(默认有一条样式规则) 3. 选择元素 4. 选择属性 5. 勾选要修改的样式,并设置为目标值 6.  获取样式的JSON数据 使用流程 1. 打开官 ...

  10. unity 判断路径是否存在或者文件夹是否存在

    目录 一.目的 1.想知道:unity 判断路径是否存在或者文件夹是否存在 1.想实现的功能:某路径下,检查是否有名字为"1"-"20"名字的文件夹. 二.参考 ...

最新文章

  1. 用户态线程在AI中的应用
  2. 类的构造函数和析构函数详解
  3. 【MySQL】MySQL开发注意事项与SQL性能优化步骤
  4. 云时代的智能运维平台,助力企业创新迭代
  5. 聊聊如何构建一支自驱团队(二)
  6. first review of team blog(4.26)
  7. 作为一个死忠粉,我的 IntelliJ IDEA 一直都是这样来设置的,效果很棒!
  8. 安卓下设置系统字体大小影响H5页面布局
  9. stm32移植paho_如何在STM32上移植Linux?超详细的实操经验分享
  10. 三层路由详解、为什么要划分vlan,vlan的作用是什么?
  11. uva10246- Asterix and Obelix
  12. 高德导航过程中实时获取道路信息
  13. NLP-文本处理:词形归一(Lemma)【英文】【把各种类型的词的变形都归为一个形式】【went->go;are->be】
  14. 一文快速了解EL表达式基础知识
  15. 人工智能产业盛宴:2019 AIIA开发者大会即将揭幕
  16. JAVA并发编程(一)上下文切换
  17. 把你的Windows Media Player 打造成全能的播放器
  18. 实训计算机硬盘分区的心得体会,计算机实训报告
  19. 瑞幸咖啡完成债务重组:陆正耀出局 股东大钲资本成实控方
  20. 2021-05-12轮训算法

热门文章

  1. 人脸对齐:Wing Loss人脸关键点检测算法2018
  2. pdf根据目录生成书签
  3. 计算机网络自顶向下 概念填空整理(完整)
  4. 并查集-A Bug's Life(poj2492)
  5. 邮政挂号信和包裹查询网站(非EMS)
  6. 微博商城开启社会化电商之路
  7. Arduino - Debugging on the Arduino IDE 2.0
  8. 如何在WIN10系统中设置护眼颜色绿豆沙?
  9. IdentityServer4(七):Consent授权页支持
  10. 第二章:硬件访问服务(4)-HAL编写