Learn Courses My Dashboard

Concurrent Processing of SKSpriteNode data in SpriteKit

I’m working on my first Swift project. It uses SpriteKit and has quite a few vehicles moving around different tracks. Each vehicle must be aware of other vehicles to avoid collisions and for overtaking etc. The processing for this is very time consuming so I want to run most of the calculations concurrently on a number of background threads.

To do this, I copied the vehicles defined in the arrays track1Vehicles and track2Vehicles (arrays of SKSpriteNodes) to t1Vehicle and t2Vehicle. The idea was to perform all the calculations on these, then afterwards transfer the new positions etc back to the original arrays using SKActions on the main thread. The problem I’m having is that any reference to t1Vehicle and t2Vehicle parameters gives the error “Main actor-isolated property ‘goalSpeed’ can not be mutated from a non-isolated context” (goalSpeed being one of those parameters). Is there a way to allow t1Vehicle and t2Vehicle on a background thread, perhaps by disabling their physicsBodies or similar?

t1Vehicle & t2Vehicle are not intended to themselves alter the display. They are intended only as a means of accessing the data as it was when the ‘findObstacles’ function was called. If there’s another way to reference this data, that would also solve the problem.

The relevant parts of the code are shown below:

//this code is on the main thread
Task {
    let result = await findObstacles()
    let t1Vehicle = result.t1Vehicle
    let t2Vehicle = result.t2Vehicle
}
//Function called from the Task above
func findObstacles() async -> (t1Vehicle: Vehicle, t2Vehicle: Vehicle) {
//Create copy of vehicles for calculating proximity to other vehicles
//Do calculations on another thread
    var t1Vehicle = track1Vehicles.dropFirst()      //Straight Track Vehicles: Ignore element [0]
    t1Vehicle.sort(by: {$0.position.y < $1.position.y}) //Sort into positional order, 000 - 999.999
    var t2Vehicle = track2Vehicles.dropFirst()
    t2Vehicle.sort(by: {$0.position.y < $1.position.y}) //Sort into positional order, 000 - 999.999

//processing of data here..
    
    return (t1Vehicle, t2Vehicle)
}

ps. the ‘Vehicle’ type is an ObservableObject. A number of its parameters were also Published variables. I tried removing the ‘@Published’ from the parameter ‘goalSpeed’ and it made no difference - the error still occurred on it.

I’m getting the impression that nodes can only be accessed from the main thread. With my code I am copying 2 arrays of nodes and use those copies in the background thread/s. The original arrays are not altered. They could even be copied prior to going into the background thread. I need access to things such as position and velocity for each node and there can potentially be 300 of them. A fast & simple way to copy these parameters from all nodes into a normal array would do. Currently my copy still contains nodes even though I don’t display them and only require read access.