unity地图画格_Unity2D四边形与六边形网格地图寻路[新手]

阅读: 评论:0

unity地图画格_Unity2D四边形与六边形⽹格地图寻路[新⼿]毕业⼏年了, 每天⽤世界上最好的语⾔写crud, 有时也挺⽆聊。最近⼼⾎来潮稍微研究了⼀下Unity, 发现⼗分有趣, 很适合当作码农的⽇常休闲娱乐活动。
想象⼀下,要先做⼀个游戏,当然得先画个地图,有了地图,最先碰到的难题就是:如何寻路。百度⼀下寻路算法,其中著名的A星算法原理就是:把地图划分为⽹格,其中有些格⼦能通⾏(开放),有些格⼦不⾏(关闭)。
起点开始,把附近的开放格⼦加⼊⼀个列表
从列表⾥选择⼀个最接近终点的格⼦,当作新起点
重复2、3步(每个格⼦只能被选中⼀次),直到起点等于终点。
简单概括⼀下,就是从起点开始扩散(像⽔流⼀样),然后问最先到达终点的⽔滴,你经过了哪些格⼦。
有了原理,就差代码了。(我先写了四边形A星寻路,⼜写了六边形A星寻路,发现代码是⼀样的,所以这⾥直接说共通的⽅法)
先定义⼀个astar⽅法, 需要传⼊6个参数:起点、终点、地图、可通⾏区域、距离估算⽅法、获取附近格⼦⽅法;需要返回⼀个结果:从起点到终点经过的格⼦列表足球缝制
static List astar(Vector2Int from, Vector2Int to, Dictionary map, List passableValues,
Func getDistance, Func> getNeighbors)
{
var result = new List();
if (from == to)
{
result.Add(from);
return result;
}
Node finalNode; //⼀个链表节点,⽤来记录最先到达终点的⽔滴 List open = new List(); //建⼀个列表,逐渐储存所有连通的区域 if (findDest(new Node(null, from, getDistance(from, to), 0), open, map, to, out finalNode, passableValues, getDistance, getNeighbors))
{
//到了,逆序链表,把每个格⼦加⼊结果中 while (finalNode != null)
{
result.Add(finalNode.pos);
finalNode = finalNode.preNode;
}
}
result.Reverse();
return result;
}
负离子灯在上⾯的⽅法⾥,调⽤了findDest⽅法,这是⼀个递归⽅法,所做的⼯作就是寻路算法中的2、3步。
static bool findDest(Node currentNode, List openList,
Dictionary map, Vector2Int to, out Node finalNode, List passableValues,
保暖鼠标垫
Func getDistance, Func> getNeighbors)
{
if (currentNode == null) {
//所有和起点连通的格⼦都试过了,⽔流还是⽆法到达终点 finalNode = null;
return false;
}
else if (currentNode.pos == to)
{
//⽔流抵达了终点 finalNode = currentNode;
return true;
}
currentNode.open = false;
openList.Add(currentNode);
//foreach把附近的开放格⼦加⼊列表中(⽔流扩散) foreach (var item in getNeighbors(currentNode.pos)) {
if (map.ContainsKey(item) && passableValues.Contains(map[item]))
{
findTemp(openList, currentNode, item, to, getDistance);
}
}
//递归迭代新起点 var next = openList.FindAll(obj => obj.open).Min();
return findDest(next, openList, map, to, out finalNode, passableValues, getDistance, getNeighbors); }
上⾯两个⽅法已经实现了原理的核⼼部分,接下来要考虑的,是在四边形或六边形寻路中,如何调⽤⽅法astar.先来看四边形寻路的实现⽅法:
public static List find4(Vector2Int from, Vector2Int to, Dictionary map, List passableValues)
{
//距离估算⽅法 Func getDistance = delegate (Vector2Int a, Vector2Int b)
{
float xDistance = Mathf.Abs(a.x - b.x);
float yDistance = Mathf.Abs(a.y - b.y);
return xDistance * xDistance + yDistance * yDistance; //标准情况下,这⾥应该返回平⽅根 };
//获取附近的格⼦,上下左右 Func> getNeighbors = delegate (Vector2Int pos)
{
var neighbors = new List();
neighbors.Add(new Vector2Int(pos.x, pos.y + 1));
neighbors.Add(new Vector2Int(pos.x, pos.y - 1));
neighbors.Add(new Vector2Int(pos.x + 1, pos.y));
neighbors.Add(new Vector2Int(pos.x - 1, pos.y));
return neighbors;
局域表面等离子体共振};
//调⽤寻路算法 return astar(from, to, map, passableValues, getDistance, getNeighbors);
}
六边形寻路和上⾯的⽅法类似:
/
/第⼀个六边形寻路算法 public static List find6X(Vector2Int from, Vector2Int to, Dictionary map, List passableValues) {
//估算距离 Func getDistance = delegate (Vector2Int a, Vector2Int b)
{
float xDistance = Mathf.Abs(a.x - b.x);
float yDistance = Mathf.Abs(a.y - b.y) * Mathf.Sqrt(3);
return xDistance * xDistance + yDistance * yDistance;
};
//获取附近的6个格⼦ Func> getNeighbors = delegate (Vector2Int pos)
{
var neighbors = new List();
neighbors.Add(new Vector2Int(pos.x + 1, pos.y + 1));
neighbors.Add(new Vector2Int(pos.x - 1, pos.y + 1));
neighbors.Add(new Vector2Int(pos.x + 1, pos.y - 1));
neighbors.Add(new Vector2Int(pos.x - 1, pos.y - 1));
neighbors.Add(new Vector2Int(pos.x - 2, pos.y));
neighbors.Add(new Vector2Int(pos.x + 2, pos.y));
return neighbors;
};
//调⽤寻路算法 return astar(from, to, map, passableValues, getDistance, getNeighbors);
}
//第⼆个六边形寻路算法 public static List find6Y(Vector2Int from, Vector2Int to, Dictionary map, List passableValues) {
//估算距离 Func getDistance = delegate (Vector2Int a, Vector2Int b)
{
float xDistance = Mathf.Abs(a.x - b.x) * Mathf.Sqrt(3);
float yDistance = Mathf.Abs(a.y - b.y);
return xDistance * xDistance + yDistance * yDistance;
};
//获取附近的6个格⼦ Func> getNeighbors = delegate (Vector2Int pos)
{
var neighbors = new List();
neighbors.Add(new Vector2Int(pos.x + 1, pos.y + 1));
neighbors.Add(new Vector2Int(pos.x - 1, pos.y + 1));
neighbors.Add(new Vector2Int(pos.x + 1, pos.y - 1));
neighbors.Add(new Vector2Int(pos.x - 1, pos.y - 1));
neighbors.Add(new Vector2Int(pos.x, pos.y - 2));
neighbors.Add(new Vector2Int(pos.x, pos.y + 2));
return neighbors;
};
//调⽤寻路算法 return astar(from, to, map, passableValues, getDistance, getNeighbors);
氢氧化钴>段远程
}
上⾯的六边形寻路有两个⽅法, 是因为我把六边形的地图组合分成了两种情况:
⼀种是这样的,⽹格 按⾏错开形成的六边形⽹格,调⽤⽅法 find6X
另⼀种是,⽹格 按列错开形成的六边形⽹格,调⽤⽅法 find6Y
本⽂的页顶图(来⾃百度)就是按列错开的六边形⽹格,需要调⽤find6Y来寻路。(也考虑通过旋转矩阵,来实现六边形寻路统⼀调⽤,但难度好像超出了我的智商)
具体的实现效果,差不多是这样⼦:
初学Unity,写的不好的地⽅,还希望各位⾼⼿多多赐教。

本文发布于:2023-05-18 16:32:17,感谢您对本站的认可!

本文链接:https://patent.en369.cn/patent/4/104638.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:寻路   六边形   地图   起点   算法
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 369专利查询检索平台 豫ICP备2021025688号-20 网站地图