SpriteKit плохая производительность FPS с очень простой сценой - PullRequest
1 голос
/ 29 марта 2020

Я новичок в SpriteKit и пытаюсь смоделировать популяцию из 1000 движущихся особей, каждый из которых представлен простым кругом. У меня ужасная частота кадров (около 6/7 кадров в секунду), поэтому я уменьшил до 100 и достиг 35 кадров в секунду ...

Мои узлы самые простые в мире, я использую систему компонентов объектов из GameplayKit , но ничего особенного.

Так, что я могу сделать, чтобы улучшить и достигнуть 60 кадров в секунду?

Сначала моя сущность формы, позже в процессе меняются цвет и заполнение для некоторых людей, но здесь есть только простой круговой узел:

class ShapeComponent : GKComponent {
    let node = SKShapeNode(ellipseOf: CGSize(width: 10, height: 10))

    override func didAddToEntity() {
        node.entity = entity
    }

    override func willRemoveFromEntity() {
        node.entity = nil
    }
}

Тогда мой компонент движения, имеющий только скорость и угол. Я даже сохранил синус и косинус для ограничения вычислений:

class MovementComponent : GKComponent {
    var speed : CGFloat = 25
    var direction : CGFloat = .random(in: 0...(2 * .pi)) {
        didSet { updateSinCos() }
    }
    var sinDir : CGFloat = 0
    var cosDir : CGFloat = 0

    override init() {
        super.init()

        updateSinCos()
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    var shapeComponent: ShapeComponent {
        guard let shapeComponent = entity?.component(ofType: ShapeComponent.self)
            else { fatalError("A MovementComponent's entity must have a ShapeComponent") }

        return shapeComponent
    }

    func updateSinCos() {
        sinDir = sin(direction)
        cosDir = cos(direction)
    }

    override func update(deltaTime: TimeInterval) {
        super.update(deltaTime: deltaTime)

        // Declare local versions of computed properties so we don't compute them multiple times.
        let delta = speed * CGFloat(deltaTime)
        let vector = CGVector(dx: delta * sinDir, dy: delta * cosDir)

        let node = shapeComponent.node
        let currentPosition = node.position

        node.position = CGPoint(x: currentPosition.x + vector.dx, y: currentPosition.y + vector.dy)
    }
}

И, наконец, моя сущность с компонентами движения и формы:

class IndividualEntity : GKEntity {

    var shapeComponent: ShapeComponent {
        guard let shapeComponent = component(ofType: ShapeComponent.self)
            else { fatalError("A IndividualEntity must have a ShapeComponent") }

        return shapeComponent
    }

    var movementComponent: MovementComponent {
        guard let movementComponent = component(ofType: MovementComponent.self)
            else { fatalError("A IndividualEntity must have a MovementComponent") }

        return movementComponent
    }

    override init() {
        super.init()

        addComponent(ShapeComponent())
        addComponent(MovementComponent())
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

В моей сцене:

func setUpScene() {
    for _ in 1...100 {
        let position = CGPoint(x: .random(in: 0..<size.width) - 0.5*size.width, y: .random(in: 0..<size.height) - 0.5*size.height)
        addIndividual(at: position)
    }
}

var componentSystem = GKComponentSystem(componentClass: MovementComponent.self)
var individuals = [IndividualEntity]()

func addIndividual(at pos: CGPoint) {
    let individual = IndividualEntity()
    individual.shapeComponent.node.position = pos
    addChild(individual.shapeComponent.node)
    componentSystem.addComponent(foundIn: individual)

    individuals.append(individual)
}

var lastUpdateTimeInterval: TimeInterval = 0
let maximumUpdateDeltaTime: TimeInterval = 1.0 / 60.0

override func update(_ currentTime: TimeInterval) {
    guard view != nil else { return }

    var deltaTime = currentTime - lastUpdateTimeInterval        
    deltaTime = deltaTime > maximumUpdateDeltaTime ? maximumUpdateDeltaTime : deltaTime

    lastUpdateTimeInterval = currentTime

    componentSystem.update(deltaTime: deltaTime)
}

Так что, если кто-то может помочь мне с этой проблемой ... Я просто хочу, чтобы эти круги блуждали, а потом реагировали на столкновения, меняя направление и цвет.

Заранее спасибо.

...