2013-10-14 2 views
7

제 게임에는 게임 맵을 구성하는 수천 개의 "타일"노드가 있습니다 (심시티를 생각해보십시오), 텍스처링을위한 가장 빠른 프레임 속도/메모리 효율적인 경로가 무엇인지 궁금하네요. 각 노드에 애니메이션을 적용 할 수 있습니까? 소수의 고유 한 타일 "유형"이 각각 고유 한 텍스처/애니메이션을 가지고 있으므로 가능한 경우 텍스처가 재사용되고 있는지 확인하는 것이 중요합니다.SpriteKit 수천 개의 스프라이트에 대해 텍스처 아트라스를로드 할 곳

내 모든 tile 노드는 타일 형식을 인식하고 필요한지도 책을 & 애니메이션을로드 맵 노드 핸들 (A PLIST에서 질감 & 아틀라스 이름을로드하여 예?)해야 하나 map 노드의 자녀

또는 각 타일 유형은 특정 하위 클래스입니다. 각 SKSpriteNode 타일이 자신의 스프라이트 아틀라스로드를 처리하는 것이 더 좋을까요? [tileInstance texturise]; (스프라이트 키트가이 방법을 사용하면이 방법을 사용하면 특정 타일 유형의 각 인스턴스에 대해 동일한 텍스처 아트라스가 메모리에로드됩니다.)

지도 및 질감에 대한 자세한 설명은 문서를 찾아 보았습니다. reusage 그러나 나는 전형적인 시나리오가 이런 시나리오를 위해 무엇인지 모른다. 어떤 도움을 주시면 감사하겠습니다.

답변

21

메모리 첫 번째 : 눈에 띄는 차이는 없습니다. 타일의 텍스처를로드해야합니다. 텍스처는 Map + Tiles의 메모리 중 99 % 이상을 차지합니다.

텍스처 재사용 : 텍스처가 자동으로 재사용되거나 캐싱됩니다. 동일한 텍스처를 사용하는 두 개의 스프라이트는 텍스처의 자체 복사본이있는 각각의 텍스처가 아닌 동일한 텍스처를 참조합니다.

프레임 속도/일괄 처리 : 이것은 일괄 처리에 대한 모든 것입니다. Sprite Kit는 자식 배열에 추가 된 순서대로 노드를 일괄 처리하여 노드의 일괄 처리에 접근합니다. 다음 자식 노드가 이전 노드와 동일한 텍스처를 사용하는 한, 모든 자식 노드는 하나의 그리기 호출로 일괄 처리됩니다. 스프라이트, 라벨, 스프라이트, 라벨 등을 추가하는 것이 가장 나쁜 방법 일 수 있습니다. 가능한 한 연속적인 순서로 같은 텍스처를 사용하여 많은 스프라이트를 추가하려고합니다.

아틀라스 용도 : 여기에서 가장 많은 것을 얻을 수 있습니다. 일반적으로 개발자는 아틀라스를 분류하려고 시도하는데 잘못된 방향입니다. 하나의 타일 (및 그 애니메이션)마다 하나의 아틀라스를 만드는 대신 가능한 한 많은 타일을 포함하는 텍스처 아틀라스를 최대한 작게 만들고 싶을 것입니다. 모든 iOS 7 장치에서 텍스처 맵은 2048x2048 일 수 있으며 iPhone 4 및 iPad 1을 제외한 다른 모든 장치는 최대 4096x4096 픽셀의 텍스처를 사용할 수 있습니다.

이 규칙에는 예외가 있습니다. 많은 양의 텍스처가 모든 장치의 메모리에 한꺼번에로드 될 수 없다면 예외가 있습니다. 이 경우 최적의 판단을 사용하여 메모리 사용과 일괄 처리 효율성에 대한 좋은 절충안을 찾아야합니다. 예를 들어 하나의 솔루션은 다른 장면에 대한 다른 텍스처 아트라스의 일부 타일을 복제하는 경우에도 고유 장면마다 또는 하나의 "장면"당 하나 또는 두 개의 텍스처지도를 만드는 것일 수 있습니다. 거의 모든 경치에 나타나는 타일이있는 경우이를 "공유 된"지도 책에 넣는 것이 좋습니다.

타일을 서브 클래 싱하는 타일의 경우, 나는 노드 클래스의 서브 클래 싱을 피하기위한 강력한 지지자입니다. 특히 하위 클래스로 분류하는 주된 이유는 단순히 사용중인 텍스처를 변경하거나 애니메이션을 적용하는 것입니다. 스프라이트는 이미 텍스처의 컨테이너이므로 스프라이트 텍스처를 변경하고 외부에서 애니메이션을 적용 할 수 있습니다.

노드에 데이터 또는 추가 코드를 추가하려면 사용자 고유의 NSMutableDictionary를 만들고 필요한 모든 객체를 추가하여 userData 속성을 볼 수 있습니다. 전형적인 구성 요소 기반 접근 방식은 다음과 같이 갈 것 :

SKSpriteNode* sprite = [SKSpriteNode spriteWithWhatever..]; 
[self addChild:sprite]; 

// create the controller object 
sprite.userData = [NSMutableDictionary dictionary]; 
MyTileController* controller = [MyTileController controllerWithSprite:sprite]; 
[sprite.userData setObject: forKey:@"controller"]; 

이 컨트롤러 객체는 다음 타일에 필요한 사용자 지정 코드를 수행한다. 타일과 그 밖의 다른 것들을 움직일 수 있습니다. 스프라이트 사전을 유지하므로

@interface MySpriteController 
@property (weak) sprite; // weak is important to avoid retain cycle! 
@end 

(: 스프라이트 여기) 약한 참조 유일한 중요한 비트를 소유하는 노드에 대한 참조를 만드는 것이다. 사전은 컨트롤러를 유지합니다. 콘트롤러가 스프라이트를 유지한다면, 스프라이트는 여전히 유지 참조가 있기 때문에 할당을 해제 할 수 없다. 따라서 스프라이트를 유지하는 컨트롤러를 보유하고있는 사전을 계속 유지할 것이다. 컴포넌트 기반의 접근 방식 (도 Kobold Kit에 의해 선호되고 구현)를 사용

장점 : 제대로 설계하는 경우

  • 은 하나 또는 여러 노드와 함께 작동합니다. 언젠가 레이블, 효과, 모양 노드 타일을 원한다면 어떨까요?
  • 모든 타일에 하위 클래스가 필요하지 않습니다. 일부 타일은 단순한 정적 스프라이트가 될 수 있습니다. 따라서 간단한 정적 SKSpriteNode를 사용하십시오.
  • 필요에 따라 개별 애스펙트를 시작/중지하거나 추가/제거 할 수 있습니다. 타일에 대해서조차도, 당신은 처음에 특정면을 필요로하거나 기대하지 않았습니다.
  • 구성 요소를 사용하면 자주 필요하거나 다른 프로젝트에서도 필요한 기능의 레퍼토리를 작성할 수 있습니다.
  • 구성 요소가 아키텍처를 개선합니다. 고전적인 OOP 디자인 실수는 플레이어 클래스와 적 클래스를 가진 다음 화살표를 쏘고 갑옷을 장비 할 수 있어야한다는 것을 깨닫는 것입니다. 그래서 move the code to the root GameObject class, 모든 하위 클래스에서 코드를 사용할 수 있습니다. 구성 요소를 사용하면 간단히 장비가 있고 촬영 구성 요소가 필요한 객체에 추가됩니다.
  • 구성 요소 기반 디자인의 큰 장점은 개별적인 측면을 다른 것들과 별도로 개발하기 시작하므로 필요에 따라 재사용하고 추가 할 수 있다는 것입니다. 다른 사고 방식으로 접근하기 때문에 더 자연스럽게 코드를 작성할 수 있습니다.
  • 내 경험에 의하면 일단 게임을 구성 요소로 모듈화하면 버그가 훨씬 적어지고 다른 구성 요소의 코드를 보거나 고려할 필요가 없으므로 해결하기가 더 쉽습니다. 한 구성 요소가 다른 구성 요소를 트리거 할 때 명확한 경계가 있습니다. 즉, 다른 구성 요소가 인수 될 때 전달 된 값이 여전히 올바른 것입니까? 그렇지 않은 경우 버그는 첫 번째 구성 요소에 있어야합니다.

이것은 good introduction on component-based design입니다. 하이브리드 방식은 분명히 갈 길이 멀다. 여기에 more resources on component based design하지만 나는 "받아 들여진 대답의 저자"가 제안한 것처럼 경로에서 벗어나 FRP를 바라 보는 것에 대해 강력하게 조언합니다 - FRP는 흥미로운 개념이지만 게임 개발에는 아직 실제 응용 프로그램이 없습니다.

+1

솔리드 대답 ... 너무 많이 배우지 못했습니다! – DogCoffee

+5

전반적으로 좋은 답변입니다. ** 일괄 처리 **에 대한 확장 : SKView에서'ignoresSiblingOrder'를'YES'로 설정하면 아이들의 순서에 대해 크게 걱정할 필요가 없습니다. Sprite Kit는 자동으로 정렬하여 효율적인 그리기를 수행합니다 (예 : 한 번의 드로우 콜에서 같은 텍스처 맵의 모든 스프라이트).** atlases ** :'ignoresSiblingOrder'를 염두에두고, 하나의 아틀라스에 너무 많은/큰 텍스처가있는 경우 노드 계층 구조를 사용하여 장면을 각각 하나의 그리기 호출이 될 수있는 "레이어"로 구성하는 데 도움이 될 수 있습니다 하나의 아틀라스 (예 : 세계 대 HUD). – rickster

+0

시원하게, 나는이 속성에 대해 몰랐다 – LearnCocos2D

관련 문제