많은 사람들이 일하는 것을 알고 있습니다. "전역 사용 안 함"또는 "단독 사용은 악"과 같은 일반적인 규칙이 적용됩니다. 이러한 지혜의 단어는 때때로 적용될 수 있지만, 게임을 끝내는 데있어보다 효율적으로 사용할 수있는 방법으로 보는 것이 좋습니다.
전역/싱글 톤이 유용 할 때가 있습니다. 게임 및 임베디드 시스템은 기존 응용 프로그램과 다른 규칙으로 실행됩니다. 이들은 일반적으로 자원 요구 사항과 결합 된 자원 제약 "응용 프로그램"입니다. 지구본은 각각의 생각보다 더 일반적입니다. 싱글 톤 또한 일반적으로 사용됩니다. 필자는 임베디드 시스템과 게임 모두에서 작업했으며, 내가 작업 한 모든 프로젝트에서 전역, 싱글 톤 또는 둘 다를 사용했다고 말할 수 있습니다.
실제로는 전역에 대해 싱글 톤을 사용합니다. 주로 전역 파일을 어디에 밀어 넣을지 걱정할 필요가 없으며, 헤더 파일이 속한 파일이 무엇인지 걱정할 필요가 없기 때문에 주로 그 이유에 대한 근거가 모든 Swifties와 다를 것입니다. 나에게이 물건은 C++에서 약간의 Obj-C와 스위프트 (Swift)의 흩어져있는 부분에서 처리된다.
게임 라이프 사이클을 관리해야하는 필요성은 SpriteKit
과 별개입니다. 내가보고있는 SpriteKit
게시물 중 상당수는 개발자 또는 씬 (scene)에 게임 상태를 포함시키는 데 사용됩니다. 그들은 보통 상황을 다음 장면으로 옮기는 방법에 대한 몇 가지 딜레마에 직면 해 있습니다. 이 방법이 "로컬 상태"(즉, 현재 화면, 스테이지 등의 상태)에 좋을 수도 있지만 글로벌 게임 상태에는 좋지 않습니다. 예를 들어 기본 화면에서 옵션 화면으로 전환 한 다음 다시 메인 화면으로 돌아간 다음 게임에서 변경 사항을 추적하는 경우 (예 : 게임 난이도 변경)? 그렇습니다. 사전, 구조체 또는 주위에있는 것들을 확실히 전달할 수 있습니다. 그러나 어떤 시점에서, 당신은 하나의 공통적이고 편리한 투기장을 갖는 것이 더 편리하다는 것을 발견하게 될 것입니다. 이 "덤핑 그라운드"는 글로벌/싱글 톤이 될 것입니다.
이제 나에게 소리 지르기 시작하기 전에 전역과 싱글 톤에 대한이 모든 미친 이야기를 포착 할 수 있습니다. 나는 전역/싱글 톤을 많이 만들지는 않는다. 오히려 글로벌/싱글 톤을 사용하는 경우 제어 할 수 있습니다.
저는 'gazillion'이라고 말하지 않습니다. 나는 하나처럼 이야기하고있다. (나는 보통 소수만 사용한다.) 우리의 허구의 친구, GameManager
에 들어가십시오.
공간 사수의 아주 간단한 시나리오를 살펴 보겠습니다. 제목 화면, 기본 화면, 게임 화면 및 끝 파도 화면과 같은 여러 화면이 있다고 가정 해보십시오. 여러 화면으로 전달되는 데 유용한 정보가 있습니다. 예를 들어 높은 점수 또는 현재 점수. 이러한 값은 다양한 화면/장면에 표시하려는 값일 수 있습니다. 그럼 점수는 어디에 저장합니까? 그들 사이에 점수를 어떻게 전달합니까? 예를 들어, 모든 화면에 마지막으로 높은 점수가 표시되면 어디에서 그 값을 유지해야합니까?
글로벌 인 경우 범위를 벗어나는 인스턴스의 전역 정의가 있습니다.
:처럼 : 당신이 점수를 UDPATE 할 경우는 같이 보일 것이다 점수를 업데이트 싱글이라면
는
var theGameManager : GameManager
그래서, 당신은
theGameManager.score += 100
을 할 거라고 GameManager.sharedInstance.score += 100
좋아요. 싱글 톤 구문은 조금 길지만 아마 이것이 어디서 무엇인지에 관해서는 세계보다 덜 암시 적이다.
하지만 이제 여기에 더 많은 힘을 줄 수 있습니다. 점수를 추가 할 때마다 100000의 배수가 당신에게 여분의 점수를 부여한다고 가정 해 봅시다. 나는 이제 세터를 쉽게 활용하고 그 세터를 사용하여 여분의 생명에 보답 할 수 있습니다. 예를 들어이 들어
:
GameManager.sharedInstance.score += 100 // the magic of the 100000 for extra life happens automagically in the setter
이 같은 가능성이 뭔가 대 :이 같은
myScore += 100
// Do logic to find out if we get an extra life.
// Is this done in a method and if so where does this method live?
// Or is it straight up code which will be duplicated?
코드 글로벌 게임 상태를 관리하는 데 도움이 모든 깔끔하게 GameManager
내에 포함되어 있습니다. 즉, GameManager
은 값을 유지 관리하는 것이 아니라 이러한 값을 중심으로 기능을 캡슐화하는 방법을 제공합니다.
흠, 여기는 currentScene
인 것 같습니다. 왜 그랬을까요? GameManager
은 장면 전환을 관리하는 훌륭한 방법이기도합니다. 게임 상태를 통해 할 가능성이 더 큽니다. 같은 아마 뭔가 : 장면 뒤에
GameManager.sharedInstance.gameState = GameOverState
의 gameState
세터 장면을 교환의 마법을 할 다음 수 있습니다.
이러한 방법의 실제적인 예가 될 수 있습니다.
로딩/저장에 관한 이야기는 원하는 경우 GameManager
을 통해 수행 할 수도 있습니다. 나 자신을 위해, 나는 일반적으로 GameManager
내의 일부 데이터를 기반으로 독립적으로 취급합니다. 그리고 이것은 또 다른 구별을 불러옵니다. 일반적으로 GameManager
내에 아이디어를 캡슐화합니다. 예를 들어, 나는 아마 Player
있을 것하고는 GameManager
모습과 같이 할 것 :
class GameManager : NSObject {
// Overall game state, GameState is probably some enum
var state:GameState
var lastState:GameState
// Sometimes tracking scenes is useful
var currentScene:SKScene?
var nextScene:SKScene? // Sometimes helpful if you need to construct the next scene and it takes a non-trivial amount of time
// These are the globals we need to share to different "parts" of the game
// Note player state is done through this object. This way I can pass around only player when needed.
var player: Player
var stage: Uint
var highscores:[Uint] // A list of all the high score for the user. You would probably want HS based on other users too
// Egads a singleton!
static let sharedInstance = GameManager()
}
은 당신이 말하는 기다립니다; "하지만이 글로벌/싱글 톤 재즈가 마음에 들지 않습니다. 왜이 곡을 필요로하는 모든 사람들에게 전달하지 않는 것이 좋을까요?" 대답은 "할 수있다"입니다. 그러나 실제로, 당신은 이것이 지루 해지는 것을 발견하기 시작할 것입니다. GameManager
이 필요하다는 것을 알았지 만 발신자에게 GameManager
이 전달 된 적이 없었습니다. 이것은 이제이 객체를 통과시키는 몇 가지 방법을 재 작업한다는 것을 의미합니다.
Soooo는 (는) 글로벌/싱글 톤입니다. 당신은 당신 자신의 판사가 될 수 있습니다. 누구나 선택할 수있는 해결책이 있습니다. 그리고 그것이 당신을 위해 작동한다면, 그것을 사용하십시오. 나를 위해, 그것은 생각할 필요가 없다.구현을 통해 전역 게임 상태에 액세스/관리 할 때 일관성있는 사용 용이성에 대한 이점은 확실한 선택입니다.
에 대한 이미 긴 대답을 위해 여기에 조금 더 많은 정보를 추가하려고합니다. 몇 가지를 명확히 해보십시오.
싱글 톤 또는 글로벌 선택은 사용법, 플랫폼 및 언어에 따라 다릅니다. 또한 게임 코드 기반에 따라 달라집니다. 그것은 단지 어떤 데이터의 투기장이되는 것이 아닙니다. 활용할 경우 내용을 신중하게 고려해야하며 가능한 경우 내용에 다른 용기를 사용하십시오 (예 : 수업에서 포장하십시오). 따라서 첫 번째 예제에 플레이어 정보가 매달려 있지만 (실제로 아이디어를 전달하기 쉽도록) 실제로는 PlayerState
에 플레이어 데이터가 포함되어 있습니다. 전체적으로 플레이어가 아닐 수도 있지만 플레이어의 게임 수명을 넘어서 살아야하는 일부 공유 정보 일 수 있습니다.
class PlayerState {
var score:Uint
var highscore:Uint
var lives:Uint
}
// Simplified GameManager
class GameManager {
var state:GameState
var lastState:GameState
var player:PlayerState
// Egads a singleton!
static let sharedInstance = GameManager()
}
또한, 나는 항상 전역/싱글을 통해 그것을 잡기 위해 코드를 기대 대 PlayerState
예를 주위에 전달 끝날 것입니다.
그래서 예를 들어 내가 이런 짓을 했을까 :
func doSomething(playerState:PlayerState) {
var score = playerState.score
// Blah blah blah
}
베루스
func doSomething() {
// Whee I have singleton
var score = GameManager.player.score
// Blah blah blah
}
효과적으로 제가 데이터에 액세스 할 수 앵커 포인트로 싱글 톤을 사용하고 있어요 것은 객체 더 쉽게 다음 필요한 경우 전달하십시오. 다시 말하면, 그들이 고용되어있는 동안, 나는 또한 코드가 GameManager.sharedInstance
으로 가득 차는 것을 원하지 않는다.
앞서 언급했듯이이 접근법에는 확실한 단점이 있습니다. 하나는 동시성입니다. 그러나 글로벌/싱글 톤이 아닐지라도 동시성은 여전히 데이터에서 발생할 수 있다고 지적 할 것입니다.
이 추가 사항은 게임 개발사 (일반적으로 코딩)가 어느 정도의 실용성이 있다는 것입니다. 게임을 발표 할 때 시스템 리소스와 균형을 맞추는 것뿐만 아니라 사람들이 게임을 할 수 있도록 게임을 만들고있는 것 같습니다. 그리고 그 일이 일어나려면 그 일을 끝내야합니다. 모두가 완벽한 눈송이를 만들고 싶어하지만 그 완벽을위한 시간은 무엇입니까? 대답의 시작 부분에서 나는이 기법이 도구라는 것을 지적했다. 전역/싱글 톤은 모든 사람에게 적합한 것은 아닙니다. 동시에, 디자인 진언을 맹목적으로 따르지 않아야합니다. 그것이 당신을위한 효과적인 도구가 될 수 있고 당신이 당신의 게임을 더 빨리 끝낼 수 있다면, 그 일은 가치있는 일입니다. 항상 다른 게임을 쓸 것이므로, 경험에 기반하여 무엇이 효과적인지, 그렇지 않은지를 결정할 수 있습니다.
https://thatthinginswift.com/singletons/ – 0x141E
NSCoding 및 iCloud를 사용하기 때문에 sharedIstance의 클래스를 사용합니다. –
여전히 이러한 답변 및 의견을 통해 무엇을 해결하려고 노력하고 있습니까? 나는 일을 해요! –