GKObstacleGraph How to Find Closest Valid point?

本秂侑毒 提交于 2019-12-12 01:38:34

问题


In a scenario where user wants to navigate via mouse or touch to some are of the map that is not passable. When sending the point to GKObstacleGRpah FindPath it just returns an empty array.

I want the unit to go to closest (or close enough) passable point.

What would be an appropriate way to find a closest valid point in GKObstacleGraph.


I understand that I can get the GKObstacle so I can enumerate it's vertices, and I know my unit's position...

But well... what is the next step ?

NOTE: I am not using GKAgengts.


回答1:


Here was my thinking as I worked through this problem. There may be an easier answer, but I haven’t found it.

1. Figure out if a point is valid or not.

To do this, I actually have a CGPath representation of each obstacle. I export paths from PhysicsEditor and then load them in through a custom script that converts them to CGPath. I always store that CGPath along with the GKObstacle I created from the path. Finally, I can call CGPathContainsPoint to determine the the obstacle contains the point. If true, I know the point is invalid.

2. Once the point is invalid, find out which obstacle was clicked.

With my approach in #1, I already have a handle on the CGPath and obstacle it belongs to.

3. Find closest vertex

Now that I know the obstacle, find the vertex closest to the unit that is moving. I wouldn’t find the closet vertex to the point clicked because that could be around a corner. Instead, figure out the vector between the desired position and the unit. Then, draw an invisible line from the desired position through the vertex. I used this equation to find out where the lines would cross.

   // http://stackoverflow.com/questions/1811549/perpendicular-on-a-line-from-a-given-point
    let k = ((end.y - start.y) * (hitPoint.x - start.x) - (end.x - start.x) * (hitPoint.y - start.y)) / ((end.y - start.y) * (end.y - start.y) + (end.x - start.x) * (end.x - start.x))
    let x4 = hitPoint.x - k * (end.y - start.y)
    let y4 = hitPoint.y + k * (end.x - start.x)
    let ret = float2(x: x4, y: y4)

4. Offset intersection by unit size towards moving unit

Knowing where the paths intersect along with the vector towards the unit, we can just move to intersection point + (the vector * unit size).

5. Edge cases

This gets tricky when you have two obstacles touching each other, or if you have very large obstacles. The user may think they are moving to the far side of the map, but this script will follow back to the closet valid point which could be nearby. Because of that, I scrapped all of the code and I just don’t allow you to move to invalid positions. A red X and a buzz sound happens prompting the user to select a new, valid position on the map.

6. DemoBots

I could be wrong, but I vaguely recall DemoBots from Apple having similar logic — they may be a good reference too.

7. Debug Layer

This took forever for me to get a proof of concept together. I’d highly recommend drawing lines on a debug layer to verify your logic.



来源:https://stackoverflow.com/questions/39546759/gkobstaclegraph-how-to-find-closest-valid-point

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!