Трептене с постоянна скорост в SpriteKit

Прилагам постоянна скорост към един от моите възли като този във функцията за актуализиране:

// Set a constant velocity to the right:
node.physicsBody?.velocity.dx = 300

Когато отпечатам скоростта във функцията didSimulatePhysics, тя отпечатва около 290. Добре, губя малко скорост от linearDamping, има смисъл. Но не остава постоянно.

На всеки 10-15 секунди ще има необяснимо трептене на скоростта (от разпечатката на didSimulatePhysics). За 6 или 7 кадъра скоростта ще варира от 285-295. По-бавно, после по-бързо. Така че ще получа 287, след това 294, след това 286, след това 294. Никога две бавни или две бързи подред.

Това е главният ми герой, проследен от моята камера и малката промяна в скоростта кара камерата да изглежда трептене, когато това се случи.

Далеч съм от всякакви сблъсъци, но имайте предвид, че пренебрегвам сблъсъци на този възел и имам реституция, зададена на 0:

node.physicsBody?.collisionBitMask = 0
node.physicsBody?.restitution = 0

Симулацията на физиката изостава ли и след това се опитва ли да компенсира това на следващия кадър (FPS е фиксиран на 60)? Или евентуално се натъквате на проблеми със закръгляването?

Има ли начин да се получи точно постоянна скорост в една посока на всеки кадър?

Добавяне на пример за действителната промяна в node.position.x на кадър при движение направо във въздуха без сблъсък, задаване на velocity.dx от 300 при всяка актуализация:

3.82861328125 // this is the norm - thousands of these before this blip)
3.82861328125
3.82861328125
5.740478515625 // blip begins
1.9150390625
3.82861328125
5.740478515625
1.9150390625
5.740478515625
1.9150390625
5.740478515625
1.9150390625
5.740478515625
3.82861328125 // blip ends
3.82861328125
3.82861328125

person Stephen    schedule 16.06.2015    source източник
comment
Що се отнася до трептенето на камерата, повечето игри ще изгладят камерата, така че камерата да се премести в позиция с течение на времето, вместо мигновено, така че сценарии като този, който описахте, да изглеждат течни. Сега по отношение на вашия действителен проблем, ако задавате скоростта в метода за актуализиране (т.е. непрекъснато), скоростта трябва да остане постоянна. Комплектът за спрайтове обаче прилага променлива времева стъпка, така че може да се появи трептене в позицията, когато скоростта на кадрите спадне. Работите ли на симулатора или устройството. И сигурен ли си, че няма външни сили като гравитация, триене?   -  person Epic Byte    schedule 16.06.2015
comment
Добри мисли - всъщност се пристрастявам към новата позиция, но промяната все още е (едва) осезаема, защото камерата иначе е толкова стабилна. Това е на устройство iPhone 6. Измервателят на FPS остава фиксиран на 60 с процесор около 5%, но със сигурност изглежда като малко забавяне. Определено няма триене. Гравитацията е включена (гравитацията е причината, поради която използвам физичен възел), но ще повлияе ли на хоризонталната скорост? И само веднъж на 10-15 секунди, но само няколко кадъра. Може би ARC почиства нещо и причинява много малко забавяне на честотата на кадрите? Инструментите не показват пикове на процесора. Благодаря за отговора.   -  person Stephen    schedule 16.06.2015
comment
Много странно. Ако искате да коригирате този проблем малко по-нататък, можете да започнете, като видите дали това наистина е честотата на кадрите, като следите вашето собствено делта време, което комплектът за спрайтове ви дава във функцията за актуализиране. Това е така, защото не можете винаги да следвате това, което SKView FPS ви показва, защото това е просто средна стойност. Ако изчислите собственото си делта време, можете да видите какво се случва по време на нервния момент. Ако делта времето показва постоянно 1/60, тогава знаете, че нервното движение трябва да е причинено от нещо друго. Може също да е полезно да възпроизведете този проблем в примерен проект.   -  person Epic Byte    schedule 16.06.2015
comment
Може също така да опитате да стартирате проекта си в режим на освобождаване, така че да се премахнат голяма част от отстраняването на грешки. И накрая (и това може да звучи странно), може да искате да опитате да изтриете приложението и да почистите папката си за компилация. Много рядко по време на моята игра със спрайт комплект изграждането щеше да бъде много бавно и това винаги коригираше проблема. Отново това може да е напълно отделен проблем от този, с който се сблъсквате, просто се опитвам да ви дам възможно най-много информация.   -  person Epic Byte    schedule 16.06.2015
comment
Интересно (5.740478515625 + 1.9150390625)/2 = 3.8277... Изглежда, че е прекалено със снимането, след което коригира следващия кадър. Подозирам, че ако регистрирате времето на кадър, ще видите скок и там. 60 кадъра в секунда е средно и тъй като това са само няколко кадъра в голямата схема на нещата, вероятно няма да видите спад в кадъра в секунда или по-скоро няма да го отчете. Не съм сигурен защо това се случва на всеки 10 до 15 минути. Предполагам, че 10 -15 е приблизителна оценка. Всъщност бих го замерил, за да видя дали има някакви постоянства с времето, необходимо за прескачане.   -  person Skyler Lauren    schedule 16.06.2015


Отговори (1)


Проблемът с физиката на SpriteKit е, че използва променлива времева стъпка, която не работи добре, особено при постоянно движение. Това означава, че SpriteKit актуализира вашата физика във всеки кадър с deltaTime, преминал от последния кадър. Това време никога не е абсолютно същото, дори ако поддържате постоянни 60 FPS. За да разрешите този проблем, може да е добра идея да използвате постоянна времева стъпка за симулация на физиката. За съжаление в SpriteKit няма начин да се контролира времевата стъпка за физична симулация и тя винаги е обвързана с кадровата честота. Ако бихте използвали двигател, който позволява ръчно актуализиране на физиката, можете да приложите постоянна времева стъпка за физична симулация, например по следния начин:

-(void)update:(double)dt
{
  double fixedDt = 1.0/60.0; // or you can put for example 1.0/300.0 to have more physics updates per frame

  self.difference += MIN(dt, 0.1); // prevent too big dt changes

  while (self.difference > fixedDt)
  {
      [self updatePhysics:fixedDt];
      self.difference -= fixedDt;
  }
}

За съжаление в SpriteKit не можете да контролирате това и това е причината, поради която винаги ще виждате някои малки трептения дори при 60 FPS при постоянно движение. Имате няколко решения:

  • игнорирайте това и просто живейте с него
  • опитайте да използвате различен физически двигател, например Chipmunk или Box2D
  • изобщо не използвайте никакъв физически двигател

Можете също така да намерите повече информация относно променлива/постоянна времева стъпка за физика тук: https://gamedev.stackexchange.com/questions/1589/when-should-i-use-a-fixed-or-variable-time-step

person Leszek Szary    schedule 06.08.2019