블로그 이미지
Every unexpected event is a path to learning for you.

카테고리

분류 전체보기 (2737)
Unity3D (817)
Programming (474)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (228)
협업 (58)
3DS Max (3)
Game (12)
Utility (136)
Etc (96)
Link (32)
Portfolio (19)
Subject (90)
iOS,OSX (53)
Android (14)
Linux (5)
잉여 프로젝트 (2)
게임이야기 (3)
Memories (20)
Interest (38)
Thinking (38)
한글 (30)
PaperCraft (5)
Animation (408)
Wallpaper (2)
재테크 (18)
Exercise (3)
나만의 맛집 (3)
냥이 (10)
육아 (16)
Total
Today
Yesterday
04-26 17:51

[iOS14+ 대응 관련 FAN SDK 6.2 적용 시 구현 이슈 2가지]

Audience Network SDK(6.2) 최신 버전은 10월 26일에 릴리스되었습니다. 최신 버전에서 강조할 만한 중요한 요구 사항은 두 가지가 있습니다.

 

1. 미디에이션 사용과 무관하게 ‘setAdvertiserTrackingEnabled’ 플래그를 구현하여 데이터로 개인화된 광고를 게재하는지 알려야 합니다.

2.  추천된 SKAdNetwork ID를 Xcode 프로젝트의 Info.plist에 추가하여 광고주가 광고 캠페인의 성공을 측정하도록 합니다.


iOS14에 대응하기 위해 AN SDK 6.2 이상을 적용해야 되는데, iOS에서 FAN SDK 6.2는 위와 같은 2가지 필수 구현사항을 요구하고 있다.

 

현재 나는 Admob 미디에이션을 사용하고, Admob의 FAN 미디에이션 플러그인을 적용해놨는데,

미디에이션이라 하더라도 위 2가지는 적용해야 된다고 한다.

 

위 2가지를 어떻게 적용했는지 정리해 둔다.

 

(※ iOS 플랫폼 대응이니 Android에서는 작동 안하도록 해두자)

1.   ‘setAdvertiserTrackingEnabled’ (이하 ATE) flag 구현

1.1. 광고 추적 활성화

1.1.1. 미디에이션 미 사용 시(AN SDK 직접 적용)

     [링크] developers.facebook.com/docs/audience-network/guides/advertising-tracking-enabled

1.1.2. 미디에이션 사용 시

1.1.2.1. 미디에이션 사용 시에는 아래와 같이 직접 구현해서 사용하라고 설명이 적혀 있다.

          [참조] 미디에이션을 사용 중인 경우 setAdvertiserTrackingEnabled 플래그를 구현한 다음, 미디에이션 SDK를 초기화해야 Facebook에서 입찰 요청을 통해 이를 수신할 수 있습니다.

          ※ 나는 Unity를 사용하고, Admob 미디에이션(GoogleMobileAds)을 사용하기 때문에 유니티에 적용할 수 있는 방식으로 직접 구현이 필요하다.

1.1.2.2. (직접 구현하는 건 귀찮으니)아래 파일을 다운받고, 패키지를 실행해서 AdSettings.cs 파일만 프로젝트에 추가

          [다운로드] Audience Network SDK for Unity

1.1.2.3. Admob 제어 하는 곳에서 Admob 초기화 전에 아래 소스를 추가해서 셋팅해 주자.

         (1.1.2.2.의 파일을 추가하면 아래 소스 실행이 가능해진다.)

// iOS에서만 실행하도록 한다.
#if UNITY_IPHONE && !UNITY_EDITOR
// Set the flag as true 
AudienceNetwork.AdSettings.SetAdvertiserTrackingEnabled(true);
#endif

 

2.   SKAdNetwork IDs Xcode 프로젝트의 Info.plist 추가

2.1. SKAdNetwork ID를 발급받는다.

     [참조 링크] www.wisetracker.co.kr/wp-content/uploads/2020/09/iOS_14_update_guide.pdf

2.2. ID를 Inpo.plist에 추가한다. (아래 보이는 ID는 예시입니다.)

2.2.1. Inpo.Plist에 직접 추가하는 방법(developer.apple.com/documentation/storekit/skadnetwork/configuring_the_participating_apps)

 

※ 아래 2개 SKAdNetworkID는 페이스북 공용 ID이니, FAN을 붙이는거면 그대로 사용하면 된다.

    [참조링크] developers.facebook.com/docs/audience-network/guides/SKAdNetwork

<key>SKAdNetworkItems</key>
<array>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>v9wttpbfk9.skadnetwork</string>
    </dict>
    <dict>   
         <key>SKAdNetworkIdentifier</key>
         <string>n38lu8286q.skadnetwork</string>
    </dict>
</array>

 

2.2.2. Unity에서 PostProcessor로 추가하는 방법(추천)

namespace blueasa
{
    public class XcodeSettingsPostProcessor
    {

        [PostProcessBuild(444)]
        public static void OnPostprocessBuild(BuildTarget buildTarget, string pathToBuiltProject)
        {

            /// Stop processing if targe is NOT iOS
            if (buildTarget != BuildTarget.iOS)
                return;

            /// Initialize PbxProject
            var projectPath = pathToBuiltProject + "/Unity-iPhone.xcodeproj/project.pbxproj";
            PBXProject pbxProject = new PBXProject();
            pbxProject.ReadFromFile(projectPath);
            string targetGuid = pbxProject.TargetGuidByName("Unity-iPhone");

            /// Add string setting
            // SKAdNetwork IDs integration(for iOS14+)
            // https://blueasa.tistory.com/2482
            // https://blueasa.tistory.com/2493
            var arraySKAdNetworkItems = plist.root.CreateArray("SKAdNetworkItems");
            // for FAN
            // https://developers.facebook.com/docs/audience-network/guides/SKAdNetwork
            var dictSKAdNetworkIdentifier_FAN_1 = arraySKAdNetworkItems.AddDict();
            dictSKAdNetworkIdentifier_FAN_1.SetString("SKAdNetworkIdentifier", "v9wttpbfk9.skadnetwork"); // FAN 1
            var dictSKAdNetworkIdentifier_FAN_2 = arraySKAdNetworkItems.AddDict();
            dictSKAdNetworkIdentifier_FAN_2.SetString("SKAdNetworkIdentifier", "n38lu8286q.skadnetwork"); // FAN 2
            
            /// Apply editing settings to Info.plist
            plist.WriteToFile(plistPath);

        }
    }
}

 

 

[참조사이트]

developers.facebook.com/blog/post/2020/10/29/preparing-our-partners-ios-14-latest-guidance-on-skadnetwork/?locale=ko_KR

developers.google.com/admob/ios/mediation/facebook?hl=en#swift

 

[SKAdNetwork IDs 참조]

[Admob] developers.google.com/admob/ios/ios14#skadnetwork

[Unity] unityads.unity3d.com/help/ios/skadnetwork-ids?fbclid=IwAR3T6BWG6-SIdWipZaB-PEtUQhg1DAnU_kQ22iiSv4Z5Q6nItq2edtpIIkM

[Unity.xml] skan.mz.unity3d.com/v2/partner/skadnetworks.plist.xml?_ga=2.140049011.1591405619.1607905486-1813266944.1603773122

[Vungle] support.vungle.com/hc/en-us/articles/360002925791-Integrate-Vungle-SDK-for-iOS#3-add-the-%E2%80%9C-objc%E2%80%9D-linker-flag-0-9

[Vungle.xml] vungle.com/skadnetworkids.xml

[AppsFlyer 제공 리스트] docs.google.com/spreadsheets/d/e/2PACX-1vSqwIBW3FzbrXKqluDQ2hEec7zcvVrxQ02ivWsHnGQTvLMeFmHHjGz1R5TVy6_cqAIVh0pAy4Yud7Qx/pubhtml

반응형
Posted by blueasa
, |

Error: 

Finally solved the problem. Need to update CocoPods.sudo gem install cocoapods

 

sudo gem install cocoapods

 

 

[출처]

stackoverflow.com/questions/64623288/framework-not-found-usermessagingplatform-xcframework-in-react-native

 

framework not found UserMessagingPlatform.xcframework in react native

I update my react native project after I encountered an error in xcode there is no problem in android Error: My new package.json "@react-native-firebase/admob": "^7.6.10", "@

stackoverflow.com

 

반응형
Posted by blueasa
, |

원문 : Unity Application.persistentDataPath のパスは Android のバージョンと Write Access によって異なる。

Unity Application.persistentDataPath의 경로는 Android의 버전과 Write Access에 따라 달라짐

Android에서 Application.persistentDataPath가 돌려주는 값이 Write Access에 따라 달라지기에 조사해봤습니다.
Unity 5.3.6에서 돌려주는 경로에 사양변경이 있었으므로, Unity 5.3.6 이전 버전에서 작성한 애플리케이션을 Unity 5.3.6 이후로 버전업할 때 주의를 기울이지 않으면 데이터가 사라질 위험이 있습니다.
갖고 있는 Android기기와 Unity 4.7.2f1, 5.3.6f1에서 검증했습니다.

Application.persistentDataPath

지속되는 데이터 디렉토리 경로.
세이브 데이터 등 유저 데이터를 저장하는 장소.
https://docs.unity3d.com/kr/current/ScriptReference/Application-persistentDataPath.html

Player Settings / Write Access

Internal Only로 지정해도 Application.persistentDataPath이 개발환경과 실제환경에서 돌려주는 값이 다를 수 있으므로 주의가 필요합니다!
외부 저장소라면 특별히 권한을 요구하지 않고 읽어들일 수 있으므로 디버그하기 쉽기 때문일지도?

External (SDCard)로 설정하면, SD 카드같은 외부 저장소에 대한 쓰기 접근을 가능하게 합니다. 개발 빌드(Development Build)에서는 자동적으로 켜집니다. https://docs.unity3d.com/kr/current/Manual/class-PlayerSettingsAndroid.html

External Storage

외부 저장소라고 불리는 영역이지만 SD 카드가 아니라 빼낼 수 없게 내장된 저장소를 참조하는 기기도 있음.
Android 4.4 이후에는 권한을 요구하지 않고 외부 저장소에 읽고 쓰기가 가능.

Windows PC를 예로 들면
오래된 Android 기기
C드라이브: 내장 드라이브 (Android 내부 저장소)
D드라이브: USB로 접속된 외장 하드디스크 (Android 외부 저장소)
최신 Android 기기
C드라이브: 내장 드라이브 파티션 0 (Android 내부 저장소)
D드라이브: 내장 드라이브 파티션 1 (Android 외부 저장소)
E드라이브: USB로 접속된 외장 하드디스크 (Android 외부 저장소)

모든 Android 호환 기기는 파일을 저장하는 데 사용할 수 있는 공유된 "외부 저장소"를 지원합니다. 해당 저장소는 제거할 수 있는 저장소 미디어(예: SD 카드) 또는 (제거할 수 없는) 내부 저장소일 수 있습니다.
https://developer.android.com/guide/topics/data/data-storage.html#filesExternal

Android 4.4 이상에서 앱 전용 디렉터리 파일 읽기 또는 쓰기는 READ_EXTERNAL_STORAGE 또는 WRITE_EXTERNAL_STORAGE 권한이 필요하지 않습니다.
https://developer.android.com/guide/topics/data/data-storage.html#AccessingExtFiles

일부 기기는 이동식 저장 장치 없이도 영구 저장소 공간을 "내부" 그리고 "외부" 파티션으로 나누어 항상 두 개의 저장소 공간을 제공하며, API의 동작은 외부 저장소의 이동식 유무에 상관없이 일관적입니다.
https://developer.android.com/training/basics/data-storage/files.html#InternalVsExternalStorage

Unity 5.3.6에서의 사양변경

Android: Application.temporaryCachePath and Application.persistentDataPath always return external paths starting KITKAT. (789870) https://unity3d.com/kr/unity/whats-new/unity-5.3.6

KITKAT은 Android 4.4의 코드네임. Android 4.4 이후에는 Write Access의 값에 관계없이 외부 저장소의 경로를 돌려주도록 사양변경. Android 4.4 이후 권한을 요구하지 않고 읽고 쓰기가 가능하게 되었기 때문일 것.

Player Settings / Write Access 별 Application.persistentDataPath의 값

Write Access: Internal Only

Unity 4.7.2

AndroidPath실체

4.1.2 (200SH) /data/data/{package name}/files/ 내부 저장소
4.2.2 (SO-02F) /data/data/{package name}/files/ 내부 저장소
5.0.2 (HTV31) /data/data/{package name}/files/ 내부 저장소
6.0.1 (SCV31) /data/user/0/{package name}/files/ -> /data/data/{package name}/files/ 내부 저장소

Unity 5.3.6

AndroidPath실체

4.1.2 (200SH) /data/data/{package name}/files/ 외부 저장소
4.2.2 (SO-02F) /data/data/{package name}/files/ 외부 저장소
5.0.2 (HTV31) /storage/emulated/0/Android/data/{package name}/files/ 외부 저장소
6.0.1 (SCV31) /storage/emulated/0/Android/data/{package name}/files/ 외부 저장소

Write Access: External (SDCard)

Unity 4.7.2

AndroidPath실체

4.1.2 (200SH) /storage/sdcard0/Android/data/{package name}/files/ SD 카드
4.2.2 (SO-02F) /storage/emulated/0/Android/data/{package name}/files/ 외부 저장소
5.0.2 (HTV31) /storage/emulated/0/Android/data/{package name}/files/ 외부 저장소
6.0.1 (SCV31) (Permissions Storage: ALLOW) /storage/emulated/0/Android/data/{package name}/files/ 외부 저장소
6.0.1 (SCV31) (Permissions Storage: DENY) /data/user/0/{package name}/files/ -> /data/data/{package name}/files/ 내부 저장소

Unity 5.3.6

AndroidPath실체

4.1.2 (200SH) /storage/sdcard0/Android/data/{package name}/files/ SD 카드
4.2.2 (SO-02F) /storage/emulated/0/Android/data/{package name}/files/ 외부 저장소
5.0.2 (HTV31) /storage/emulated/0/Android/data/{package name}/files/ 외부 저장소
6.0.1 (SCV31) (Permissions Storage: ALLOW) /storage/emulated/0/Android/data/{package name}/files/ 외부 저장소
6.0.1 (SCV31) (Permissions Storage: DENY) /storage/emulated/0/Android/data/{package name}/files/ 외부 저장소

결과

Write Access: External (SDCard)로 지정하면 androidmanifest.xml에 외부 저장소에 읽고 쓰기 권한 요구가 추가됩니다.
WRITE_EXTERNAL_STORAGE 권한으로 읽고 쓰기도 가능.

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

WRITE_EXTERNAL_STORAGE를 추가한 경우, Android 6 이후에는 Permissions Storage의 물음에서 ALLOW를 선택할 때까지는 기동할 때마다 물어봄.
ALLOW를 선택한 후에도 Application의 설정에서 Permissions Storage 허가의 변경은 가능.
4.1.2 (200SH): Write Access: External (SDCard) 만이 SD 카드의 경로를 돌려줌.
SD 카드를 뽑았을 경우에는 Internal Only와 같은 경로를 돌려줌.
그 외에는 내부 저장소를 참조.
Unity 4.7.2 Android 6.0.1는 Permissions Storage의 허가 유무로 돌려주는 경로가 달라짐.
Unity 5.3.6 Android 4.4 이후는 Permissions Storage의 허가 유무와 상관없이 돌려주는 값이 같음.

Unity 4.7.2에서 작성한 애플리케이션에서 Application.persistentDataPath에 저장한 데이터를 Unity 5.3.6에서 작성한 애플리케이션에서 덮어씌웠을 경우 읽어들일 수 있을까?

internal-storage: /data/data/{package name}/files/
external-storage: /storage/emulated/0/Android/data/{package name}/files/

Android 4.1.2 (200SH)

Unity 4.7.2 Write AccessUnity 5.3.6 Write Access읽기 가능?거동

Internal Only Internal Only
Internal Only External (SDCard)
External (SDCard) Internal Only UnauthorizedAccessException: Access to the path "/storage/sdcard0/Android/data/{package name}/files/{file name}" is denied. external-storage를 internal-storage에 복사하려고 해서 실패?
External (SDCard) External (SDCard)

Android 4.2.2 (SO-02F)

Unity 4.7.2 Write AccessUnity 5.3.6 Write Access읽기 가능?거동

Internal Only Internal Only
Internal Only External (SDCard)
External (SDCard) Internal Only UnauthorizedAccessException: Access to the path "/storage/sdcard0/Android/data/{package name}/files/{file name}" is denied. external-storage를 internal-storage에 복사하려고 해서 실패?
External (SDCard) External (SDCard)

Android 5.0.2 (HTV31)

Unity 4.7.2 Write AccessUnity 5.3.6 Write Access읽기 가능?거동

Internal Only Internal Only
Internal Only External (SDCard)
External (SDCard) Internal Only UnauthorizedAccessException: Access to the path "/{file name}" is denied. external-storage를 internal-storage에 복사하려고 해서 실패?
External (SDCard) External (SDCard)

Android 6.0.1 (SCV31)

Unity 4.7.2 Write AccessUnity 5.3.6 Write Access읽기 가능?거동

Internal Only Internal Only internal-storage를 external-storage에 복사
Internal Only External (Permissions Storage: ALLOW)
Internal Only External (Permissions Storage: DENY) internal-storage를 external-storage에 복사
External (Permissions Storage: ALLOW) Internal Only 같은 경로
External (Permissions Storage: ALLOW) External (Permissions Storage: ALLOW) 같은 경로
External (Permissions Storage: ALLOW) External (Permissions Storage: DENY) 같은 경로
External (Permissions Storage: DENY) Internal Only internal-storage를 external-storage에 복사
External (Permissions Storage: DENY) External (Permissions Storage: ALLOW)
External (Permissions Storage: DENY) External (Permissions Storage: DENY) internal-storage를 external-storage에 복사

결과

Internal Only, External (Permissions Storage: DENY)일 때에는 internal-storage를 external-storage에 복사한 후에 읽어들이도록 되어 있음.
external-storage로 변경해도 internal-storage는 복사 시점 그대로 변경은 되지 않음.

정리

Internal Only -> External (SDCard)로의 변경은 데이터를 이어받지 못하는 경우가 있음. 그 경우, 수동으로 /data/data/{package name}/files/ 를 복사하는 등의 대응이 필요.
External (SDCard) -> Internal Only로의 변경은 오래된 Android 기기기에서 정상으로 처리되지 않을 가능성이 있음.
Android 6 이후에는 Unity 4.7.2의 Write Access가 어느쪽이든 Unity 5.3.6의 Write Access: Internal Only로 해두면 데이터를 이어받아 읽고 쓰기가 가능.

 

 

[출처] gist.github.com/overworks/541fcb519bc23cd14cf622c2baa28d3b

 

유니티와 안드로이드 버전에 따른 Application.persistentDataPath의 경로 정리

유니티와 안드로이드 버전에 따른 Application.persistentDataPath의 경로 정리 - Unity-Android-persitentDataPath.md

gist.github.com

 

반응형
Posted by blueasa
, |

[추가] Android / iOS 방식이 달라서 플랫폼에 따라 Two Letter ISO 받는 방식을 다르게 적용

 

    /// <summary>
    /// Two Letter ISO Language
    /// [참조] https://lonewolfonline.net/list-net-culture-country-codes/
    /// [참조] https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
    /// </summary>
    /// <returns></returns>
    public static string GetTwoLetterISOLanguage()
    {
        string strCurrentCultureName = "en";
#if UNITY_EDITOR
        strCurrentCultureName = "en";
#elif UNITY_ANDROID
        strCurrentCultureName = GetTwoLetterISOLanguage_Android();
#elif UNITY_IOS || UNITY_IPHONE
        strCurrentCultureName = GetTwoLetterISOLanguage_iOS();
#endif
        return strCurrentCultureName;
    }

    public static string GetTwoLetterISOLanguage_iOS()
    {
        string strTwoLetterISOLanguageName = System.Threading.Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName;
        Debug.LogFormat("[GetCurrentCultureName_iOS] {0}", strTwoLetterISOLanguageName);
        return strTwoLetterISOLanguageName;
    }

    // returns "en" / "de" / "hi" / "th" / "ar" / ...
    public static string GetTwoLetterISOLanguage_Android()
    {
#if !UNITY_EDITOR && UNITY_ANDROID
        try
        {
            var locale = new AndroidJavaClass("java.util.Locale");
            var localeInst = locale.CallStatic<AndroidJavaObject>("getDefault");
            var name = localeInst.Call<string>("getLanguage");
            Debug.LogFormat("[getLanguage] {0}", name);
            return name;
        }
        catch (System.Exception e)
        {
            return "Error";
        }
#else
        return "Not supported";
#endif
    }

    // returns "eng" / "deu" / "hin" / ...
    public static string GetThreeLetterISOLanguage_Android()
    {
#if !UNITY_EDITOR && UNITY_ANDROID
        try
        {
            var locale = new AndroidJavaClass("java.util.Locale");
            var localeInst = locale.CallStatic<AndroidJavaObject>("getDefault");
            var name = localeInst.Call<string>("getISO3Language");
            Debug.LogFormat("[getISO3Language] {0}", name);
            return name;
        }
        catch (System.Exception e)
        {
            return "Error";
        }
#else
        return "Not supported";
#endif
    }

[출처]

answers.unity.com/questions/729801/using-applicationsystemlanguage-returns-unknown.html?_ga=2.105896064.227436567.1600081424-730033693.1580204381

 

Using Application.systemLanguage returns Unknown - Unity Answers

 

answers.unity.com

 

 

[참조]

You should also be able to use .NET to get the current culture instead:

using System;
using System.Globalization;
using System.Threading;

CultureInfo myCulture = Thread.CurrentThread.CurrentCulture;


// You can then use all these member variables
myCulture.DisplayName
myCulture.EnglishName
myCulture.Name (e.g. es-ES / en-GB)
myCulture.Parent (e.g. es / en)
myCulture.ThreeLetterISOLanguageName (e.g. spa/eng/hin)
myCulture.TwoLetterISOLanguageName (e.g. es/en/hi)

 

Here's a selection of the Indian 3 and 2 letter ISO codes (see attached jpg)

 

[출처] forum.unity.com/threads/automatically-set-hindi-language.624973/

 

Automatically set Hindi language

As you all know it's possible to use SystemLanguage to detect the default language of the device running the game. When my game opens, i use it to...

forum.unity.com

 

반응형
Posted by blueasa
, |

Problems that Thai is [?] In [Unity] iOS13

phenomenon

If when you try to multi-lingual in Unity Oke Select the default font asset referred to as "Arial", so you use Yoshinani the system font, but I did not have a problem until now, generating a phenomenon that garbled in iOS13 are you with.

Screenshot is iOS13.2.1 (iPhone8). In the middle of the screen [?] [?] [?] [?] And is in a place that is garbled applicable.
VIEW IMAGE

Investigation

Even Unity of the Issue have been reported, Armenian in addition to Thai, it seems to become garbled in Georgian.

For more details, it might be good to get a look at the people of Issue.

It summarizes the results of actually examined.

  • If you set the Thai fonts will be displayed without any problems.

    Screenshot is iOS13.2.1 (iPhone8). VIEW IMAGE
  • In iOS12.4.1 it will be as normally displays the Thai below.

    Screenshot is iOS12.4.1 (iPhoneXR). VIEW IMAGE
  • In Android10 it will be as normally displays the Thai below.
  • Unity version was also confirmed at 2018.3 and 2019.1, but it was the same result.

The method and the iOS language settings to use the system font to fall back a font to another tried such as the Thai, but it did not change.

temporary solution

Since it has published an app that was the Thai correspondence, it does not need to wait for the renovation of Unity.

Thinking of correspondence has the following procedure.

  1. Put the Thai font, eliminate garbled
  2. Raise Unity and is After the corresponding version

Since there is a free font Fortunately Thai, and the garbled solve with it.

Since a little thinner than the default font, it may not afford the alternative as long as there is a commitment.

I learned for the first time a license that GPL font exception. I did not know what I do a credit notation, it was for the time being added. If you have somebody who is familiar wait for information.

Font size was 480KB. I thought one more font size increases, but I have put in a not too nervous and if this much. But does not recommend because as far as possible towards the size of the app is small, I think good for the user.

Something like the following, we have set the font in the timing of switching to Thai.

text.font = Resources.Load<Font> ("Fonts/THSarabunNew/THSarabunNew");

It was also good as switched fallback, but because the provisional support of easy-to-understand on the code TODOhas been switched by the code this time on the grounds that I wanted to write a.

Summary

Because of what is in the Unity side, but have no idea what is in the iOS side, is a story that has survived for the time being in the provisional support.

We look forward to information If you know the other way.

reference

Unity Issue Tracker - [iOS 13.0] Some languages symbols are replaced with a [?] marks
https://issuetracker.unity3d.com/issues/ios-13-dot-0-all-thai-symbols-are-replaced-with-a-marks

Font - Unity manual
https://docs.unity3d.com/ja/2018.1/Manual/class-Font.html

[Unity] want to use a font that is installed on the OS in the Unity - Terra sur-blog
http://tsubakit1.hateblo.jp/entry/2018/05/30/234314

Public institutions of Thailand to issue "Thai font free" | Thailand favor
https://thaion.net/thai-font-sipa

Fxnt. Khxm »Fxnt Sarbrrn Prabprung Run Him" Sarabun New "
https://www.f0nt.com/release/th-sarabun-new/

GPL font exception - Wikipedia
Https://Ja.Wikipedia.Org/wiki/GPL font exception

 

 

[참조1] issuetracker.unity3d.com/issues/ios-13-dot-0-all-thai-symbols-are-replaced-with-a-marks

 

Unity IssueTracker - [iOS 13.0] Some languages symbols are replaced with a [?] marks

To reproduce: 1. Download attached "Thai Font Issue Example.zip" project and open in Unity 2. Build for iOS 3. Deploy the Xcode proj...

issuetracker.unity3d.com

 

[참조2] qiita.com/canecco/items/50b27ba214926e690ab0

 

【Unity】iOS13でタイ語が[?]になる問題 - Qiita

現象 Unityで多言語に対応しようとすると「Arial」というデフォルトのフォントアセットを選択しておけば、システムフォントをよしなに使ってくれるので今まで問題がなかったのですが、iOS13

qiita.com

 

[출처] titanwolf.org/Network/Articles/Article?AID=0f5127d9-dcac-4e95-8c1b-a97b6bc9a5c7#gsc.tab=0

 

Problems that Thai is [?] In [Unity] iOS13(Others-Community)

 

titanwolf.org

 

반응형
Posted by blueasa
, |

Unity 를 이용해 그림판 같은 기능을 구현하는 중에 겹치는 이미지의 테두리가 흰색으로 나타나는 현상이 발생 하였다.

 

 

위 화면은 Canvas 에 검정색 원 Image 여러개가 겹쳐 있고 이를 RenderTexture 를 통해 RawImage 로 출력하고 있는 예제 이다. 사용한 이미지는 아래와 같은 설정이 되어 있다.

 

 

Scene 화면을 통해 RawImage 의 테두리 부분을 확대해 보면 다음과 같이 투명하게 처리가 되고 있는 것이 보였다.

 

 

RenderTexture 로 그려주던 Canvas 를 메인으로 돌려보면 아래와 같이 의도 했던 대로 출력이 된다.

 

 

 

1. 이미지 테두리 부분의 픽셀이 기존 픽셀과 겹쳐지면서 혹은 덮어 쓰면서 해당 픽셀을 투명하게 바꾸고 있다.

2. RenderTexture 로 변환되 RawImage 로 출력하는 과정에서 테두리 부분이 투명해 지는 현상이 일어난다.

 

1. 이미지가 문제가 있다

2. RenderTexture 가 잘못 그려주고 있다

3. RawImage 가 잘못 출력하고 있다.

 

이미지에 육안으로 확인 되지 않는 투명한(?) 부분이 있다고 가정하고 이를 보정하는 것은 어떨까? 로 시작해 쉐이더를 추가한 Material 을 추가해 보았다.

그 결과 이미지에 Sprites/Default 쉐이더를 사용하는 Material 을 사용하니 간섭 현상이 사라졌다. Material 이 추가되지 않은 이미지의 기본 쉐이더는 UI/Default 쉐이더인데 Sprites/Default 쉐이더와의 차이가 이런 현상을 만드는 것 같다.

 

UI/Default 쉐이더 코드와 Sprite/Default 쉐이더 코드를 비교하며 테스트 했더니 다음과 같이 수정해 문제 해결이 가능했다.

- UI/Default 쉐이더의  Blend SrcAlpha OneMinusSrcAlpha 값을 Blend One OneMinusSrcAlpha 값으로 변경

Blend - 투명 오브젝트를 만드는데 사용합니다.

SrcAlpha - 스테이지 값을 소스 알파 값으로 곱합니다.

One - 1값입니다. 소스 또는 대상 컬러가 완전히 표시되도록 하려면 이 값을 사용합니다.

OneMinusSrcAlpha - 스테이지 값을 (1 - 소스 알파)로 곱합니다.

 

https://docs.unity3d.com/kr/current/Manual/SL-Blend.html

 

ShaderLab: 블렌딩 - Unity 매뉴얼

블렌딩은 투명 오브젝트를 만드는 데 사용됩니다.

docs.unity3d.com

 

정리하자면 소스 알파 값이란 새로 그려진 이미지의 알파 값이고 스테이지 값은 기존 화면에 그려져 있는 값인데 이둘을 곱하면 새로 그려진 이미지의 알파값을 따라가기 때문에 이를 1값으로 변경해 새로 그려진 이미지의 알파 값을 따라가지 않게 수정 함으로써 해결 됬다고 생각한다.

 

위와 같은 문제 때문이 었다면 RenderTexture 를 통하지 않고 직접 그리는 이미지에서도 해당 상황이 재현되야 하지 않을까? 하지만 직접 그리는 이미지에서는 해당 이슈가 발생하지 않는다. 

 

RenderTexture 설정이 잘못되어 출력이 잘못 되고 있는 것은 아닐까?

RenderTexture 의 Color Format 설정을 바꿔보니 다음 두 경우에 원했던 형태의 출력이 되는 것을 확인 하였다.

RGB565 - 모든 그래픽 카드를 지원하지 않는 16 bit 텍스쳐 포멧

RGB111110Float - 모든 그래픽 카드를 지원하지 않는 포멧

https://docs.unity3d.com/ScriptReference/RenderTextureFormat.html

 

Unity - Scripting API: RenderTextureFormat

You've told us this page needs code samples. If you'd like to help us further, you could provide a code sample, or tell us about what kind of code sample you'd like to see: You've told us there are code samples on this page which don't work. If you know ho

docs.unity3d.com

보통의 경우 Default 값인 ARGB32 를 사용할 텐데 ... 이 방법은 아닌 것 같다.

 

RawImage 에서 출력 할 때 문제가 생기는 것은 아닐까?

https://forum.unity.com/threads/using-render-textures-on-a-ugui-image-panel-or-button.272332/

 

Using Render Textures on a uGUI Image, Panel or Button?

Hello! I'm trying to put my minimap into the uGUI system. Is it possible to get a Render Texture working with these? I've got my render texture...

forum.unity.com

관련 이슈로 토론한 흔적이 보인다. 여기서 찾은 방법은 UI/Default 쉐이더에서 알파 클립을 제거한 커스텀 쉐이더를 RawImage 에 붙여 해결한 것이다. 쉐이더 코드를 보면 강제로 알파 값을 1로 만들어 주는 역활을 하고 있다.

UI-Default-No-Alpha.shader
0.00MB

 

여지껏 시도해 봤던 방법 중에 커스텀 쉐이더를 RawImage 에 적용하는 방법이 제일 괜찮아 보여 일단은 이것으로 해결. 왜 저러는 건지에 대해서는 좀더 찾아봐야 될듯...



출처: https://ukprog.tistory.com/56 [Vader87]

 

[Unity3D] RenderTexture RawImage 출력 이슈

Unity 를 이용해 그림판 같은 기능을 구현하는 중에 겹치는 이미지의 테두리가 흰색으로 나타나는 현상이 발생 하였다. 위 화면은 Canvas 에 검정색 원 Image 여러개가 겹쳐 있고 이를 RenderTexture 를 ��

ukprog.tistory.com

 

반응형
Posted by blueasa
, |

유니티 데이터 통신 압축용으로 사용 중.

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using ICSharpCode.SharpZipLib.BZip2;

public class ZipHelper
{
    public static byte[] Zip(byte[] data)
    {
        return Zip(data, 0, data.Length);
    }

    public static byte[] Unzip(byte[] data)
    {
        return Unzip(data, 0, data.Length);
    }

    public static byte[] Zip(byte[] data, int offset, int size)
    {
        MemoryStream inStream = new MemoryStream(data, offset, size);
        MemoryStream outStream = new MemoryStream();
        BZip2.Compress(inStream, outStream, false, 3);

        byte[] result = outStream.ToArray();
        inStream.Close();
        outStream.Close();

        return result;
    }

    public static byte[] Unzip(byte[] data, int offset, int size)
    {
        MemoryStream inStream = new MemoryStream(data, offset, size);
        MemoryStream outStream = new MemoryStream();
        BZip2.Decompress(inStream, outStream, false);

        byte[] result = outStream.ToArray();
        inStream.Close();
        outStream.Close();

        return result;
    }
}

// 예제
//class Program
//{
//    static void Main(string[] args)
//    {

//        byte[] array = new byte[1000];
//        for (int i = 0; i < array.Length; i++)
//        {
//            array[i] = (byte)(i % 255);
//        }
//        byte[] compress = ZipHelper.Zip(array);
//        byte[] decompress = ZipHelper.Unzip(array);


//    }

//}

 

 

[SharpZip dll 다운로드] https://www.nuget.org/packages/SharpZipLib/

 

[참조] https://nahyungmin.tistory.com/38

반응형
Posted by blueasa
, |
using System;
using Mono.Data.Sqlite;

public class Example
{

    static void Main() 
    {
        string cs = "URI=file:test.db";        
        
        using (SqliteConnection con = new SqliteConnection(cs)) 
        {
            con.Open();

            using(SqliteTransaction tr = con.BeginTransaction())
            {
                using (SqliteCommand cmd = con.CreateCommand())
                {

                    cmd.Transaction = tr;
                    cmd.CommandText = "DROP TABLE IF EXISTS Friends";
                    cmd.ExecuteNonQuery();
                    cmd.CommandText = @"CREATE TABLE Friends(Id INTEGER PRIMARY KEY, 
                                        Name TEXT)";
                    cmd.ExecuteNonQuery();
                    cmd.CommandText = "INSERT INTO Friends(Name) VALUES ('Tom')";
                    cmd.ExecuteNonQuery();
                    cmd.CommandText = "INSERT INTO Friends(Name) VALUES ('Rebecca')";
                    cmd.ExecuteNonQuery();
                    cmd.CommandText = "INSERT INTO Friends(Name) VALUES ('Jim')";
                    cmd.ExecuteNonQuery();
                    cmd.CommandText = "INSERT INTO Friends(Name) VALUES ('Robert')";
                    cmd.ExecuteNonQuery();
                    cmd.CommandText = "INSERT INTO Friends(Name) VALUES ('Julian')";
                    cmd.ExecuteNonQuery();
                    cmd.CommandText = "INSERT INTO Friends(Name) VALUES ('Jane')";
                    cmd.ExecuteNonQuery();
                }

                tr.Commit();
            }

            con.Close();
        }
    }
}

 


출처: https://unsigned.tistory.com/entry/Sqlite-Insert-속도-문제시 [공부하자 공부공부]

 

Sqlite Insert 속도 문제시

using System; using Mono.Data.Sqlite; public class Example { static void Main() { string cs = "URI=file:test.db"; using (SqliteConnection con = new SqliteConnection(cs)) { con.Open(); using(SqliteTr..

unsigned.tistory.com

 

 

반응형
Posted by blueasa
, |

[참조] https://mentum.tistory.com/150

 

유니티 퍼미션 체크 적용기. (Unity Permission Check) 2019.11.14 재작성.

2019.11.14 재작성. 유니티 안드로이드에서 스크린샷을 저장하기 위해 권한 부분을 다시 작성해야해서 하는 김에 이 글도 재작성 하였다. 2019/11/14 - [Unity/프로그래밍] - 유니티 안드로이드 스크린샷

mentum.tistory.com

 

 

참조 사이트에 포스팅 된 내용을 참고해서 나한테 맞게 만듬.

(Unity2018 / 저장공간(선택) 권한만 필요)

 

using System;
using UnityEngine;
using System.Collections;
using UnityEngine.SceneManagement;
using UnityEngine.Assertions;
using UnityEngine.Android;

public class UICheckPermissionManagerSGT : MonoBehaviour
{
    public GameObject m_panelCheckPermission = null;
    public GameObject m_panelDeniedConfirm = null;

    private bool m_bOnCheckPermission = false;


    void Start()
    {
        Debug.Log("[Scene] CheckPermission");

        InitCheckPermission();
        CheckCountryCode_KR();
    }

    void InitCheckPermission()
    {
        m_bOnCheckPermission = false;

        ActivateCheckPermission(false);
        ActivateDeniedConfirm(false);

    }

    void CheckCountryCode_KR()
    {
        // GetIP가 한국인지 체크하는 외부 함수
        SGT.Global.CheckCountryCode_KR(ConfirmCountryCode_KR);
    }

    void ConfirmCountryCode_KR(bool _bIsCountryCode_KR)
    {
        if (true == _bIsCountryCode_KR)
        {
            // 한국 : Permission 확인
            DoCheckPermission();

            //CallPermission();
        }
        else
        {
            // No 한국 : Next Scene으로 이동
            GoToNextScene();
        }
    }

    void DoCheckPermission()
    {
        // 저장공간(Write) 권한 체크(선택 권한)
        if (Permission.HasUserAuthorizedPermission(Permission.ExternalStorageWrite) == false)
        {
            // 지정된 권한이 없으면 CheckPermission UI 활성화
            ActivateCheckPermission(true);
        }
        else
        {
            GoToNextScene();
        }
    }

    IEnumerator CheckPermissionCoroutine()
    {
        m_bOnCheckPermission = true;

        yield return new WaitForEndOfFrame();

        // 저장공간(Write) 권한 체크(선택 권한)
        if (Permission.HasUserAuthorizedPermission(Permission.ExternalStorageWrite) == false)
        {
            // 권한 요청
            Permission.RequestUserPermission(Permission.ExternalStorageWrite);

            yield return new WaitForSeconds(0.2f); // 0.2초의 딜레이 후 focus를 체크하자.
            yield return new WaitUntil(() => Application.isFocused == true);

            if (Permission.HasUserAuthorizedPermission(Permission.ExternalStorageWrite) == false)
            {
                // 권한 거절하면 안내 팝업
                OnEventDenied();
                yield break;
            }
        }

        // 권한이 있으면 다음 Scene으로 이동
        GoToNextScene();

        m_bOnCheckPermission = false;
    }


    // 해당 앱의 설정창을 호출한다.(권한 설정할 수 있도록 유도)
    // https://forum.unity.com/threads/redirect-to-app-settings.461140/
    private void OpenAppSetting()
    {
        try
        {
#if UNITY_ANDROID
            using (var unityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
            using (AndroidJavaObject currentActivityObject = unityClass.GetStatic<AndroidJavaObject>("currentActivity"))
            {
                string packageName = currentActivityObject.Call<string>("getPackageName");

                using (var uriClass = new AndroidJavaClass("android.net.Uri"))
                using (AndroidJavaObject uriObject = uriClass.CallStatic<AndroidJavaObject>("fromParts", "package", packageName, null))
                using (var intentObject = new AndroidJavaObject("android.content.Intent", "android.settings.APPLICATION_DETAILS_SETTINGS", uriObject))
                {
                    intentObject.Call<AndroidJavaObject>("addCategory", "android.intent.category.DEFAULT");
                    intentObject.Call<AndroidJavaObject>("setFlags", 0x10000000);
                    currentActivityObject.Call("startActivity", intentObject);
                }
            }
#endif
        }
        catch (Exception ex)
        {
            Debug.LogException(ex);
        }
    }

    void ActivateDeniedConfirm(bool _bActive)
    {
        GgUtil.Activate(m_panelDeniedConfirm, _bActive);
    }

    void ActivateCheckPermission(bool _bActive)
    {
        GgUtil.Activate(m_panelCheckPermission, _bActive);
    }

    void GoToNextScene()
    {
        // 패치씬으로 이동
        SGT.Scene.RunCheckPermissionToPatch();
    }

    //////////////////////////////////////////////////////////////////////////
    // Event
    //////////////////////////////////////////////////////////////////////////

    void OnEventCheckPermission()
    {
        if (true == m_bOnCheckPermission)
            return;

        StopCoroutine("CheckPermissionCoroutine");
        StartCoroutine("CheckPermissionCoroutine");
    }

    void OnEventDenied()
    {
        ActivateDeniedConfirm(true);
    }

    void OnEventDeniedConfirm()
    {
        // 저장공간은 선택권한이라 권한요청 거절해도 게임 진행
        GoToNextScene();
    }

    //////////////////////////////////////////////////////////////////////////
    // UI Event
    //////////////////////////////////////////////////////////////////////////

    // 권한 동의 버튼
    public void OnUIEventCheckPermission()
    {
        if (SGT.Global.bPreventDoubleClick)
            return;

        SGT.Global.PreventDoubleClick();

        OnEventCheckPermission();
    }

    // 거절 확인
    public void OnUIEventDeniedConfirm()
    {
        OnEventDeniedConfirm();
    }

    // 권한 설정 열기
    public void OnUIEventOpenAppSetting()
    {
        OpenAppSetting();
    }
}

 

반응형
Posted by blueasa
, |

[추가]

- 상대경로 기준 : 프로젝트 폴더

 

프로젝트 하위 폴더

프로젝트 하위에 위와 같이 Keystore 폴더 아래 debug.keystore 파일이 있을 때 상대경로는 아래와 같다.

[상대경로] ./Keysotre/debug.keystore

 

----------------------------------------------------------------------------------------------------------

유니티의 안드로이드 빌드 환경을 설정에서 키스토어 파일을 등록할 때, 일반적으로 Browe Keystore 버튼으로 파일을 등록하게 되면 위 사진과 같이 절대경로가 설정된다.

 

자동 빌드 환경이나, 서로 다른 빌드 머신에서 빌드하고자 할 때 굉장히 짜증나는 부분이며 제대로된 해결 방법은 없고 편법을 사용해야 하는 것을 보인다.

 

유니티 상단 메뉴 -> Edit -> Project Settings -> Editor -> Asset Serialization

값을 Force Text 로 변경한다.

이 작업은 다른 설정 또는 .unity 파일도 모두 변경합니다.

 

프로젝트 경로 -> ProjectSettings 폴더 -> ProjectSettings.asset 을 열면 텍스트로 변환되어 있다. 이중 AndroidKeystoreName 을 검색하여 절대 경로를 상대 경로로 변경한다.

 

유니티를 다시 실행시켜 결과를 확인한다.

 

 

빌드 머신에서 실행해 결과를 확인한다.



출처: https://pjc0247.tistory.com/44 [pjc0247]

 

[Unity] Android keystore 경로 상대경로로 지정하기

유니티의 안드로이드 빌드 환경을 설정에서 키스토어 파일을 등록할 때, 일반적으로 Browe Keystore 버튼으로 파일을 등록하게 되면 위 사진과 같이 절대경로가 설정된다. 자동 빌드 환경이나, 서로

pjc0247.tistory.com

 

반응형
Posted by blueasa
, |