applyForce不是光滑的 - applyForce is not smooth

- 此内容更新于:2015-12-13
主题:

希望有人可以帮助你。我已经把我的头发!下面是一些控制台上的代码从我雪碧装备游戏使用英雄的船。我喜欢控制和运动的感受,它有一些漂亮的漂移,等等……但是我对动画/运动产生不一致的结果。有时(大约一半时间)动画完全光滑,看起来是正确的。其余的时间船在不同强度运动动画口吃。游戏中的怪物和皮卡上运行不同的路径。他们的动画不受当问题发生在英雄的船,我通常看到它发生在一个卖60.0fps的调试,这让我觉得这不是一个帧下降问题。我的内存使用是一致的,我看不出任何大的峰值。错误发生时总是从一开始就明显的场景(它从来不会发生在我开始平稳运动?爉蛇行我认为它与最初的力量或多个部队)和继续发生,直到我重启或暂停un-pause游戏水平,此时我得到一个新的行为光滑的动画,动画也有漏洞。我很平,节点优化与地图集和预压,甚至当我关掉在游戏中几乎所有的(除了船和控制垫)我仍然经验与船上applyForce这个问题。我注意到我的经验这经常当插入Xcode,通常当我日志(但不总是),特别是在运行工具。我ControlPad称回到游戏里一个委托以上只是我的类。我可以提供更多的代码和/或日志的东西。只是让我知道。谢谢。编辑/史诗字节的评论,我不应该叫applyForce触摸移动,(在苹果和阅读文档:“加速度是申请一个模拟步骤(一帧)”),我已经更新循环。我现在设置movedByX和movedByY浮动属性在游戏场景触动了,然后使用它们在applyFoce每一步的更新循环。我使用这些设置后为零所以当你释放碰它停止施加的力和船舶漂移。我还体验不一致的平滑。一半的时间它是完美的,另一半动画口吃。我在iPad2和怀疑一个更强大的设备上测试会告诉我什么。我的内存使用率很低。

原文:

Hopefully someone can help. I have been pulling my hair out on this one! Below is some of the control pad code from my Sprite Kit game which uses applyForce to move the hero ship. I like how the controls and movement feel, its got some nice drift, etc... However I have inconsistent results on the animation/movement it produces. Sometimes (about half the time) the animation is perfectly smooth and looks correct. The rest of the time the ship movement animation stutters at different intensities.

The monsters and pickups in the game run on various paths with SKAction. Their animations do not suffer when the issue happens to the hero ship and I typically see it happening with a sold 60.0 fps in the debug, which makes me think it is not a frame drop issues. My memory usage is consistent and I don't see any large spikes.

When the bug happens it is always apparent from the beginning of the scene (it never starts happening after I start with a smooth movement – making me think its something with the initial force or multiple forces at once) and continues to happen until I restart the level or pause and un-pause the game, at which point I get a new behavior of either perfectly smooth animation, or glitchy animation.

My draws and nodes are pretty optimized with atlases and preloading and even when I turn most everything in the game off (everything but the ship and the control pad) I still experience this issue with applyForce on the ship.

I have noticed that I experience this more often when plugged into Xcode, often when I'm logging (but not always), and especially while running instruments.

My ControlPad calls back to the game scene with a delegate

/* Game Scene */

@interface GameScene () <SKPhysicsContactDelegate, ControlPadDelegate>

...

- (void)createHero
{
    self.heroShip = [Hero createHeroInFrame:self.frame];
    [self.gameObject addChild:self.heroShip];
    self.heroShip.position = CGPointMake(self.heroShip.size.width, self.frame.size.height / 2);
}

// Move Hero By X And Y

- (void)moveHeroByX:(float)moveByX andY:(float)moveByY
{
    [self.heroShip.physicsBody applyForce:CGVectorMake(moveByX, moveByY)];
}

/* Control Pad Class */

static float const sensitivity   = 10;
static float const maxMove       = 10;

@interface ControlPad()

// Touch Points
@property (nonatomic) CGPoint navPadTouchPrevious;
@property (nonatomic) CGPoint navPadTouchCurrent;

// Touch Instances
@property (nonatomic) UITouch * navPadTouchInstance;

@implementation ControlPad

- (id)initWithSize:(CGSize)size { ... }

// Touches Began

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    // Loop through touches
    for (UITouch * touch in touches) {

        CGPoint location = [touch locationInNode:self];
        SKNode * node    = [self nodeAtPoint:location];

        // Navigation Pad Touched
        if (node == self.navigationPad) {
            self.navPadTouchInstance    = touch; // Assign Touch Instance
            self.navPadTouchPrevious    = location;
            self.navPadTouchCurrent     = location;
        }
    }
 }

 // Touches Moved

 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
 {
      // Loop Through Touches
      for (UITouch * touch in touches) {

          CGPoint location = [touch locationInNode:self];
          CGPoint previous = [touch previousLocationInNode:self];
          SKNode * node    = [self nodeAtPoint:location];

          // Move Nav Pad
          if (touch == self.navPadTouchInstance) {
              if (node == self.navigationPad) {
                   self.navPadTouchPrevious    = previous;
                   self.navPadTouchCurrent     = location;
                   // Move Hero
                   [self moveHero];
               }
          }
      }
 }

 // Move Hero

 - (void)moveHero
 {
     // Calculate Delta Move
     float moveByX = self.navPadTouchCurrent.x - self.navPadTouchPrevious.x;
     float moveByY = self.navPadTouchCurrent.y - self.navPadTouchPrevious.y;

     // Throttle Move
     moveByX = moveByX >= 0 ? MIN(moveByX, maxMove) : MAX(moveByX, -maxMove);
     moveByY = moveByY >= 0 ? MIN(moveByY, maxMove) : MAX(moveByY, -maxMove);

     // Add Sensitivity
     moveByX = moveByX * sensitivity;
     moveByY = moveByY * sensitivity;

     // Move Hero
     [self.delegate moveHeroByX:moveByX andY:moveByY];
 }

Above are just pieces of my classes. I can provide more code and/or logs of anything. Just let me know. Thanks.

Edit

Per Epic Byte's comment that I should not be calling applyForce in touches moved, (and reading in the Apple Docs: "The acceleration is applied for a single simulation step (one frame)"), I have moved it to the update loop. I'm now setting movedByX and movedByY float properties in the game scene on touches moved and then using them in applyFoce in each step of the update loop. After I use them I'm setting them to zero so when you release the touch it stops applying the force and ship drifts.

I'm still experiencing inconsistent smoothness. Half the time it's perfect, the other half the animation stutters. I'm on an iPad 2 and wonder if testing it on a more powerful device would tell me anything. My memory usage is low.

/* Game Scene */

-(void)update:(NSTimeInterval)currentTime
{
    ...
    [self moveHero];
    ...
}

- (void)moveHero
{
    [self.heroShip.physicsBody applyForce:CGVectorMake(self.moveByX, self.moveByY)];
    self.moveByX = 0;
    self.moveByY = 0;
}

// Called from control pad class

- (void)moveHeroByX:(float)moveByX andY:(float)moveByY
{
    self.moveByX = moveByX;
    self.moveByY = moveByY;
}
网友:尝试删除所有怪物和皮卡(使用SKAction动画)从现场,检查如果问题仍然发生。

(原文:Try to remove all the monsters and pickups (which are using SKAction animations) from the scene and check if the problem is still occurs.)

网友:你有试过applyImpulse呢?的英雄碰撞任何节点,通过行动机会吗?用物理的身体因为移动节点使用正确行动不会导致身体碰撞的行为。

(原文:have you tried applyImpulse instead? Is the hero colliding with any node that moves via actions by chance? Because moving a node with physics body using actions will not result in physically correct collision behavior.)

网友:我建议而不是使用applyImpulse或applyForce,你计算速度自己所以没有惊喜。你也不应该使用applyForce在触动了。ApplyForce游戏循环中应该使用和设置适当的每一步,因为它不断加班工作。

(原文:I suggest instead of using applyImpulse or applyForce, you calculate the velocity yourself so there are no surprises. Also you should not be using applyForce within touches moved. ApplyForce should be used within the game loop and set appropriately at every step because it works continuously overtime.)

楼主:问题仍然出现当怪物和皮卡。它也发生在英雄不是碰撞与移动节点通过行动(因为一切是关闭的)。怪物和皮卡physicsBodies不是动态的,只用于接触测试(不碰撞测试)。我试过applyImpulse但我得到一个不受欢迎的指导效果。由于史诗字节。我用尽了applyForce更新循环,但是到目前为止我得到不理想的成绩。今晚我将计算速度,这样应用。我认为:?

(原文:The problem still occurs when monsters and pickups are off. And it also occurs when the hero is not colliding with nodes that move via actions (because everything else is off). The monster and pickup physicsBodies are not dynamic and are only used for contact test (not collision test). I have tried with applyImpulse but I get an undesired steering effect. Thanks Epic Byte. I have tried applyForce in the update loop but so far I get undesired results. I will try calculating the velocity myself tonight and applying it like this. I assume: self.heroShip.physicsBody.velocity = CGVectorMake()?)

楼主:我还遇到这个问题如果我显式地设置一个速度以及如果我移动applyForce更新循环。

(原文:I am still experiencing this issue if I set a velocity explicitly as well as if I move applyForce to the update loop.)