Cocos2d-x에는 AssetManager라는 라이브 업데이트에 사용할 수 있는 클래스를 Extension으로 제공한다. 하지만 문서화가 잘 되어있지 않고 라이브 업데이트는 코드가 잘못 동작했을 경우 발생할 수 있는 부작용이 크기 때문에 AssetManager를 분석하여 사용하는 대신에 이해하기 쉽게 간단히 라이브 업데이트 기능을 구현해 보았다.(압축 해제 루틴은 AssetManager 클래스를 그대로 참조하였다.) https://github.com/lekdw/cocos2dx-live-update에 작성한 코드를 공개하였으니 참고하기 바란다.
프로젝트에서 cocos2d 폴더와 Android, iOS 프로젝트 폴더가 생략되었으므로 Cocos2d-x 프로젝트에서 복사하여 사용하도록 한다. Update 폴더에 테스트로 만들어 놓은 업데이트 파일과 버전 파일을 라이브 업데이트를 위한 Http 서버에 복사해 놓은 후 AssetPanel.cpp의 VERSION_FILE_URL에 버전 파일 위치로 변경하고 Win32 프로젝트를 빌드하여 실행하면 다음과 같이 새로운 버전 업데이트 파일을 다운로드하여 압축을 해제하는 것을 확인할 수 있다.
다운로드한 업데이트 파일이 저장되고 압축이 해제되는 위치는 코드 상에서 FileUtils::getInstance()->getWritablePath() + "asset/"이고 번들의 Resources 디렉토리보다 파일 찾기 우선순위가 높기 설정되어 있기 때문에 업데이트된 파일과 버전 파일을 asset 디렉토리에서 읽어들이게 된다. 파일 찾기 우선순위는 AppDelegate.cpp에서 아래과 같은 코드로 변경된다.
AppDelegate.cpp
bool AppDelegate::applicationDidFinishLaunching() {
(생략)
// 캐쉬 디렉토리에 에셋 디렉토리가 없으면 생성한다.
std::string assetPath = FileUtils::getInstance()->getWritablePath() + "asset/";
if (!FileUtils::getInstance()->isDirectoryExist(assetPath))
FileUtils::getInstance()->createDirectory(assetPath);
// 캐쉬 디렉토리의 에셋 디렉토리에서 먼저 리소스 파일을 찾을 수 있도록 설정한다.
// 요청하는 리소스 파일이 캐쉬 디렉토리의 에셋 디렉토리에 없을 경우는 번들 리소스 디렉토리에서 찾는다.
std::vector searchPath;
searchPath.push_back(assetPath);
for (std::string path : FileUtils::getInstance()->getSearchPaths())
searchPath.push_back(path);
FileUtils::getInstance()->setSearchPaths(searchPath);
(생략)
}
구현된 라이브 업데이트 기능의 실행 플로우를 그려보면 아래와 같다.
파일 다운로드는 Cocos2d-x의 network::HttpClient 클래스를 사용하는데 이 클래스 구현은 파일 다운로드 진행 상황을 알 수가 없다.다운로드 진행 상황을 Polling 방식으로 알 수 있도록 network::HttpClient 클래스가 수정되어 적용되었다.
프로세스 항목 중에서 파일 다운로드와 압축 해제 과정은 별도의 Thread에서 처리되므로 Cocos2d-x Thread가 Block되지 않도록 AssetPanel.cpp에 구현되어있다. 모든 처리가 완료된 후 프로그램을 다시 실행하면 다음과 같이 라이브 업데이트가 적용된 것을 확인할 수 있으며 Android, iOS 모두 동일하게 동작한다.

댓글 없음:
댓글 쓰기