레이블이 Unity인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Unity인 게시물을 표시합니다. 모든 게시물 표시

2020년 7월 10일 금요일

TextMesh Pro의 italic 수치 조절하는 방법

유니티 포럼 링크



특정 텍스트만 조절할 수 없고 폰트 전체의 이텔릭 수치만 조절 가능.

 <i angle=30> 이렇게 Rich Text 도 된다고 하는데 이건 2019부터...

2020년 4월 13일 월요일

구글, 애플은 ₩, 원스토어는 ₩. 원 표시가 다르다.

원스토어 출시 준비를 하면서 기존 판매 상품들들 점검하고 있었는데 원스토어로 빌드했을 때 상품 가격의 원(₩) 표시가 출력되지 않았다. 로그를 출력했을때는 분명 문제 없었는데 실제 게임에서는 출력되지 않아서 더 큰 문제라고 생각했다.

상품 가격을 표시하기 위해 유니코드 상의 ISO 기반 통화 기호와 알파벳, 숫자들을 모아서 NotoSans 기반으로 폰트 아틀라스를 하나 만들고, TextMeshProUGUI 를 이용해 출력하고 있었는데, 혹시나 해서 원 표시의 유니코드를 출력해 보니 구글, 애플에서 가격을 받아올 때 쓰는 원 표시와 원스토어에서 받아오는 원 표시가 달랐다. 나무위키 참고

다행이라는 생각으로 전각 반각 원 표시를 다 추가해서 TextMeshPro 폰트롤 새로 만들었는데 NotoSans 폰트에는 U+FFE6 원 표시가 없었다.....(나눔고딕에는 있다)

급한대로 가격 string에서 U+FFE6를 U+20A9로 replace 해서 사용중이다.

2020년 2월 6일 목요일

mesh.vertices is too small. the supplied vertex array has less vertices than are referenced by the triangles array.

글자와 글자 사이에 스프라이트 폰트를 사용해야 할 일이 생겨 (ex. 상금 ⓒ 100)
TextMeshProUGui 에 sprite richText 를 사용하여 다음과 같이 설정하였다.

상금 <sprite="coin_gem" name="coin"> <color=#FFEA00>100</color>

다른 것은 수정하지 않고 텍스트 내용만 바꾸었을 뿐인데 

mesh.vertices is too small. the supplied vertex array has less vertices than are referenced by the triangles array.


해당 게임 오브젝트가 껏다 켜질 때마다 위의 에러가 콘솔창에 출력되었다. (다행히 글자 출력에는 문제가 없음)
구글링을 좀 해 보니 TextMeshPro의 MeshFilter를 Clear 하고 새로 new 해서 할당하라는 글이 있어서 따라 해 봤는데 수정되지 않아서 포기하는 심정으로 해당 게임 오브젝트만 지우고 새로 만들었더니 에러가 사라졌다.(?)
비슷하게 다른곳도 수정했는데 똑같은 에러가 나오고, 게임오브젝트를 지웠다 새로 만드니 역시 사라졌다.

결론 : 모르겠으면 지우고 새로 만들자

2019년 12월 12일 목요일

Unity GPresto 변수 성능 테스트

GPresto에서 제공하는 메모리 변조 방지용 변수들을 사용해야 하는데 성능에 관한 의심이 들어 간단하게 테스트를 해 보았다.

bool 부터 Quaternion, Vector3 까지 지원해 주는데 제일 빈번하게 사용하는 int, float, Vector3만 테스트 했다.

각 타입에 최소 단위(1, 1.0f, Vector3.one)를 1억번 더한 결과, 다음과 같았다
(갤럭시s 8 기준)



int 형 : 8032 / 178 = 45.1배
float 형 : 38092 / 962 = 39.5배
Vector3형 : 54066 / 3808 = 14.2 배

결론 : 꼭 필요한 곳만 쓰자.

2019년 12월 3일 화요일

Android OBB 와 TextMeshPro

APK 가 150MB를 초과해서 OBB를 도입하고 있다.
기존 로그인 씬 보다 더 앞에 OBB다운로드 체크 씬을 도입하고 APK를 빌드해서 실행하니

위와 같은 에러를 뱉어내었다.

다운로드 확인을 위한 팝업에서 TextMeshPro를 사용 중이었는데, 타 팀에서도 TextMeshPro를 OBB체크 시에는 사용하지 않는다는 얘기를 들어 TextMeshPro 대신 일반 Text 로 교체하니 일단 에러는 사라졌다.

2019년 11월 27일 수요일

Jenkins에서 유니티로 실행한 Shell Script 가 끝나질 않는 문제 삽질 이야기


1. 우리팀 빌드머신은 iMac 이고 젠킨스로 빌드하고 있다.

2. 어셋 번들 파일 서버는 Amazon S3에 마련되어 있어 각 버전별로 폴더를 만들어서 업로드 하고 싶었다.

3. 버전이 클라이언트의 특정 변수에 설정되어 있어서 쉘크립트를 젠킨스가 직접 실행할수 없다. 서버 개발자 분께 부탁해서 버전을 파라메터로 받아서 S3의 버전 이름 폴더에 파일을 업로드 할 수 있는 스크립트를 만들었다.

4. 해당 스크립트를 어셋 번들 생성 후 유니티 코드로 호출 할 수 있도록 함수를 만들었다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
static void RunQaBundleUploadScript()
    {
        Debug.Log($"업로드 스크립트 실행 준비");
        if (psi == null)
        {
            psi = new System.Diagnostics.ProcessStartInfo();
        }
        var v = new GlobalConfig.VersionInfo();
        string args =
            Path.Combine(Application.dataPath,
            $"Editor/QaBundleUploadScript/qa_{EditorUserBuildSettings.activeBuildTarget.ToString().ToLower()}_patch.sh {v.ClientVersionToString()}");

        psi.FileName = "/bin/sh";
        psi.UseShellExecute = false;
        psi.RedirectStandardOutput = true;
        psi.Arguments = args;
        psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Minimized;
        psi.CreateNoWindow = true;
        var proc = System.Diagnostics.Process.Start(psi);
        proc.WaitForExit();//로그 출력을 위해
        var log = proc.StandardOutput.ReadToEnd();

        Debug.Log($"업로드 스크립트 실행 완료 {args}\n{log}");
    }

5. 단순 실행이 아니라 로그도 보고 싶어서 WaitForExit 와 ReadToEnd 를 사용하였다.
6. 유니티 에디터에서 해당 함수를 테스트 하고 동작이 확인되어 젠킨스 빌드를 돌렸는데 빌드도 되고 S3에 업로드도 잘 되었지만 젠킨스의 빌드 상태가 종료되지 않고 계속 대기상태가 유지되었다.
7. 서버 개발자분께서 알려 주셔서 WaitForExit 와 ReadToEnd 의 소스 코드를 다음과 같이 수정하니 젠킨스 빌드가 정상적으로 종료 되었다.


1
2
3
4
5
6
using(var proc = System.Diagnostics.Process.Start(psi))
{
    var log = proc.StandardOutput.ReadToEnd();
    proc.WaitForExit();
    Debug.Log($"업로드 스크립트 실행 완료 {DateTime.Now}\n{args}");
}

2019년 5월 22일 수요일

Max Size 가 원래 크기보다 작은 스프라이트의 SetNativeSize 하기

256x256 사이즈의 스프라이트를 128로 Max Size를 줄여서 사용할 때 SetNativeSize 를 하면 128x128 이 아니라 256x256 의 원래 크기로 돌아가 버린다

그럴 땐 overrideSprite의 사이즈를 이용하면 된다.

Sprite overrideSprite = GetComponent<Image>().overrideSprite;
icon.rectTransform.sizeDelta = new Vector2(overrideSprite.rect.width, overrideSprite.rect.height);

2019년 3월 22일 금요일

TextMeshPro의 글자 가로 세로 길이

TextMeshProUGUI 의 Text 글자들의 가로 세로 길이 구하는 법

GetPreferredValues()

Function to Calculate the Preferred Width and Height of the text object.
Declaration
public Vector2 GetPreferredValues()
Returns

TypeDescription
Vector2

2018년 12월 13일 목요일

Unity에서 string.Format 으로 숫자에 comma 찍기

재화 표시에 Comma 를 추가하기 위해
string text = string.Format("{0:0.#,###}", Gold)
를 사용중이었는데, Gold가 0일 경우 string이 "0" 이 아니라 비어있었다.

애용하는 c# web ide 페이지에서는 같은코드를 사용해도 0으로 출력이 잘되는걸로 보아 유니티 문제인듯.

string.Format("{0:n0}", Gold)
를 사용하면 0도 정상적으로 표시 된다.

Gold.ToString("#,##0") 도 된다.

2018년 11월 28일 수요일

iOS는 파일명 대소문자를 구분한다

제목 그대로.

 번들 다운로드 시스템을 변경한 후 테스트 도중 아이폰에서만 파일을 찾지 못하는 현상이 발생.
 윈도우 유니티 에디터, 맥 유니티 에디터, 안드로이드 기기에서는 문제가 없었음

 매니페스트 파일명을 대문자로 넣었더니 아이폰에서만 파일을 찾지 못해서 소문자로 수정했더니 문자 해결.

 약 3/4일 걸림

2018년 10월 18일 목요일

WorldToScreenPos in UGUI

개발 중인 게임의 UGUI 캔버스 모드가 Screen Space - Overlay 에서 Screen Space - Camera 로 변경되게 되었다.

별 일 없을줄 알았는데, 월드 좌표를 UI 좌표로 바꿨을때 이생해져서 열심히 구글링을 한 결과, Render Mode에 따라 변환하는 방식이 다르다는것을 알게되었다.

Overlay 모드에서는 단순히 

rectTransform.position = RectTransformUtility.WorldToScreenPoint (Camera.main, target.position);

로 해결되었지만 Camera모드에서는 좀더 복잡한 계산이 필요하다

  var pos = Vector2.zero;
  var uiCamera = Camera.main;
  var worldCamera = Camera.main;
  var canvasRect = canvas.GetComponent<RectTransform> ();

  var screenPos = RectTransformUtility.WorldToScreenPoint (worldCamera, target.position);
  RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRect, screenPos, uiCamera, out pos);
  rectTransform.localPosition = pos;


참고 링크

일본 개발자들이 정리를 참 깔끔하게 하는것 같다. 번역도 편하고.

2018년 10월 15일 월요일

Sprite 를 Texture2D로 변환하던 중 발생한 문제

Atlas 의 Sprite 를 Texture2D로 변환하여 잘 활용하던 중, 2017.1에서 2018.3 b5로 유니티 버전업을 하게 되었다.

발생하던 모든 Error 를 다 처리하고 테스트 하는 도중 Sprite 에서 변환한 Texture2D가 나
오지 않는 걸 확인하고 여러가지 방법(텍스쳐 포멧 바꿔 보기 등)으로 수정하려고 노력해 보았지만 소용이 없었다.

원인은 Sprite.textureRect 의 모든 값이 0으로 반환되는 것이었는데 2018에 해당 내용이 Obsolated 된 것도 아니었다.

마지막이라는 심정으로 해당 아틀라스의 옵션을 확인하니, 2017.1 에서 설정했던 내용이 바뀌어 있었다. Allow Rotation 과 Tight Packing 옵션이 켜져 있었다. 그 중 Tight Packing 옵션을 끄니 Sprite.textureRect 값이 정상적으로 반환되었다.

2018년 9월 4일 화요일

GetAllScenePathsFromAssetBundle crash


  1. 백그라운드로 번들을 다운받고 캐싱하는 코드를 만들고 있는 중
  2. 번들 파일을 받고  UnityWebRequest.GetAssetBundle 을 사용하여 캐싱을 하면 에디터에서 100% 크래쉬가 발생(2017.2.1p1)
  3. Editor 로그를 확인하니까 마지막 콜스텍이 GetAllScenePathsFromAssetBundle
  4. 구글링 해 보니 나같은 현상이 발생한다는 애들이 있었음
    issuetracker
  5. We noticed that this bug was related to using WebRequest to cache bundles in background and not accessing the DownloadHandler.assetBundle property before the UnityWebRequest dispose.
  6. UnityWebRequest 를 쓸 때는 꼭 using 을 사용하자 유니티 메뉴얼

2018년 7월 3일 화요일

소소한 최적화


생각날 때마다 업데이트.
  • transform.position = p; transform.rotation = r; 대신 transform.SetPositionAndRotation(p,r)
  • null 조건 연산자를 사용하라
public class EventSource
{
    private EventHandler<int> Update;
    private int counter;    

    public void RaisUpdates()
    {
        counter++;
        if (Update != null)
            Update(this, counter);
    }
}
대신

    public void RaisUpdates()
    {
        counter++;
        Update?.Invoke(this, counter);
    }
Effective c# 8장 참고. Atomic 하다고 함.


  • Enum 을 문자열로 바꿀 때 nameof(MyEnum.EnumValue);
  • c# 7.2 에서 추가된 in 키워드를 최대한 활용하자. 링크 구조체를 파라매터로 넘길 때 속도가 10.1배 정도 차이가 난다
  • 만들 갯수가 예측되는 프리팹은 동적으로 만들지 말고 미리 만들어 놓자.

2018년 6월 28일 목요일

Unity Assert on Device


using System.Collections.Generic;

private readonly Dictionary<TYPE, IValue> _values = new Dictionary<TYPE, IValue>();

private void SetTable(TYPE type, IValue origin)
{
    Assert.IsFalse(_values.ContainsKey(type), type.ToString());
    _values.Add(type, origin);
}

public ITable GetTable(TYPE type)
{
    IValue value = null;
    Assert.IsTrue(_values.TryGetValue(type, out value));
    return value;
}



유니티에서 위의 코드를 사용하고 있었는데 지속적으로 핸드폰에서만 문제가 발생했다.

에디터에서는 재현이 되지 않아 로그를 추가하여 APK를 빌드하고 기기에 설치하여 Logcat 으로 로그를 확인해 보았다.

_values 에는 분명 값이 있고 _values.TryGetValue 를 사용하면 정상적인 값을 얻을 수 있었지만,  GetTable 함수를 사용하면 null 만 반환되는 문제였다.

몇 줄 되지 않는 코드라 대체 어떤것이 문제인지 도통 감을 잡을수가 없었다.

마지막이라는 심정으로 GetTable 함수의 Assert 를 제거하고 다시 APK를 빌드하여 핸드폰에서 실행하자 거짓말처럼 GetTable 함수가 정상적인 값을 반환했다.

대체 이해가 불가하여 옆자리 동료에게 물어보니 이유를 들을 수 있었다.

Assert 함수들의 소스 코드를 보면

[Conditional("UNITY_ASSERTIONS")]
public static void IsTrue(bool condition)
{
    Assert.IsTrue(condition, (string) null);
}

[Conditional("UNITY_ASSERTIONS")] 가 붙어있음을 확인 할 수 있다.

에디터에서 Assert 함수들이 잘 동작하는 이유는 유니티가 C# 프로젝트 파일을 만들때

속성에 위 스크린샷 처럼 UNITY_ASSERTIONS 속성을 강제로 넣어주기 때문이다.

APK에서는 UNITY_ASSERTIONS 속성이 정의되어 있지 않고, Assert 함수들은 동작하지 않게 된다.

게다가 GetTable 함수의 Assert 코드 위에 IValue value = null; 로 초기화까지 해 버렸다.(C++ 쓰던 습관으로)
아마 IValue value; 로 했었으면 APK 빌드 도중 컴파일 에러가 나서 더 빨리 문제를 찾을수 있었을 지도.

APK에서도 Assert 함수들을 사용하고 싶으면 UNITY_ASSERTIONS 디파인을
Player Settings -> Other Settings -> Scripting Define Symbols 에 추가하면 된다.