0

I'm having a pathfinder class in a SpriteKit game that a I want to use to process every path request in the game. So I have my class stored in my SKScene and I access it from different parts of the game always from the main thread. The pathfinder uses a GKGridGraph of a pretty good size (288 x 224). The class holds an array of requests processed one after another at each update() call from the main scene. Here is the code :

class PathFinder {

    var isLookingForPath = false

    var groundGraph : GKGridGraph<MyNode>?
    var queued : [PathFinderRequest] = []

    var thread: DispatchQoS.QoSClass = .userInitiated

    func generate(minPoint: CGPoint) {
        // generate the groundGraph grid
    }

    func update() {
        // called every frame
        if !self.isLookingForPath {
            findPath()
        }

    }


    func findPath(from start: TuplePosition, to end: TuplePosition, on layer: PathFinderLayer, callBack: PathFinderCallback) {
        // Generating request

        let id = String.randomString(length: 5)
        let request = PathFinderRequest(id: id, start: start, end: end, layer: layer, callback: callBack)

        // Append the request object at the end of the array
        queued.append(request)
    }


    func findPath() {
        self.isLookingForPath = true

        guard let request = queued.first else {
            isLookingForPath = false
            return
        }

        let layer = request.layer
        let callback = request.callback
        let start = request.start
        let end = request.end
        let id = request.id

        var graph = self.groundGraph

        queued.removeFirst()


        let findItem = DispatchWorkItem {
            if let g = graph, let sn = g.node(atGridPosition: start.toVec()), let en = g.node(atGridPosition: end.toVec()) {
                if let path = g.findPath(from: sn, to: en) as? [GKGridGraphNode], path.count > 0 {
                    // Here we have the path found
                    // it worked ! 

                }
            }

            // Once the findPath() method execution is over,
            // we reset the "flag" so we can call it once again from
            // the update() method
            self.isLookingForPath = false

        }

        // Execute the findPath() method in the chosen thread
        // asynchronously
        DispatchQueue.global(qos: thread).async(execute: findItem)

    }

    func drawPath(_ path: [GKGridGraphNode]) {
        // draw the path on the scene
    }

}

Well the code works quite good as it is. If I send random path request within (x+-10, y+-10) length it will return them to each object holding the callback in the request object pretty quickly, but suddenly one request is randomly taking a huge amount of time (approximatively 20s compared to 0.001s) and despite everything I tried I wasn't able to find out what happens. It's never on the same path, never the same caller, never after a certain amount of time... here is a video of the issue : https://www.youtube.com/watch?v=-IYlLOQgJrQ

It sure happens more quickly when there is too much entities requesting but I can't figure why I'm sure it has to deal with the DispacthQueue async calls that I use to prevent the game from freezing.

With delay on every call, the error appear later but is still here :

DispatchQueue.global(qos: thread).asyncAfter(deadline: .now() + 0.1, execute: findItem)

When I look for what is taking so much time to process it is a sub method of the GKGridGraph class : the method makeHeap() is taking 15s to execute !

So I really don't know how to figure this out, I tried everything I could think of but it always happens whatever the delay, the number of entities, the different threads, etc...

Thank you for your precious help !

Onoulade
  • 138
  • 10
  • Wall of text, did not read it, you might benefit from making your question clear and code snippet much smaller :) – Sajjon May 02 '20 at 16:27
  • @Sajjon yeah sorry ^^ . I updated the code to be much much lighter and added comments so it's easier to understand, thank you ! ;) – Onoulade May 03 '20 at 07:24

0 Answers0