카테고리 없음

Unity와 iOS 네이티브 코드 연동하여 iCloud 데이터 저장 구현하기

wolstar 2024. 8. 22. 22:42

Unity 게임 개발에서 iCloud와 같은 iOS 고유 기능을 활용하려면, iOS 네이티브 API를 Unity와 연동해야 합니다. 이 글에서는 iOS의 네이티브 코드를 작성하고 이를 Unity C# 코드와 연결하여 iCloud 데이터를 저장하고 불러오는 방법을 설명하겠습니다.

iOS 네이티브 코드 구현

먼저, iOS 네이티브 코드를 Objective-C로 작성합니다. 이 코드는 iCloud에 데이터를 저장하고 불러오는 기능을 제공합니다.

Objective-C 클래스 구현 ,네이티브 함수와 Unity 연동

Objective-C로 작성한 iOS 네이티브 코드를 Unity에서 호출할 수 있도록 외부 함수로 노출해야 합니다. 이를 위해 extern "C"를 사용하여 C# 코드에서 호출 가능한 형태로 함수를 정의합니다.

 

iCloudManager.mm

#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>
 
@interface iOSPlugin : NSObject
 
@end
 
@implementation iOSPlugin
 
    // iOS에서 다른 오디오가 재생 중인지 확인하는 함수
    +(bool)IsAudioPlaying
    {
        return [[AVAudioSession sharedInstance] isOtherAudioPlaying];
    }
 
    // iCloud에서 데이터를 불러오는 함수
    +(NSString *)GetiCloudData:(NSString *)key
    {
        // 데이터를 가져오기 전에 iCloud와 동기화
        [[NSUbiquitousKeyValueStore defaultStore] synchronize];
     
        NSUbiquitousKeyValueStore *cloudStore = [NSUbiquitousKeyValueStore defaultStore];
        return [cloudStore objectForKey:key];
    }
 
    // iCloud에 데이터를 저장하는 함수
    +(BOOL)SetiCloudData:(NSString *)key setValue:(NSString *)value
    {
        NSUbiquitousKeyValueStore *cloudStore = [NSUbiquitousKeyValueStore defaultStore];
        [cloudStore setObject:value forKey:key];
        // iCloud와 동기화 (비활성화됨)
        return false;
    }
 
    // iCloud에서 모든 데이터를 삭제하는 함수
    +(void)DeleteiCloudData()
    {
        NSUbiquitousKeyValueStore *cloudStore = [NSUbiquitousKeyValueStore defaultStore];
     
        NSDictionary *dict = [cloudStore dictionaryRepresentation];
     
        NSArray *allKeys = [dict allKeys];
     
        for(int i = 0; i < allKeys.count; i++)
        {
            NSString *key = [allKeys objectAtIndex:i];
            [cloudStore removeObjectForKey:key];
        }
    }
 
    // iCloud 데이터를 강제로 동기화하는 함수
    +(void)ForceSynciCloudData()
    {
        NSUbiquitousKeyValueStore *cloudStore = [NSUbiquitousKeyValueStore defaultStore];
        [cloudStore synchronize];
    }
 
    // C 문자열을 반환하여 Unity가 메모리를 처리할 수 있도록 함
    char* cStringCopy(const char* string)
    {
        if(string == NULL)
        {
            return NULL;
        }
     
        char* res = (char*)malloc(strlen(string) + 1);
        strcpy(res, string);
           
        return res;
    }
 
@end

extern "C"
{
    bool _IsDevicePlayingOtherAudio()
    {
        return [iOSPlugin IsAudioPlaying];
    }
 
    const char * _GetiCloudData(const char *key)
    {
        // NSString을 C 문자열로 변환하여 Unity에서 사용 가능하도록 함
        return cStringCopy([[iOSPlugin GetiCloudData:[NSString stringWithUTF8String:key]] UTF8String]);
    }
 
    bool _SetiCloudData(const char *key, const char *value)
    {
        return [iOSPlugin SetiCloudData:[NSString stringWithUTF8String:key] setValue:[NSString stringWithUTF8String:value]];
    }
 
    void _DeleteiCloudData()
    {
        [iOSPlugin DeleteiCloudData];
    }
 
    void _ForceSynciCloudData()
    {
        [iOSPlugin ForceSynciCloudData];
    }
}

 

 

네이티브 코드 설명

  1. IsAudioPlaying:
    • AVAudioSession을 통해 현재 iOS 기기에서 다른 오디오가 재생 중인지 확인합니다.
    • Unity에서 이 함수를 호출하면 게임이 실행 중일 때 다른 오디오가 재생되고 있는지 알 수 있습니다. 이를 통해 게임의 오디오 출력을 조정할 수 있습니다.
  2. GetiCloudData:
    • 주어진 key를 사용하여 iCloud에 저장된 데이터를 가져옵니다.
    • 데이터를 가져오기 전에 synchronize를 호출하여 iCloud와의 동기화를 보장합니다.
    • 반환된 데이터는 NSString 형식으로, Unity에서는 C 문자열로 변환됩니다.
  3. SetiCloudData:
    • 주어진 key와 value를 사용하여 iCloud에 데이터를 저장합니다.
    • 데이터가 저장된 후 iCloud와의 동기화는 기본적으로 비활성화되어 있지만, 필요에 따라 활성화할 수 있습니다.
  4. DeleteiCloudData:
    • iCloud에 저장된 모든 데이터를 삭제합니다.
    • 이 함수는 dictionaryRepresentation을 사용하여 모든 키-값 쌍을 가져온 후, 각 키에 대해 removeObjectForKey를 호출하여 데이터를 삭제합니다.
  5. ForceSynciCloudData:
    • iCloud 데이터를 강제로 동기화합니다.
    • 이 함수는 수동으로 동기화를 강제하여, 데이터 동기화가 즉시 이루어지도록 합니다.
  6. cStringCopy:
    • NSString을 C 문자열로 변환하여 Unity에서 메모리를 안전하게 관리할 수 있도록 합니다.
    • 이 함수는 문자열 복사를 수행하여, Unity가 반환된 문자열을 자유롭게 사용할 수 있도록 합니다.

 

Unity에서 iOS 네이티브 함수 호출

이제 앞서 작성한 iOS 네이티브 코드를 Unity C#에서 호출할 수 있습니다. 아래의 C# 코드에서 네이티브 함수를 호출하는 방법을 확인할 수 있습니다.

 

public class iOSNativePlugin : MonoBehaviour
{
    static string GAME_DATA_KEY => $"Game_Name";

#if UNITY_IOS && !UNITY_EDITOR

    [DllImport("__Internal")]
    private static extern bool _IsDevicePlayingOtherAudio();

    [DllImport("__Internal")]
    private static extern string _GetiCloudData(string key);

    [DllImport("__Internal")]
    private static extern bool _SetiCloudData(string key, string value);

    [DllImport("__Internal")]
    private static extern void _DeleteiCloudData();

    [DllImport("__Internal")]
    private static extern void _ForceSynciCloudData();

    public static bool IsDevicePlayingOtherAudio()
    {
        return _IsDevicePlayingOtherAudio();
    }

    public static string GetiCloudData()
    {
        if (string.IsNullOrEmpty(_GetiCloudData(GAME_DATA_KEY)))
        {
            return "";
        }
        else
        {
            return System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(_GetiCloudData(GAME_DATA_KEY)));
        }
    }

    public static bool SetiCloudData(string value)
    {
        return _SetiCloudData(GAME_DATA_KEY, Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(value)));
    }

    public static void DeleteiCloudData()
    {
        _DeleteiCloudData();
    }

    public static void ForceSynciCloudData()
    {
        _ForceSynciCloudData();
    }

#else
    public static bool IsDevicePlayingOtherAudio()
    {
        return false;
    }

    public static string GetiCloudData()
    {
        return "";
    }

    public static bool SetiCloudData(string value)
    {
        return false;
    }

    public static void DeleteiCloudData() { }
    public static void ForceSynciCloudData() { }

#endif
}

 

Unity C# 코드 설명

  1. 플랫폼 전처리:
    • #if UNITY_IOS && !UNITY_EDITOR는 iOS 환경에서만 네이티브 함수를 호출할 수 있도록 하며, Unity 에디터나 다른 플랫폼에서는 더미 함수가 대신 호출되도록 합니다.
  2. 네이티브 함수 호출:
    • C#의 DllImport("__Internal")를 사용하여 네이티브 Objective-C 코드를 직접 호출합니다.
    • 예를 들어, _IsDevicePlayingOtherAudio()는 IsAudioPlaying을 호출하여 오디오 재생 상태를 반환합니다.
  3. 데이터 저장 및 불러오기:
    • GetiCloudData와 SetiCloudData 함수는 iCloud에서 데이터를 불러오고 저장하는 역할을 합니다.
    • 저장된 데이터는 Base64 인코딩 후 저장되며, 불러올 때는 이를 디코딩하여 사용합니다.
  4. 데이터 동기화 및 삭제:
    • ForceSynciCloudData와 DeleteiCloudData 함수는 iCloud 데이터의 동기화 및 삭제를 담당합니다.

 

Unity에서 iOS 네이티브 코드를 활용하여 iCloud 데이터 저장 기능을 구현하는 방법을 살펴보았습니다. 이와 같이 네이티브 코드를 연동하면, iOS 고유의 기능을 Unity 게임에 통합할 수 있습니다. iCloud를 통해 게임 데이터를 관리하면, 사용자는 여러 기기에서 동일한 데이터를 사용할 수 있어 보다 일관된 사용자 경험을 제공할 수 있습니다.