이번에는 패치 다운로드를 하나씩 차근차근 만들어 볼 예정입니다.
우선 이번 편에는 간단하게 패치파일을 AssetBundle로 만들어보고 패치 리스트를 json으로 관리하는 것을 차근차근 구현해 볼 예정입니다.
실제 프로젝트에서는 AssetBundle 이외에 다른 방식을 이용하기도 하고 json 외에도 csv, tsv, xml 등등 패치 리스트를 관리하는 다른 포맷도 많아서 제 글은 되도록 참고만 하시면 됩니다.
1. 패치 파일 빌드
var manifest = UnityEditor.BuildPipeline.BuildAssetBundles(
patchFolderPath,
UnityEditor.BuildAssetBundleOptions.None,
UnityEditor.EditorUserBuildSettings.activeBuildTarget);
간단하게 에셋 번들 빌드하는 코드를 작성했습니다.
manifest는 저장해두었다 번들 이름이나 Hash를 가져오는데 쓸 수 있어서 변수로 받아두었습니다.
2. 패치 리스트 데이터
[System.Serializable]
public class PatchDataList
{
public List<PatchData> dataList = new List<PatchData>();
}
[System.Serializable]
public class PatchData
{
public string fileName;
public long fileSize;
}
패치 데이터를 저장할 클래스를 선언해주었습니다. 우선은 이름과 사이즈만 저장하도록 해두었습니다.
PatchDataList클래스를 따로 만들어준 이유는 이후 코드에서 JsonUtility로 json파일로 만들어주기 위함입니다.
3. 패치 리스트 만들기
var patchDataListPath = System.IO.Path.Combine(rootPath, patchFolderPath, PATCH_LIST_FILENAME);
var patchDataList = new PatchDataList();
var assetBundleNames = manifest.GetAllAssetBundles();
foreach (var assetBundleName in assetBundleNames)
{
var filePath = System.IO.Path.Combine(rootPath, patchFolderPath, assetBundleName);
if (System.IO.File.Exists(filePath) == false) continue;
var fileInfo = new System.IO.FileInfo(filePath);
if (fileInfo == null) continue;
var newData = new PatchData();
newData.fileName = assetBundleName;
newData.fileSize = fileInfo.Length;
patchDataList.dataList.Add(newData);
}
//패치 리스트 저장
System.IO.File.WriteAllText(patchDataListPath, JsonUtility.ToJson(patchDataList, true));
이전에 받아둔 manifest를 통해서 AssetBundle 이름들을 불러와서 패치 리스트에 넣어주는 코드를 만들었습니다.
참고로 manifest를 받지 않고 AssetDatabase.GetAllAssetBundleNames함수로도 에셋 번들 이름들을 불러올 수 있습니다.
아직 이 정도 구현으로는 패치파일이 갱신되었을 경우 패치받는 클라이언트에서 갱신 확인을 할 수 없습니다.
4. 패치 리스트 버전 갱신 관련 추가
[System.Serializable]
public class PatchData
{
public string fileName;
public long fileSize;
public int version;
public string hash;
}
우선은 version과 hash를 추가했습니다.
hash는 빌드된 패치파일이 갱신되었는지 체크하기 위해 추가했고, version은 패치를 받아야 하는 클라이언트에서 패치받았던 version과 비교하기 위해 추가했습니다.
var patchDataListPath = System.IO.Path.Combine(rootPath, patchFolderPath, PATCH_LIST_FILENAME);
//이전 패치리스트 로드
string jsonText = System.IO.File.Exists(patchDataListPath) ? System.IO.File.ReadAllText(patchDataListPath) : null;
var patchDataList = string.IsNullOrEmpty(jsonText) ? null : JsonUtility.FromJson<PatchDataList>(jsonText);
if (patchDataList == null) patchDataList = new PatchDataList();
List<string> pathedFileNameList = new List<string>();
var assetBundleNames = manifest.GetAllAssetBundles();
foreach (var assetBundleName in assetBundleNames)
{
var filePath = System.IO.Path.Combine(rootPath, patchFolderPath, assetBundleName);
if (System.IO.File.Exists(filePath) == false) continue;
var fileInfo = new System.IO.FileInfo(filePath);
if (fileInfo == null) continue;
var fileSize = fileInfo.Length;
var fileHash = manifest.GetAssetBundleHash(assetBundleName);
var fileHashStr = fileHash.ToString();
var defaultData = patchDataList.dataList.Find(m => m.fileName == assetBundleName);
//기존 데이터가 없으면 새로 생성
if (defaultData == null)
{
var newData = new PatchData();
newData.fileName = assetBundleName;
newData.version = 1;
newData.fileSize = fileSize;
newData.hash = fileHashStr;
patchDataList.dataList.Add(newData);
}
else
{
//hash로 같은 파일인지 체크.
if (defaultData.hash != fileHashStr)
{
defaultData.version++;
defaultData.fileSize = fileSize;
defaultData.hash = fileHashStr;
}
}
pathedFileNameList.Add(assetBundleName);
}
//삭제된 패치파일의 경우 삭제시켜준다.
for (int i = 0; i < patchDataList.dataList.Count; i++)
{
if (pathedFileNameList.Contains(patchDataList.dataList[i].fileName) == false)
{
patchDataList.dataList.RemoveAt(i);
i--;
}
}
//패치 리스트 저장
System.IO.File.WriteAllText(patchDataListPath, JsonUtility.ToJson(patchDataList, true));
이전 패치 데이터와 manifest로 불러온 hash로 비교하여 version을 올려주도록 작업했습니다.
설명보다는 직접 코드를 한 줄씩 보시는 게 더 이해가 빠를 거라 생각됩니다.
추가로 더 이상 패치파일이 아닌 파일은 패치 데이터를 제거하는 코드도 추가했습니다.
마무리
이번 패치 다운로드 만들기 코드들은 GitHub에 올려두고 있습니다.
https://github.com/PieceOfPaper/Unity_SimplePatchExample
GitHub - PieceOfPaper/Unity_SimplePatchExample: 그냥 심플하게 패치 받는 예제
그냥 심플하게 패치 받는 예제. Contribute to PieceOfPaper/Unity_SimplePatchExample development by creating an account on GitHub.
github.com
이로서 패치 리스트 기본 구조는 설계가 끝났고, 다음 편부터는 간단하게 Coroutine으로 다운로드하는 것을 다뤄 볼 예정입니다.
이미 코드는 다 짜둔 상태라 GitHub Repository에 가면 코드를 미리 보실 수 있는 상태이긴 합니다.
이번에도 긴 글 읽어주셔서 감사합니다.
'Unity Tips' 카테고리의 다른 글
Unity에서 패치 다운로드 만들기 3편 - 패치 UI 만들기 (0) | 2022.05.07 |
---|---|
Unity에서 패치 다운로드 만들기 2편 - UnityWebRequest 이용하여 만들기 (0) | 2022.05.07 |
Unity에서 Enum.Parse함수 GC 발생 줄이기 (0) | 2022.05.01 |
Unity에서 계층이 있는 데이터 저장 (JSON vs XML vs Scriptable Object) (0) | 2022.04.30 |
Unity에서 C++코드(cpp) Native Plug-ins 사용하기 (0) | 2022.03.27 |