배경 정보 : 여러 개의 "바닥"이있는 SpriteKit 2D 플랫폼 스타일 게임을 만들고 있습니다. 사용자가 "포털"에 입장하면 다른 층 (하나 또는 둘 중 하나)으로 운송됩니다. 사용자가 가장 최근의 스폰 지점과 다른 층에서 사망하면 스폰 지점으로 다시 이송됩니다.SKNodes 추가, 제거 및 캐싱
문제점 : iOS8로 업그레이드 한 후이 시나리오를 실행하면 예외/오류 EXC_BAD_ACCESS
이 발생하여 게임이 중단됩니다. 이러한 오류를 디버깅하는 방법에 대한 여러 자습서를 거친 후에도 문제를 찾을 수없는 것 같습니다.
누군가 내 코드를 살펴보고 내가하고있는 일을하는 더 좋은 방법을 볼 수 있다면 게임을 멈추지 않는 것이 좋습니다.
게임 레이아웃 : 나는 레이 Wenderlich의 책 자습서으로 아이폰 OS 게임에서 같은 클래스를 기반으로 사용자 정의 클래스 TileMapLayer
있습니다. 기본적으로 여러 개의 32x32p 타일을 포함하는 사용자 정의 SKNode 클래스로, 내 게임의 배경을 만듭니다.
게임 시작시 적절한 층을 적재하고 사용자가 위/아래로 이동할 때 다른 층을 불러 오라고합니다. 이 시나리오에서는 현재 층을 NSDictionary
에 먼저 캐시하므로 사용자가이 층으로 돌아 오면 나중에 액세스 할 수 있습니다.
// Cache the current floor
[_allFloors setObject:_bgLayer forKey:[NSString stringWithFormat:@"floor_%tu", (unsigned)_currentFloor]];
// Remove the current floor
[_bgLayer removeFromParent];
// Get the cached (next) floor if it exists, if not create it
TileMapLayer *cachedFloor = [_allFloors objectForKey:[NSString stringWithFormat:@"floor_%tu", (unsigned)(_currentFloor + 1)]];
if (!cachedFloor) {
_bgLayer = [self createScenery:[NSNumber numberWithInteger:(_currentFloor + 1)]];
NSLog(@"creating new floor");
} else {
_bgLayer = cachedFloor;
NSLog(@"getting cached floor");
}
// Display the new floor
[_worldNode addChild:_bgLayer];
// Increment the floor number
_currentFloor++;
(나는 바닥을 내려 가기위한 유사한 방법을가집니다). iOS8로 업그레이드하기 전후에 완벽하게 작동합니다.
사용자가 사망하면 마지막 스폰 지점으로 다시 이동합니다. 마지막 스폰 지점이 다른 층에 있으면 층도 적절하게 변경됩니다. 내가 애니메이션의 일환으로 볼 자체에이 사용자 정의 SKAction 전화 :
SKAction *changeFloor = [SKAction runBlock:^{
if (self.spawnFloor != _currentFloor) {
[_bgLayer removeFromParent];
_bgLayer = [_allFloors objectForKey:[NSString stringWithFormat:@"floor_%tu", (unsigned)self.spawnFloor]];
[_worldNode addChild:_bgLayer];
_currentFloor = self.spawnFloor;
NSLog(@"Made it here");
}
}];
당신은 큰 차이가없는 볼 수 있듯이
.Made it here
은 콘솔에 기록되지만 게임은 즉시 멈 춥니 다. 공을 올바른 위치로 이동시키기 위해 내가 호출하는 다음 메서드는 전혀 실행되지 않습니다. 그냥 재미를 위해 나는과 같이 부모로부터 제거하기 전에 _bgLayer
캐싱을 시도 :
if (self.spawnFloor != _currentFloor) {
[_allFloors setObject:_bgLayer forKey:[NSString stringWithFormat:@"floor_%tu", (unsigned)_currentFloor]];
...
그리고 나는이 작업을 수행 할 때 게임이 정지하지 않는 몇 가지 이유. 그러나 바닥은 마치 _bgLayer
이 부모로부터 절대 제거되지 않은 것처럼 섞여 버립니다. (참고 : "오래된"타일은 더 이상 물리 시뮬레이션에 반응하지 않으며 배경이없는 상태입니다.)
[_bgLayer removeFromParent];
[_bgLayer removeAllChildren];
을하지만 내가 respawning 후이 바닥에 반환 할 때 _bgLayer가 비어 원인 :
는 또한 바로 부모로부터 제거한 후 (개별 타일을 제거)[_bgLayer removeAllChildren]
을 시도했다. 마치 사전에 저장하기 전에 모든 노드를 제거한 것처럼 말입니다. 내 생각에 사전은 콘텐츠 자체가 아닌 _bgLayer의 위치 만 참조합니다. 그래서 화면에서 모든 아이들을 제거 할 때 캐시에서 모든 아이들을 효과적으로 제거합니다. 요약 : 이 질문은 오랜 질문이며, 작성해 주신 것에 대해 감사드립니다. 질문이 있으시면 아래 의견에 주저하지 마십시오. 궁극적으로, 제가 알고 싶은 것은 이것입니다 : 게임이 멈추지 않도록 내 문제를 어떻게 해결할 수 있습니까? 메모리 문제없이 바닥을 캐싱하는 가장 좋은 방법은 무엇입니까? 화면에서 노드를 제거하고 추가하는 가장 좋은 방법은 무엇입니까? 항상 현재 바닥 (화면에있는 바닥)을 _bgLayer
이라고 말하면 어떨까요?
다시 한 번 감사드립니다.
예외 중단 점을 추가 했습니까? 충돌이 발생할 때 Xcode가 강조하는 라인은 무엇입니까? 호출 스택이란 무엇입니까? 어떤 종류의 오류 메시지가 로그에 인쇄됩니까? – LearnCocos2D
예외 중단 점을 추가하려고 시도했지만 xcode는 @autoreleasepool을 제외한 모든 행을 강조 표시하지 않습니다. 콘솔에 아무 것도 인쇄되지 않습니다 ... :( – Aleksander