, , , ,

Java、Objective-C 傳送圖片到遊戲引擎

讓 Java、Objective-C 語言能夠將圖片轉為 Unity、Unreal 的教學,主要也是我自己研究了一段時間,相關的文件真的蠻少的。

Java、Objective-C 傳送圖片到遊戲引擎
Photo Unity, Unreal, Native : Choose Better Game Engine for Mobile Game Development (redappletech.com)

前言

我的工作是串接 iOS、Android 的原生功能 e.g. , IAP、Permission、AlertDialog ,來讓公司的遊戲專案可以不用去考慮平台的原生功能,專心的處理遊戲及商業邏輯。

功能需求

這一次的功能需求起因是遊戲專案需要讓玩家可以選擇頭像,但原先使用的 Unity 套件沒有繼續更新支援新版 Android 日漸嚴格的隱私權政策,所以就把這個 case 轉來我們團隊了 !


作法簡介

我的作法是將圖片先轉為 Byte Array 再轉為 base64 字串傳到引擎內再去處理。

處理順序

  1. Convert to byte array
  2. Encode to base64
  3. Send message to engine
  4. Engine base64 decode
  5. Convert to engine texture

引擎坑

Unity 支援 base 64 帶有 \n
Unreal 不支援 base64 帶有 \n

Objective-C

// 選擇照片的 Callback
-(void)onSelectPhotoSuccess:(UIImage*)choseImage
{
    // 壓縮值(%)
    CGFloat quality = 0.8;
    // Convert image to NSData
    NSData* data = UIImageJPEGRepresentation(choseImage, quality);
    [self sendPhotoDataToEngine: data];
}

// 傳送處理過的 data 給遊戲引擎
-(void)sendPhotoDataToEngine:(NSData*)photoData
{
    if (photoData != nil)
    {
        // no \n
        NSString* base64Str = [photoData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
        // default
        NSString* base64StrWithLine = [photoData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
        // Use your way to Engine
    }
}
SelectPhoto.m

Java

// 選擇照片的 Callback
private void onSelectPhotoSuccess(Bitmap bitmap)
{
    float quality = 80;
    
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.PNG, quality, out);
    sendPhotoDataToEngine(out.toByteArray());
}

// 傳送處理過的 data 給遊戲引擎
private void sendPhotoDataToEngine(byte[] data)
{
    String resultString = "";
    
    // Unity support Default
    resultString = Base64.encodeToString(data, Base64.DEFAULT);    
    // Unreal doesn't support DEFAULT
    resultString = Base64.encodeToString(data, Base64.NO_WARP);
    // Use your way to Engine
}
SelectPhoto.java

Unity

/// <summary>
/// 處理傳來的 base64 
/// </summary>
/// <param name="base64Str">圖片資訊</param>
private void ConvertBase64ToBytes(string base64Str)
{
    byte[] bytes = System.Convert.FromBase64String(base64Str);
    ConvertBytesToTexture(bytes);
}
/// <summary>
/// 轉換為 Texture
/// </summary>
/// <param name="photoByteArray">圖片byte array</param>
private void ConvertBytesToTexture(Byte[] photoByteArray)
{
    if (photoByteArray != null)
    {
        // 如果有需要,也可以把長寬從 Java、iOS 傳過來
        var photoTexture = new Texture2D(width, height);
        photoTexture.LoadImage(photoByteArray);
    }
}
SelectPhoto.cs

Unreal

// 略過相關的 C、Jni 類型轉換
void Sample::ConvertBase64ToTexture2D(FString base64Str)
{
    TArray<uint8> sourceData;
    FBase64::Decode(base64Str, sourceData);
    UTexture2D* outTexture = FImageUtils::ImportBufferAsTexture2D(sourceData);
}
SelectPhoto.cpp