首次加载时动画滞后

Posted

技术标签:

【中文标题】首次加载时动画滞后【英文标题】:Animations lag when first loaded 【发布时间】:2015-01-20 22:44:11 【问题描述】:

我使用 Sprite Kit 开发了一款 ios 游戏,其中有很多敌人和障碍物,我制作了动画。每次第一次加载动画帧时,游戏都会滞后一点,然后运行良好。

例如我的一个敌人是这样的:

Fox 实现文件:

- (id)initWithTexture:(SKTexture *)nodetexture

    self = [super initWithTexture:nodetexture];
    if (self) 
        //Initialization code
        [self setScale:0.2];
        [self setSpeed:20];
        self.physicsBody.allowsRotation = false;
        self.physicsBody.contactTestBitMask = 0x1 << 1 | 0x1 << 3;
        self.physicsBody.categoryBitMask = 0x1 << 2;//enemy
        self.physicsBody.collisionBitMask = 0x1 << 1 | 0x1 << 3;
        [self animateSelf];
    
    return self;


- (void) animateSelf
    [super animateSelf];
    NSMutableArray *textures = [NSMutableArray arrayWithCapacity:16];
    for (int i = 1; i < 5; i++) 
        NSString *textureName = [NSString stringWithFormat:@"fox%d.png", i];
        SKTexture *texture =[SKTexture textureWithImageNamed:textureName];
        [textures addObject:texture];
    
    [self removeActionForKey:[NSString stringWithFormat:@"animate %@", self.class]];
    [self runAction:[SKAction sequence:@[[SKAction repeatAction:[SKAction sequence:@[[SKAction runBlock:^
        self.xScale = -0.2;
        [self jumpEntity];
        [self setSpeed:40];
        [self impulseEntityRight];
        [self setSpeed:20];
        self.runAnimation = [SKAction animateWithTextures:textures timePerFrame:3];
    ], [SKAction waitForDuration:20], [SKAction runBlock:^
        self.xScale = 0.2;
        [self jumpEntity];
        [self setSpeed:40];
        [self impulseEntityLeft];
        [self setSpeed:20];
        [self runAction:[SKAction repeatActionForever:self.runAnimation]];
    ], [SKAction waitForDuration:20]]] count:5]]] withKey:[NSString stringWithFormat:@"animate %@", self.class]];

帧存储在 .atlas 文件中,我认为延迟的原因是第一次运行 for 循环,但这只是一个假设。

我尝试按照这些思路在 GameViewController 中预加载帧:

GameViewController 实现文件:

- (void)viewDidLoad

    [super viewDidLoad];
    //Load new game
    [self initialiseGameScene];
    [self.gamescene.physicsWorld setContactDelegate:self];
    [self checkTiltBool];
    self.gamestarted = false;
    self.startedbytilt = false;
    [self addListenersToButtons];
    [self instantiateGestureRecognizers];
    self.spawnedobjects = [[NSMutableArray alloc] init];
    if (self.tiltbool == true)
        [self startGame];
    
    [self updateLifeIcons];
    NSMutableArray *frames = [[NSMutableArray alloc]init];
    for (int i=0; i<[SKTextureAtlas atlasNamed:@"fox"].textureNames.count; i++) 
        [frames addObject:[SKTexture textureWithImageNamed:[SKTextureAtlas atlasNamed:@"fox"].textureNames[i]]];
    
    [SKTexture preloadTextures:frames withCompletionHandler:^NSLog(@"Complete");];


我走对了吗?理想情况下,我想在游戏开始之前预加载所有动画,以便动画顺利运行。

【问题讨论】:

您正在预加载。你只需要让你的代码以预加载完成的方式流动,然后你的游戏才开始。例如,使用 BOOL 变量让您的 NSLog “完成”在加载完成时通知您。您可以在更新方法中测试 BOOL 变量,以了解何时开始运行您的游戏。 您不应该在每次运行动画时都创建新的纹理数组。而是为您拥有的每个动画存储一个纹理数组并重复使用每个纹理数组。 纹理预加载代码相当浪费。每次在循环中,您都会让狐狸图集从中获取所有纹理名称两次,一次在 for 循环中,一次在循环内。 那么我可以在 GameViewController 中加载帧,然后在我的 Fox 类中使用预加载的帧吗? 我会将其设为共享类变量,并在加载场景数据时加载动画。您绝对应该有一种加载/准备场景的方法。我个人会将数据加载到您的场景类中,但这完全取决于您。 GameViewController 也可以工作。 【参考方案1】:

我强烈建议您只初始化一次纹理数组。目前,每次调用 animateSelf 方法时都会创建一个新的 NSMutableArray。

所以参加这个部分:

  NSMutableArray *textures = [NSMutableArray arrayWithCapacity:16];
    for (int i = 1; i < 5; i++) 
        NSString *textureName = [NSString stringWithFormat:@"fox%d.png", i];
        SKTexture *texture =[SKTexture textureWithImageNamed:textureName];
        [textures addObject:texture];
    

并将其放入一个方法中,该方法将在应用程序启动时调用。例如,您可以创建一个可以从代码中访问的全局变量。

如果您使用它,还有一个问题可能是 iOS 模拟器。我经常遇到的问题是我在 iOS 模拟器上运行游戏,它很迟钝并且表现不佳(大约 23FPS)。但在真实设备上,它以 60FPS 运行得很好。所以如果你是在模拟器上测试,也要在真机上检查一下。

【讨论】:

以上是关于首次加载时动画滞后的主要内容,如果未能解决你的问题,请参考以下文章

从另一个活动返回时,MapFragment 的地图加载滞后

iPhone 应用首次加载查询时的动画

首次加载和鼠标悬停/移出时动画矩形高度

首次播放动画时游戏冻结

UITextField 的初始键盘动画的超慢滞后/延迟

winform的页面怎么判断页面首次加载,在线等待!谢谢了!