https://sungjjinkang.github.io/



- 요구조건 


앱 버전을 x.x.x 형식으로 한다


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


- 업데이트를 강제 하고 싶지 않은 경우 맨 뒤의 숫자만 바꾸면 업데이트 요구를 하지 않는다



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


bool IsSameVersion = false; //일단은 그냥 같은 버젼으로 취급해준다
bool IsChecked = false;
      
private void GooglePlayVersionCheck()

{
        ////////////////////

        UnsafeSecurityPolicy.Instate(); //이 코드를 안쓸 경우 오류가 뜨더라구요

        string marketVersion = "";

        string url = "https://play.google.com/store/apps/details?id=앱id";

            HtmlWeb web = new HtmlWeb();
            HtmlDocument doc = web.Load(url);
            yield return doc;

        try
        {
            System.Collections.Generic.IEnumerable<HtmlNode> nodes = doc.DocumentNode.Descendants("div").Where(d => d.Attributes["class"].Value.Contains("htlgb"));

            foreach (HtmlNode node in doc.DocumentNode.SelectNodes("//span[@class='htlgb']"))
            {
                string value = node.InnerText.Trim();

               

                /////////
                if (System.Text.RegularExpressions.Regex.IsMatch(value, @"^\d{1}\.\d{1}\.\d{1}$"))
                {
                    
                    marketVersion = value;
                    Debug.Log("market version : " + marketVersion.Trim());



                    if(marketVersion.Split('.')[0] == Application.version.Split('.')[0] && marketVersion.Split('.')[1] == Application.version.Split('.')[1]) // . . 형식중에서 앞의 두 숫자가 바뀌는 경우에만 업데이트 요구 -> 업데이트를 강제할 필요없는 경우에는 맨뒤의 숫자만 바꾸자
                    {
                        Debug.Log("업데이트 필요없음");
                        //버전이 같은 경우 
                        IsSameVersion = true; //일단은 그냥 같은 버젼으로 취급해준다
                        IsChecked = true;
                        yield break; //함수 빠져나감 
                    }
                    else
                    {
                        Debug.Log("업데이트 필요함");
                        //버전이 다른 경우 
                        IsSameVersion = false;
                        IsChecked = true;
                        _DeveloperLogoScene.SetActiveRequestUpdateGameOnGooglePlayPanel(true);
                        yield break; //함수 빠져나감 
                    }

                }


            }

          
        

        }
        catch
        {

            //구글 플레이 쪽에서 코드를 자주 바꾸다 버전을 못가져 올 수 도 있습니다. 이런 경우를 대비하여 exception이 뜬 경우 그냥 버전이 동일한걸로 취급
            IsSameVersion = true; //일단은 그냥 같은 버젼으로 취급해준다
            IsChecked = true;

 
        }

      
      
  }


유니티 라이트맵을 사용하다 보면 위의 사진과 같이 오브젝트에 어색한 얼룩이나 검은 점이 생기는 것을 볼 수 있다

이는 UV가 겹쳐서 생기는 일이다 .

이를 해결하기 위해서는 아래와 같이 Generate Lightmap Uvs를 설정해 주어 라이트 맵을 위한 UV를 만들어 주면 된다


간혹 UV를 생성해준 후에도 얼룩이 그대로 있는 경우가 있다

이는 생성된 UV에서 텍스쳐가 겹치는 부분이 있기 때문이다 이를 해결해 주기 위해서는 PackMargin을 늘려주면 된다. 조금 씩 늘리면서 Overlapping UV가 사라지는 지점까지 PackMargin을 늘려주면 된다. 



https://docs.unity3d.com/kr/2018.1/Manual/RandomNumbers.html

우선 스크롤뷰를 사용하는 방법에는 여러가지가 있다


1. Vertical하게 컨텐츠들을 배치하는 방법




2. Horizontal하게 컨텐츠들을 배치하는 방법




3. Vertical하게 배치하되 한 줄에 여러 컨텐츠를 넣는 방법




등등이 있다


이러한 스크롤뷰 내의 Content와 Content의 child들의 size , position을 일일이 코드로 수정해주려면 매우 힘들다.

그렇기 때문에 유니티는 여러가지 좋은 컴퍼넌트들을 제공해준다. 그 방법을 알아보자.


우선 가장 기본적인 것은 Content의 Child로 들어갈 Ui들에 LayoutElement를 추가해주는 것이다


아래와 같이 Preferred Width와 Height를 체크해주어서 적절한 사이즈를 정해주자....


그 다음에는 Content에 여러 두가지 컴퍼넌트가 각각 필요하다


우선 공통적으로는 Content Size Filtter가 필요하다

스크롤뷰를 아래위로 당기는지 혹은 좌우로 당기는지에 따라 


아래위로 당기는 경우 Vertical Fit을 Preferred Size로 Horizontal Fit을 Uncontrained로

좌우로 당기는 경우 Vertical Fit을 Uncontrained로 Horizontal Fit을 Preferred Size로 설정한다

Vertical Fit, Horizontal Fit 모두 Preferred Size로 설정한다


그 다음 


1. 아래 위로 당기는 경우에는 Vertical layout Group을


2. 좌 우로 당기는 경우에는 Horizontal layout Group을


3. 한 줄 혹은 한 행에 여러 Content child가 들어가는 경우에는 Grid layout Group을


각 컴포넌트의 설정방법은 아래의 것을 참고하면 된다..



특별하게 Grid Layout Group의 경우에는 


한 줄에 여러 컨텐츠를 넣는 경우에는 Cell Size를 조정, Constraint를 Fixed Column Count를 한 줄에 들어갈 컨텐츠 개수로 정해주면 된다


한 행에 여러 컨텐츠를 넣는 경우에는 Cell Size를 조정, Constraint를 Fixed Row Count를 한 행에 들어갈 컨텐츠 개수로 정해주면 된다




Start Axis는 Content의 Child 순서대로 ScrollView에서 어떤 순서로 배치할지를 결정한다

horizontal은 Child 순서대로 왼쪽에서 오른쪽으로 스크롤뷰를 채워나간다

vertical은 Child 순서대로 위에서 아래로 스크롤뷰를 채워나간다










Content와 Content의 child로 들어갈 오브젝트의 Anchor을 조정해주어서 적절한 위치를 정해주자


C# Dictionary에서 key를 enum이나 struct으로 사용 시 매우 주의해야할 점


Dictionary key 값으로 enum이나 struct을 사용하면 알게 모르게 사용하면서 엄청난 양의 가비지가 발생한다


그 이유는 enum이나 struct은 Equals, GethashCode가 구현되지 않았기 때문에 Dictionary의 Contain 함수를 사용할 때 비교를 위해 부모 클래스 형인 Object로 박싱하여 Object끼리 비교를 해야하기 때문이다. 예를 들면 A라는 딕셔너리가 있고 A.ConatinKey(키값) 이나 A[키값]을 사용 할 때 모두 내부적으로는 비교구문이 실행된다. 비교를 위해서는 비교 함수를 사용하는데 이때 자신이 만든 enum , struct은 Equals, GethashCode가 구현이 되어 있지 않아 박싱을 해야하고 박싱을 할 때 가비지가 발생한다.


이러한 문제는 프로그램이 커질 수록 더 많은 양의 가비지를 발생시켜 나중에는 문제가 될 가능성이 많다


이를 해결하기 위해서는 IEqualityComparer<T> 인터페이스를 상속받는 클래스를 선언하여 Dictionary 인스턴스를 생성할 때 생성자로 넣어주면 된다


아래와 같이 struct(Vector3) , enum(MoviePoint)에 대한 Comparer 클래스를 생성해주면 된다.



public class Vector3Comparer : IEqualityComparer<Vector3>

{

    public bool Equals(Vector3 x, Vector3 y)

    {

        return x.x == y.x && x.y == y.y && x.z == y.z;

    }


    public int GetHashCode(Vector3 vector)

    {

        return vector.x.GetHashCode() ^ vector.y.GetHashCode() << 2 ^ vector.z.GetHashCode() >> 2;

    }

}


public class MoviePointComparer : IEqualityComparer<MoviePoint>

{

    public bool Equals(MoviePoint x, MoviePoint y)

    {

        return (int)x == (int)y;

    }


    public int GetHashCode(MoviePoint obj)

    {

        return ((int)obj).GetHashCode();

    }

}


Dictionary<Vector3, bool> dic = new Dictionary<Vector3, bool>(new Vector3Comparer());


Dictionary<MoviePoint, bool> dic = new Dictionary<MoviePoint, bool>(new MoviePointComparer ());

  1. GameObject WorldObject;
  2. //this is the ui element
  3. RectTransform UI_Element;
  4. //first you need the RectTransform component of your canvas
  5. RectTransform CanvasRect=Canvas.GetComponent<RectTransform>();
  6. //then you calculate the position of the UI element
  7. //0,0 for the canvas is at the center of the screen, whereas WorldToViewPortPoint treats the lower left corner as 0,0. Because of this, you need to subtract the height / width of the canvas * 0.5 to get the correct position.
  8. Vector2 ViewportPosition=Camara.main.WorldToViewportPoint(WorldObject.transform.position);
  9. Vector2 WorldObject_ScreenPosition=new Vector2(
  10. ((ViewportPosition.x*CanvasRect.sizeDelta.x)-(CanvasRect.sizeDelta.x*0.5f)),
  11. ((ViewportPosition.y*CanvasRect.sizeDelta.y)-(CanvasRect.sizeDelta.y*0.5f)));
  12. //now you can set the position of the ui element
  13. UI_Element.anchoredPosition=WorldObject_ScreenPosition;



- 출처 : https://answers.unity.com/questions/799616/unity-46-beta-19-how-to-convert-from-world-space-t.html

유니티 프로젝트 폴더를 깃에 올리다 보면 .obj 모델 메쉬파일이 깃에 안올라와 있는 것을 알 수 있다

대개 이유는 자신의 gitignore에 *.obj 를 추가 했거나 global ignore list에 *.obj가 올라와 있는 경우이다.

위 두 경우 때문에 obj 확장자의 파일들이 커밋에 추가 되지 않았던 것이다


이를 해결하기 위해서는 해당 깃의 gitignore에 !Assets/**/*.obj 를 추가함으로 해결 할 수 있다

그럼 Assets 폴더 안에 모든 *.obj를 찾아내어서 그 파일들을 전부 허용해줄 것이다




유니티 Raycast를 사용할 때 특정한 오브젝트만 Raycast에 Target되기를 원하는 경우 LayerMask를 사용한다

하지만 LayerMask를 사용할 때 주의해야할 점이 


RaycastHit hitInfo;

Ray ray = Camera.main.ScreenPointToRay(InputManager.GetInputPos());



1.   if (Physics.Raycast(ray, out hitInfo, 1 << LayerMask.NameToLayer("특정 레이어") ))


2.   if (Physics.Raycast(ray, out hitInfo, float.MaxValue, 1 << LayerMask.NameToLayer("특정 레이어") ))



위의 1번과 2번의 차이는 중간에 float.MaxValue 즉 Raycast의 파라미터 중 maxDistance를 넣어주느냐 마냐의 차이이다


1번의 경우에는 Raycast는 1 << LayerMask.NameToLayer("특정 레이어") 를 flaot maxDistance 파라미터에 넣어주는 것으로 인식하여서 LayerMask가 제대로 적용되지 않는다. 함수가 프로그래머가 의도한 바와는 다르게 1 << LayerMask.NameToLayer("특정 레이어") 를 다른 parameter 값으로 인식한 경우다. 게다가 Raycast에는 maxDistance 파라미터가 없이 LayerMask를 파라미터로 넣는 함수형은 없다.


그래서 프로그래머는 maxDistance에 float.MaxValue를 넣어주어야만 뒤의 1 << LayerMask.NameToLayer("특정 레이어")를 프로그래머가 의도한대로 LayerMask의 값으로 인식한다

사진과 같이 Button에 Event Trigger이라는 컴포넌트를 추가하여 준다

 그 다음 Add New EventType에서 원하는 Event를 추가하여 주면 된다


누르고 있는 상태를 체크하려면 Pointer Down를 추가하여 주면 된다

그 후 스크립트에서 


priavte bool ButtonDown;


public void PointerDown()

{

ButtonDown=true;

}


이 코드를 추가 후 Pointer Down의 유니티 이벤트 List에 PointerDown() 함수를 추가하면 버튼을 누르고 있는 상태일때 PointerDown() 함수가 실행된다



+ Recent posts