참고 : https://learn.microsoft.com/ko-kr/dotnet/api/system.linq.enumerable.oftype

 

OfType 

실행 쿼리문 메소드
지연된 실행 없음 OfType

사용예시

필터결과 = 집합.OfType<클래스>()

- 집합내의 아이템들 중 클래스에 해당하는 타입의 아이템들을 뽑아낸다.

 

OfType은 메소드로만 존재하고, 쿼리문은 없습니다.

 

예제 및 활용

기본적인 예

    class Animal
    {

    }
    class Dog : Animal
    {

    }
    class Cat : Animal
    {

    }
    List<Animal> animals = new List<Animal>()
    {
        new Animal(),
        new Dog(),
        new Cat()
    };
    
    // 주인공 OfType
    var res = animals.OfType<Dog>();
    
    
    // 아래는 위 OfType과 동일한 로직을 Where과 일반 문법으로 표기한 겁니다.
    // where절일 때,
    var res = animals.Where(item => item.GetType() == typeof(Dog));

    // 일반적인 문법일 때,
    foreach(var item in animals)
    {
        if(item.GetType() == typeof(Dog))
        {
        }
    }

 

Animal을 상속받은 클래스 중에 Dog 클래스만을 필터링하는 코드입니다.

 

object가 최상위 클래스니까 object List에 여러 클래스를 담아서 원하는 클래스를 뽑아서 쓸 수도 있겠지만,, 그렇게 쓰는 곳이 있을런지 의문이네요.

 

특정 클래스를 상속받아 하나의 리스트에 담는 경우는 흔합니다.  같은 클래스를 상속받아 함수를 클래스별로 다르게 구현하고, list 루프를 돌면서 실행시키는 식으로 많이 쓰잖아요.

예를 들어, 모든 몬스터 (오크, 스켈레톤, 뱀파이어 등)를 이동시키고자 하는데, 다 이동범위가 제각각이라면, 최상이 클래스에 이동 함수를 구현하고, 각 몬스터마다 상속받아 이동범위를 다르게 구현하겠죠.

 이 때 오크들만 뽑아서 잠깐 스톱시키고 싶다! 이럴 때 OfType으로 오크 클래스만 필터링해서 Stop 시킬 수 있겠네요.

 

다만, OfType은 Where절로도 구현이 가능합니다.

성능을 한번 PS에서 비교해보겠습니다.

 

PS. 성능 비교해보기.

1. foreach 와 Where절, OfType  비교하기.

 코드 :

    private void Start()
    {
        for(int i = 0; i < 100000; i++)
        {
            animals.Add(new Animal());
            animals.Add(new Dog());
            animals.Add(new Dog());
            animals.Add(new Cat());
            animals.Add(new Cat());
            animals.Add(new Cat());
        }
        Debug.Log("List count " + animals.Count);
    }

    public void OnClick1()
    {
        System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
        sw.Start();

        foreach (var item in animals)
        {
            if (item.GetType() == typeof(Dog))
            {
            }
        }

        sw.Stop();
        Debug.Log($"foreach Time : {sw.ElapsedMilliseconds}ms");
    }
    public void OnClick2()
    {
        System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
        sw.Start();


        var res = animals.Where(item => item.GetType() == typeof(Dog));

        foreach(var item in res)
        {
        }

        sw.Stop();
        Debug.Log($"Where Time : {sw.ElapsedMilliseconds}ms");

    }

    public void OnClick3()
    {
        System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
        sw.Start();

        var res = animals.OfType<Dog>();

        foreach (var item in res)
        {
        }

        sw.Stop();
        Debug.Log($"OfType Time : {sw.ElapsedMilliseconds}ms");
    }

 

결과:

상세 프로파일링 결과:

Foreach:

 Where:

 OfType:

결론:

foeach-if보다 where이 1.5배 정도 느리고, OfType 이 where보다 1.5배 정도 느리네요.

당혹스럽네요... Where로도 할 수 있는 걸 따로 메소드를 뺏길래 더 특화되서 좋은 건가? 했는데, 더 안좋네요?

뭔가 별도의 사용 용도가 있는 걸까요? 모르겠네요.

 

이전 where 절에서 테스트 했을 때는 foreach-if가 20~40배 가량 압도적으로 빨랐는데, 이번엔 1.5배가 나왔네요. 상황에 따라 다르긴 하지만 foreach-if가 Where절보다 빠르단 건 변하지 않았네요

 

(제대로 Type  필터 로직이 돌았는지는 count()를 통해 각각 200000의 결과가 나온건 확인했습니다. 프로파일링에서도 확인 할 수 있습니다.)

 

최종 결론:

 - foreach-if (일반 문법) > Where > OfType 순으로 속도가 빠릅니다. ( OfType이 제일 느리고, 각각 1.5배 정도 이상의 차이가 난다.)

 - OfType 전 안쓸랍니다...

 

 

 

 

테스트 환경

  • cpu - i5-11400F
  • gpu - GeForce RTX 3060
  • Unity 2021.3.13f1
  • VisualStudio 2022
Posted by 검은거북

 

Linq에서 가장 기초가 되는 Where 문부터 시작하겠습니다.

참고 : https://learn.microsoft.com/ko-kr/dotnet/csharp/programming-guide/concepts/linq/filtering-data

 

 

필터링 메소드란?

필터링은 지정된 조건을 충족하는 요소만 포함하도록 결과 집합을 제한하는 작업을 가리킵니다.  라고 공식문서에서 말하네요.

그냥 간단하게 말해서 조건에 만족하는 요소만 추출해낸다.

예를 들어, 키가 180 이상인 사람만 고른다.  과일 중 귤만 고른다.

 

이런 필터링 메소드에 포함되는 Linq 메소드가 Where, OfType 이 있더군요.

Where은 정말 자주 사용하는데, OfType은 처음 알았네요. 사실 Where절이 워낙 범용적이라, Where로도 OfType은 대신할 수 있을거 같습니다만.... 성능면에서는 어떨지는 OfType에서 한 번 테스트해봐야겠네요.

 

Where 절

실행 쿼리문 메소드
지연된 실행 where Where

사용예시

필터결과 = 집합.Where(item => 필터 조건절)

- 집합내의 아이템들을 모두 조건절로 비교해서 부합하는 것만 뽑아내는 겁니다.

 

예제 및 활용

가장 기본적인 예

        char[] chars = new char[] {'a','b','k','q','g'};
        var res = chars.Where(item => item == 'k');

 

chars 배열 중에 k를 찾아줘 라는 구문이죠

 

Where 절을 사용 안하고 foreach문을 쓰면 아래와 같아집니다.

        foreach (var item in chars)
        {
            if (item == 'k')
            {
            }
        }

 

linq가 훨씬 깔끔하죠? 

코드가 복잡해질 수록, 조건자가 복잡해질 수록 더더욱 깔끔해집니다.

 

당연하게도 조건절에는 얼마든지 if문에 넣을 수 있는 것들은 다 들어갈 수 있습니다

        var res = chars.Where(item => item == 'k' && item == 'q');

 

뭐 이런식으로 &&, ||도 얼마든지 사용 가능!

 

하지만! 밑에서도 PS로 설명하겠지만, Where절은 편의성은 올라가지만 성능면에서는 떨어지는 편입니다. 모든 Linq가 그렇겠지만 코드 가독성, 유지보수 측면에서는 쓰기좋지만, 최적화가 중요한 곳에서는 남용하지 않으시길 권장드립니다.

 

 

PS. 성능 비교해보기.

1. Where절과 Foreach - if 를 직접 비교하기.

 코드 :

    public void OnClick1()
    {
        System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
        sw.Start();

        var res = chars.Where(item => item == 'k');

        sw.Stop();
        Debug.Log($"Linq Time : {sw.ElapsedMilliseconds}ms");
    }

    public void OnClick2()
    {
        System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
        sw.Start();

        foreach (var item in chars)
        {
            if (item == 'k')
            {
            }
        }

        sw.Stop();
        Debug.Log($"foreach Time : {sw.ElapsedMilliseconds}ms");
    }

 

결과:

 

상세 프로파일링 결과:

 Linq:

 

 Foreach:

 

결론:

얼핏 보면... Linq가 0ms!? 대박 할 수도 있는데.... 이건 Where절이 실행이 안된겁니다.

이게 Linq 특유의 "지연된 실행" 입니다.

Where절만 써서는 실제로 실행되지 않아요. 담아만 두고, 어딘가에서 Count() 또는 Foreach 등에서 사용을 할 때 비로소 실행이 됩니다.

 

그럼 이번엔 Foreach에 담아서 실행이 되게 해보죠.

 

2. Where절 - Foreach 와 Foreach - if 를 비교하기.

코드 :

    public void OnClick1()
    {
        System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
        sw.Start();

        var res = chars.Where(item => item == 'k');

        foreach (var item in res)
        {
        }

        sw.Stop();
        Debug.Log($"Linq Time : {sw.ElapsedMilliseconds}ms");

    }

    public void OnClick2()
    {
        System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
        sw.Start();

        foreach (var item in chars)
        {
            if (item == 'k')
            {
            }
        }

        sw.Stop();
        Debug.Log($"foreach Time : {sw.ElapsedMilliseconds}ms");
    }

 

결과:

프로파일링 결과:

Linq:

 

Foreach:

 

결론:

Linq가 확 느려졌죠? Foreach에 넣으면서 실제로 Where절이 실행되었기 때문입니다.

같은 foreach로 돌린거니까, if문과 Where절의 비교라고 볼 수 있겠네요.

즉, 지연되었던 실행이 실행되면 Linq의 Where절은 Foreach - if 보다 40배가량 느리다 입니다.

(여러번 테스트해본 결과 평균적으로 40배정도의 데이터가 나왔습니다.)

 

- Count 함수로 Where 절을 실행시켜 테스트 했을 때는 10배가량 느렸던 결과를 보았습니다. 대략 10 ~ 40배 라고 생각해도 꽤 큰 성능 차이죠? 

 

 

최종 결론:

 - Linq의 Where 절은 "지연된 실행"으로 실제로 다른 함수에 의해 실행되기까지 실행되지 않는다.

 - Linq의 Where 절은 같은 로직의 Foreach - if문보다 대략 40배정도 느리다.

 - 편의성은 올라가지만 성능면에서는 떨어지기 때문에 최적화가 중요한 곳에서는 남용하지 않기를 권장드립니다.

  (성능 저하를 잡기위해 프로파일링을 해보면 Linq에서 잡히는 경우가 꽤나 많습니다)

 

 

 

 

테스트 환경

  • cpu - i5-11400F
  • gpu - GeForce RTX 3060
  • Unity 2021.3.13f1
  • VisualStudio 2022
Posted by 검은거북

목차

  • 개요
  •  필터
  • 프로젝션 (변환? 투사?)
    • Select
    • SelectMany
    • Zip
  • 진행중...

 

Linq란 무엇인가?

https://learn.microsoft.com/ko-kr/dotnet/csharp/linq/

라고 공식문서가 말하네요.

뭔가.... 어려운 말 막 쓰는데, 그냥 단순하게,

SQL처럼 쿼리형식으로 데이터 처리 (필터링/ 가공 등) 가 가능하게 해주는 언어 집합이다.

라고 생각하면 편할거 같네요.

 

특징으로는 "지연된 실행"이 있습니다.

결과가 필요한 함수 (Count, Max 등) 나 foreach에 사용하지 않는한 실행이 지연된다는 의미인데, 이걸 간과하고 코딩하면 발적화를 느껴보실 수 있습니다;;

 

사용해보며 느낀 장단점

장점

  • 코드 가독성 향상
  • 코드 재사용성 / 확장성 향상
    • 유지보수에 좋겠죠
    • 저는 게임에서 필터링하는 구간은 대부분 Linq를 애용하긴 합니다.

단점

  • 성능 부하 증가
  • 잘못쓰면 더더 성능 부하 증가

 

참고

공식문서에서는 쿼리 방식과 매서드 방식이 있는데, 성능상에 다른 점은 없지만, 쿼리 방식이 가독성이 좋으니 권장한다고 합니다. 다만 매서드 방식으로만 할 수 있는 함수들이 있다고 하더라고요.

 

개인적으로는 가독성은 주관적인 영역이니 권장하는 이유라 보기 힘들거같고, (실제로 전 매서드가 더 보기 편합니다) 매서드 방식으로만 할 수 있는게 있다면, 매서드 방식을 권장하는게 맞지않나? 싶어요. 음... 전 그래서 향후 포스팅에서는 매서드 방식으로 진행할 예정입니다.

 

 

여담

전 이직하고 처음으로 Linq를 접하고, 어언... 5년정도 쓴 거 같습니다. Linq 사용법 자체가 어렵진 않아서 금방 사용하는 방법은 익혔는데, 사용하다보니 성능상에 문제가 좀 있는 아이더군요. 

단순한 데이터 처리면 별 문제 없겠지만, Linq가 주로 사용되는 곳이 데이터 처리, 즉, 수백개의 데이터를 처리하는데 사용되다보니, 성능 부하로 프로파일링을 해보면 꽤 자주 보이더라고요.

굳이 필요가 없는데, 자주 호출하는 함수에 ToList를 해놨다거나, 너무 남용해서 썼다거나 등등... 그래서 인식이 쓰기 편하고, 보기에는 이쁘지만, 퍼포먼스는 나쁜 아이로 인식이 됐습니다.

그래서 어깨너머로 배워 쓰던 Linq를 제대로 공부해보려고 합니다. 이왕 공부하는거 포스팅으로도 남기고, Linq 백과사전을 함 만들어보자라는 포부로 시작해보려고 합니다.

 

 

 

Posted by 검은거북

 

 

계정 분류 Developer Enterprise
취득 방법 기본 유료 맴버쉽 (법인)
프로비저닝 프로필 AppStore Adhoc Development Inhouse
용도 서비스 배포용 테스트 테스트 테스트
기기 제한 배포 전에는 앱 센터 등록 후 테스트 플라이트에 등록된 유저만 테스트,
배포 후에는 제한 없음
최대 100대 등록 가능 Adhoc 등록기기
+ 2대 추가 가능
무제한
Apple / App Center
로그인
O O O X
푸쉬 O O O X
결제 O O O X
기타     Adhoc과의 차이점이 무엇일까?

보안 솔루션에서 Dev 프로비저닝은 변조앱으로 구분하는 것을 경험해봄.

이름으로 봐선 Unity Development 빌드를 뽑을 때 써야할 것 같지만 꼭 그렇지도 않은 듯.
 

 

(대체 왜 이렇게 프로비저닝을 분기를 해놓은 건지.... 애플....)

 

일하면서 퍼블리셔 3개 회사를 겪어봤는데, 그 과정에서 알게 된 iOS 프로비저닝 정보를 정리한 표입니다.

매번 라이브 하다보면 까먹고 해서 생각난 김에 적어봅니다.

 - 대체로 퍼블리셔들은 inhouse 프로비저닝 (회사에 따라 Enterprise 프로비저닝이라고도 합니다) 은 기본으로 제공하고, 회사에 따라 다르지만, 기기 UUID 2대를 취합받아 Develpment 프로비저닝을 전달해 주는 듯합니다. ( Adhoc은 회사가 클수록 제한 기기가 부족하기 때문에 전달이 안 되는 것으로 추측합니다.)

 - 개발자 입장에서는 Adhoc 이 그나마 앱스토어와 비슷한 환경이여서 Adhoc을 전달해 주는 곳이 가장 좋긴 했습니다.

 

 

저는 iOS 프로그래머가 아니다보니 틀린 정보가 있을 수 있습니다. 지적해 주시면 감사히 배우겠습니다. 

새로 알게되거나 틀린 게 있으면 다시 업데이트하겠습니다.

 

 

 

'IT > 기타' 카테고리의 다른 글

신입 프로그래머의 마음가짐  (1) 2023.11.17
Posted by 검은거북

첫 회사에 입사하는 신입 프로그래머의 마음가짐과 조심해야 하는 것들에 대해 한 번 적어보려고 합니다.

 

저도 신입 프로그래머 시절을 겪기도 했고, 몇몇 신규 입사자분들을 가이드해드리면서 느꼈던 것들을 적으면, 누군가에게는 도움이 될 수도 있고, 저 또한 마음가짐을 다시 다잡을 수 있을 거라 생각합니다.

 

참고로 저는 클라이언트 프로그래머입니다. 클라이언트 관점에서 작성되었습니다.

 

 

필수사항

- 이것만 지켜도 기본기는 되어있다!

 

  1.  절대 본인이 모르는 코드는 넣지 마세요.
    • 라이브 프로젝트에서 이미 사용하는 코드를 가져오는 것은 좋습니다. 라이브에 서비스되며 검증된 코드니까요. 하지만 복붙 하더라도 코드를 정확히 파악하고, 필요한 것만 가져오세요.
    • 해당 코드가 뭔지 도통 모르겠으면 그냥 선임에게 물어보세요.
    • 작업자가 모르는 코드는 다 시한폭탄입니다.
    • 외부 오픈소스를 가져올 때도 확인하고 필요한 것만 가져오는 게 베스트겠지만, 여의치 않다면 충분히 검토하시고, 이 소스가 필요한 타당한 이유를 근거로 가져오시길 추천드립니다.
  2. 작업하시면서 더 이상 사용하지 않는 코드가 생기면 바로바로 제거해 주세요.
    • 그때그때 정리 안 하면 혼란이 가중되고, 다음 작업자한테 떠넘기기 밖에 안됩니다.
    • 혹시 몰라서 내버려두었다는 소리는 잘 모르고 작업했다는 소리로 들립니다.
  3. 항상 서버가 에러 날 수 있다는 상황을 염두하시고 코드를 짜주세요.
  4. 작업자 간의 R&R이 있습니다. 아무 말 없이 다른 작업자의 작업공간을 침범하지 마세요.
    • 작업공간은 그 작업자의 책임하에 있습니다. 근데 작업자 본인이 모르는 작업이 생기는 건 위험하기도 하고, 실례라고 생각합니다.(부득이하게 작업하게 되면 작업 후에라도 알려주세요)
  5. 함부로 타인의 코드를 바꾸지 마세요. (부득이하게 해야 한다면 나중에 공유해 주세요)
    • 변경해야 할 이유가 있다면 해당 작업자와 논의하시길 추천드립니다.
    • 작업자 간의 코드 스타일을 존중해 줍시다. 어차피 그 부분을 나중에 수정해야 될 사람은 그 담당자입니다. 본인 코드 스타일대로 바꿔버리면 혼란스럽습니다.
    • 특히 라이브라면 검증된 코드를 바꾸는 건 어떤 이슈가 터질지 모르기 때문에 더 위험합니다. (검증된 코드는 다시 테스트 안 하고 넘어갈 확률이 크거든요)
    • 비효율적으로 보여도 그렇게 해야 할 이유가 있을 수 있습니다.
  6. 함수명 / 변수명은 역할을 알 수 있게 신경 써 주세요.
  7. 적절한 자료구조를 사용해 주세요.다른 곳에서 썼으니 따라 한다는 1번과 같은 행동입니다.
  8. 라이브 서비스는 서비스 안전이 최우선입니다.
    • 예를 들어, 코드 리펙토링 같은 건 큰 각오가 필요할 겁니다. 5번과 비슷한 맥락으로 함부로 하지 않으시길 추천드립니다.
  9. QA를 맹신하시면 안 됩니다.
    • 귀찮더라도 테스트 꼼꼼히 해주세요. 예외상황은 작업자가 가장 잘 압니다.
    • QA는 기본적으로 기획 의도와 동작이 맞는가를 확인하는 최소한의 테스트입니다. 겉으로 쉽게 보이는 예외상황 외에는 찾기 힘듭니다.
  10. 중복코드 최대한 줄여주세요.
    • 너무 복잡해서 실수하는 건 어쩔 수 없겠지만, 신경은 쓰시길 바랍니다. 다 낭비고, 잘못하면 꼬이니까요.
    • 자주 사용하는 함수는 static을 사용하세요. (static을 남용하지 말라곤 하지만, 자주 사용하는 함수는 오히려 static이 효율적일 수 있습니다.)
  11. 공식이나 보정 값, 한 번만 쓰일 값 정도를 제외한 곳에서는 코드에 숫자를 그대로 쓰지 말고 enum이나 Define(const)로 관리해 주세요.
    • enum이나 const로 관리해 주는 것이 범용성 및 유지보수 측면에서 훨씬 좋습니다.
    • 수정 요청이 왔을 때 선언된 곳에서 추가/삭제/변경하면 끝이니까요.
    • 만약에 숫자를 코드에 그대로 입력한다면 - 반년 뒤에 "2"를 "3"으로 바꿔달라는 요청이 왔다면? "2"를 검색해서 바꾸시겠습니까? 몇 백개가 나올 텐데? 검색해서 운 좋게 찾는다 해도 그게 본인이 찾는 "2"가 맞을까요? 만약에 본인이 휴가 중이라면? 다른 작업자가 해야 된다면?

 

권장사항

 - 습관하하면 좋다 싶은 것들 또는 추천하고 싶은 것들

 

  1. 형상관리 프로그램 (git, svn) 커밋하시기 전에 change Log에서 마지막으로 한 번 더 코드를 확인하는 습관을 가지시면 좋습니다.
  2. 커밋 시 리버트 하기 쉽게 작업단위로 커밋하시면 나중에 문제 생겼을 때 원복하기 쉽습니다.
    • A, B 작업이 섞여서 커밋을 하게 되면, 후에 A가 문제가 생겨서 리버트 하면 B의 일부분도 리버트 되겠죠? 바로 에러가 나면 그나마 다행이지만, 에러조차 안 나서 발견 못하면 시한폭탄이 됩니다.
  3. 일정시간 헤매고 있으면 그냥 선임에게 물어보세요. 일정이 우선입니다.
  4. 플랫폼 작업과 같은 히스토리가 중요한 작업은 히스토리를 남기시길 추천드립니다.
    • 예를 들어 플랫폼 업데이트 내역 (버전과 사유), 에러 또는 장애 발생과 수정내역, 
    • 본인이 절대기억 능력자가 아니시라면 히스토리 관리 / 문서화가 협업, 유지보수에 있어 꽤 큰 도움이 될 수 있습니다.
    • (귀찮으시면 정리까진 아니더라도, 히스토리만이라도 카테고리별로 남겨두세요. 그것만으로도 도움이 될 수 있습니다.)
  5. 일정 산정 시에는 작업 단위를 작게 끊어서 생각하시면 더 편합니다.
  6. 일정 산정이 힘드시다면 본인이 작업을 하시면서 작업 전에 예상 일정을 적고, 작업 후 실제 걸린 시간들을 적으면서 연습해 보세요.
    • 일정 산정에 감이 잡히실 거고, 본인의 실력을 객관적으로 판단할 지표로도 쓸 수 있을 겁니다.
  7. "나중에 수정하지 뭐...."하는 생각하지 말아주세요. 안합니다. 99퍼센트, 그 상태로 라이브 나가면 검증된 코드라 더 이상 손대기도 힘들어요.
  8. 어떤 업무적인 행동이나, 의사 결정을 할 때, 그 이유를 명확히 하는 연습을 하세요.
    • 쉽게 예를 들면, 자료구조를 무엇을 사용할 것인가 왜 이게 적합한가, 상속 구조를 어떻게 가져갈 것인가, 작업 우선순위를 어떻게 할 것인가 등등.
    • 상황에 따라 귀찮고 어려울 수 있지만, 어렵다고 안 하는 거랑 하려고 노력하는 거랑은 다르니까요. 저도 여전히 노력하고 있습니다.
    • 일하다 보면 코드뿐 아니라 여러 상황에서 "왜 그렇게 했는가" 질문이 들어올 때가 많습니다. 혼내려고 묻는 게 아니라 상대방도 제 상황과 생각을 모르기 때문에 묻는 겁니다. 본인의 생각을 명확히 말할 수 있다면 좋은 인상은 물론, 상대방과 더 심도 깊은 논의를 할 수 있고, 혹시라도 틀리거나 부족하면 피드백을 받아 더 생각의 깊이를 늘릴 수도 있을 겁니다.
    • 본인이 충분히 생각해 보고 결정한 것을 피드백받는 것과 단순하게 작업해서 피드백 받는 것은 경험의 질이 다를 거라 생각됩니다.
  9. 일을 이해하고 하세요.
    • 지시하달로 업무를 할 때, 그 일이 왜 필요한가 제대로 파악하고 하시길 바랍니다.
    • "왜 이 작업을 하세요" 했을 때 ~가 시켜서요 만큼 힘 빠지는 답변도 없습니다. 
    • 이유를 알고 하는 것과 그냥 누가 시켜서 하는 것은 결과가 질적으로 다릅니다.
    • 이해하기 위해 지시자에게 물어보는 게 참... 어렵죠... 그래도 하는 게 좋습니다... 여의치 않으면 본인이 생각해서 그 의도를 추측이라도 해야 좋겠죠. 
  10. 타 부서가 볼 수 있는 메일은 최대한 간결하고, 명확하게, 초등학생도 이해 가능하게

 

 

 

너무 당연한 것들 아닌가? 하실 수도 있는데, 새로운 환경에 들어서게 되고, 낯선 사람들과 일하게 되면, 당연한 게 당연하지 않게 되더라고요. 직접 겪은 경험담이기도 하면서, 곁에서 여럿 보기도 했습니다.

 

저는 신규 입사자분이 들어오시면 작업하신 코드들을 전부 간단하게라도 확인을 해보고, 피드백을 드리는 편인데, 이 과정에서 생각보다 위의 필수사항에 있는 기초적인 실수들을 많이 보이시더라고요. (기억은 잘 안 나지만, 저도 아마 그랬겠죠) 이후에 같이 일해 보면서 느낀 건 그분들이 실력 문제라기보단 코드파악, 새로운 환경에 따른 긴장, 일정의 다급함 등 다른 요소로 인한 거라 생각이 들더라고요. 사회 초년생들이 당연한걸 왜 안 했지, 왜 몰랐지 하면서 자책을 많이 하기도 하잖아요. 당연한 걸 당연하다고 그냥 넘어가기보단, 한 번 숙지하고 마음가짐을 다잡는 게 조금이라도 도움이 되지 않을까 싶더라고요.

 

아무튼 사회 초년생분들에게 조금이나마 도움이 될 수 있기를 바라며,

이건 어디까지나 제가 겪으면서 생각한 것들이기에, 반박 시 여러분 생각이 맞습니다!

'IT > 기타' 카테고리의 다른 글

IOS 프로비저닝 정리  (0) 2023.11.17
Posted by 검은거북

휴리스틱 길찾기 알고리즘의 대표 / 너비탐색과 다익스트라 알고리즘의 확장판 A* 알고리즘입니다.

 

포스팅 순서는 아래와 같습니다.

  • A* 알고리즘
    • 개요
    • 장단점
    • 구현방법
    • 사용예시

 

 

A* 알고리즘

  • 개요
    • 노드간의 가중치 뿐 아니라 휴리스틱 함수라는 추정값을 기반으로 최단거리를 탐색하는 알고리즘
    • 공식으로는 f (x) = g(x) + h(x)
      • g(x) - 시작노드 부터 현재 노드까지의 가중치 합
      • h(x) - 현재 노드부터 도착 노드까지의 예상 가중치
        • 일반적으로 가중치를 노드 간 거리라 했을 때 도착 노드까지의 대략적인 거리를 의미.
        • 이때 대략적인 거리를 구하는 방식에 따라 또 결과가 달라집니다.
      • 휴리스틱이란? 쉽게 말해 그냥 추정값이라고 보면 됩니다. (대략 이정도 하겠다~ 정도)
        • 그래서 휴리스틱 함수라 하면 추정값을 구하는 방법을 의미합니다. 추정이기 때문에 여러 방법이 있겠죠.
        • 예를 들면, 현재노드에서 목적지까지의 대략적인 거리를 구하는 방법으로 줄자로 제어진 거리, 수학 공식으로 대략적으로 구한 거리, 좌표상으로 구한 거리 등
    • 쉽게 말해 등산하면서 산 위의 정상을 보고 어림짐작으로 가깝겠다 싶은 갈림길을 선택해 가는 겁니다.
    • 결국 A*는 이 휴리스틱 함수에 좌지우지됩니다.
      • 상황에 맞는 적절한 휴리스틱 함수를 결정해야만 좋은 효과를 볼 수 있습니다.

 

  • 장단점
    • 장점
      • 올바른 휴리스틱 함수를 사용하면 보다 빠른 최단거리 길찾기가 가능하다.
      • 주변환경 또는 추정값이 반영된 실질적 최단거리를 찾기 용이하다.
    • 단점
      • 휴리스틱 함수 의존도가 강하다.
      • 최단경로를 결정 이후, 환경에 변동이 있을 시 유연하게 반응하기 힘들다.
  • 구현방법
    • 우선순위 큐 사용 ( 우선순위 정렬요소는 f / 오름차순)
      1. 1. 시작노드를 우선순위 큐에 넣는다.
      2. 2. 우선순위 큐에서 다음 노드를 꺼내 현재 노드로 설정한다. 현재 노드는 지나간 노드 (close list)로 설정한다.
      3. 3. 현재 노드의 주변 노드를 탐색한다.
        • close list에 포함된 노드라면 무시.
        • 만약 우선순위 큐(open list)에 포함되지 않은 노드라면 f(x)값을 구하고, 현재 노드를 주변 노드의 부모로 설정하고, 우선순위 큐에 등록한다.
        • 만약 주변 노드가 이미 open list에 등록되어 있다면, 자신보다 G값이 적은 노드가 있는지 확인하여 해당 노드를 현재노드의 부모노드로 바꾸고 f(x)를 재계산한다. (G값이 크다면 무시)
      4. 4. 목표에 도달할 때까지 2~3을 반복한다.
      5. 5. 목표를 찾으면 거꾸로 부모노드를 쫒아 역정렬하면 최단거리 경로가 된다.

 

  • 사용예시
    • 게임 AI의 길찾기, 미로찾기 등 기본적인 길찾기로 많이 사용.

 

여담

 * A* 알고리즘은 예전에 공부하면서도 느꼈지만, 결국 휴리스틱 함수가 핵심인 듯합니다. 일반적인 예시로 휴리스틱 함수를 최종 도착지까지의 추정 가중치라고하는데, 네비게이션과 같은 변수가 많은 쪽을 예시로 들면, 최종 도착지까지의 실제적인 거리 예상치는 큰 의미가 없을 수 있을 거 같습니다. 그보다는 교통체중, 신호등 갯수, 속도 제한 등이 더 유용해지기도 할 거 같아요. 상황에 따라 노드간 가중치와 휴리스틱 함수를 적절하게 응용할 수 있어야 하지 않을까 싶습니다.

 * 다음은 A*에서 확장된 LPA* 알고리즘을 포스팅하겠습니다.

 

* 포스팅내에 잘못된 내용이나, 문의사항 있으시면 언제든 댓글로 지적해주시면 감사하겠습니다.

Posted by 검은거북

많은 탐색 / 길찾기 알고리즘의 기본이 되는 너비탐색과 깊이탐색입니다. 

 

특히 너비탐색의 경우에는 최단경로 길찾기의 기본적인 탐색 알고리즘입니다. 앞으로 진행할 길찾기 알고리즘 포스팅을 위해 먼저 정리할 목적으로 포스팅을 합니다.

너비탐색과 깊이탐색은 탐색 방법이고, 이를 통해 다양한 길찾기 알고리즘이 파생됩니다. (다익스트라, A* 등)

 

포스팅 순서는 아래와 같습니다.

  1. 너비탐색
    • 개요
    • 장단점
    • 구현방법
    • 사용예시
  2. 깊이탐색
    • 개요
    • 장단점
    • 구현방법
    • 사용예시

 

 

1. 너비탐색 (BFS)

  • 개요
    • 시작 정점으로부터 인접한 거리순으로 주변으로 넓게 퍼지는 탐색
      • 종이에 먹물이 퍼지는 것과 같음.
  • 장단점
    • 장점
      • 로직이 단순하다.
      • 최초 발견 루트를 최단경로라고 보장할 수 있다.
      • 언제나 같은 거리 결과값을 얻을 수 있다.
    • 단점
      • 비교적 많은 저장공간이 필요하다.
  • 구현방법
    • 를 활용하여 구현 ( 선입선출 )
      • 1. 시작 노드를 현재 노드로 설정.
      • 2. 현재 노드를 탐색된 노드로 저장.
      • 3. 현재 노드의 주변 노드 중 탐색되지 않은 노드를 탐색
      • 4. 3번의 노드를 큐에 저장. / 탐색된 노드로 저장.
      • 5. 현재 노드의 주변 노드가 모두 탐색된 노드가 될 때까지 3~4 반복
      • 6. 큐에서 다음 노드를 꺼내 현재 노드로 설정. 
      • 7. 목표에 도착할 때까지 5~6 반복. (전체탐색의 경우, 큐가 빌 때까지 진행.)
  • 예시
      • 최단경로 판별에 유용
      • 길찾기의 기본으로 유용

 

2. 깊이탐색 (DFS)

  • 개요
    • 시작 정점으로부터 각 분기 / 방향 별로 깊게(완전하게) 탐색하고 다음 분기 / 방향으로 넘어가는 탐색
      • 미로찾기와 같음.
  • 장단점
    • 장점
      • 로직이 단순하다.
      • 비교적 적은 저장공간
    • 단점
      • 최초로 구해지는 길이 최단이라는 보장을 할 수 없다.
        • 최단경로 길찾기에 적합하지 않음.
      • 적절한 제한을 두지 않는다면 한쪽 분기에 과도하게 깊이 빠질 수 있음.
        • 재귀함수의 경우 stack overflow 우려 (깊이 제한 필요)
      • 탐색하는 방향 우선순위에 따라 결과가 다르게 나올 수 있다.
  • 구현방법
    • 스택 또는 재귀함수로 구현 (후입선출) 
      • 1. 시작 노드를 현재 노드로 설정.
      • 2. 현재 노드를 탐색된 노드로 저장.
      • 3. 현재 노드의 주변 노드 중 탐색되지 않은 노드 탐색 
      • 4. 3번의 노드를 스택에 저장 / 탐색된 노드로 저장.
      • 5. 현재 노드의 주변노드가 모두 탐색될 때까지 3~4 반복
      • 6. 스택에서 다음 노드 (최근에 들어간) 를 꺼내 현재 노드로 설정.
      • 7. 목표에 도착 또는 전체 순회를 할 때까지 5~6 반복. (전체 탐색의 경우 스택이 빌 때까지 진행)
  • 예시
    • 자동 미로 생성기

 

 

 

 

 

여담

  • 너비탐색과 깊이탐색의 구현방법의 차이는 사실상 큐와 스택입니다. 그 외 돌아가는 기본 로직은 비슷합니다. 
  • 앞으로 4~5 포스팅 동안 길찾기 알고리즘을 시리즈로 할 생각입니다. 최종적으로는 D* lite 알고리즘까지 가는 것이 목표이며, 이를 위해 하나씩 과정을 밟아갈 예정입니다.
    • 하여 이후 길찾기 알고리즘의 순서는 A*, LPA*, D* lite 알고리즘 순으로 포스팅 할 예정입니다.

 

* 포스팅내에 잘못된 내용이나, 문의사항 있으시면 언제든 댓글로 지적해주시면 감사하겠습니다.

 

 

 

Posted by 검은거북

Unity ECS - Hybrid 에 대한 스크립팅 및 사용방법 기록 포스팅입니다.

 

ECS에 대한 설명및 기본세팅은 이전 포스팅으로 - https://zprooo915.tistory.com/66

아래 포스팅은 Unity ECS 샘플 프로젝트의 스크립트를 기준으로 작성하였습니다.

 

이번 포스팅은 아래순서로 진행됩니다.

  1. Hybrid ECS란?
  2. 기본적인 사용방법
  3. 사용 Tip & 오류 및 해결방법

 

1. Hybrid ECS란?

  • 간단하게 기존 Unity의 컴포넌트 방식과 ECS 방식을 융합된 방법입니다.
    • Unity Editor 상에서는 기존 Unity와 동일하게 하이러키와 컴포넌트를 사용하고, 스크립트는 ECS 방식입니다.
  • ECS 방법 자체는 기존 사용자가 바로 사용하기에는 무리가 있을 정도로 에디팅 방식이 많이 바뀌지만, Hybrid 방식으로 둘을 적당히 섞음으로써 ECS 방식을 좀 더 쉽게 접근할 수 있습니다.
  • 장점
    • 진입장벽이 낮다    
    • 기존의 유니티에서 제공하는 시스템을 함께 사용할 수 있다. (ECS만 사용한다면, 새로 만들어야 할 수도 있습니다.) 
  • 단점

 

2. 기본적인 사용방법

 편의상 component - Entity - System 순으로 진행하겠습니다.

 순서는 간단한 설명 후 플레이어블 캐릭터를 예시로 드는 식으로 진행합니다. 

 

Component

 - 하나의 정의에 필요한 데이터 집합

 

  • 아래는 플레이어블 캐릭터의 playerInput 데이터의 집합(컴포넌트) 입니다. 일반 클래스 생성하듯 만듭니다.
public class PlayerInput : MonoBehaviour 
{ 
    public float2 move; 

    public bool jump; 
    public bool seat; 

    public bool attack; 
}

 

  • 그리고 밑은 캐릭터/ 몬스터 누구나 가지고 있을법한 hp에 대한 데이터 집합(컴포넌트) 입니다.
public class Health : MonoBehaviour 
{ 
    public float value;

    public bool isDead;
}

 

  • 위와 같이 하나의 정의에 필요한 데이터 집합들이 component입니다.
    • input에 관련된 요소, Health에 관련된 요소 hp값과 죽었는지 여부입니다.

 

Entity

 - 컴포넌트들의 집합

  •  위의 컴포넌트들을 조합해서 만들어집니다. 기존의 게임오브젝트와 유사하게 생각하시면 됩니다.
  •  위에서 만든 컴포넌트들을 에디터창에서 원하는 오브젝트에 붙이면 됩니다.
    • 각 오브젝트에 필요한 특성과 정의를 부여한다고 생각할 수 있겠네요.
  •  반드시 지켜야 할 것이 ECS의 관리를 받는 오브젝트를 만들려면 Game Object Entity라는 클래스도 오브젝트에 추가해야합니다. (이것을 안하면 System에서 아예 인지를 하지 못합니다.)
  • 아래는 플레이어블 캐릭터의 인스펙터 창입니다.

  • 아래는 체력만 가진 몬스터의 인스펙터 창입니다. ( PlayerInput 빼고는 위와 동일합니다.)

 

 

 System

 - Entity들의 행동로직 

  • 데이터들을 가공하는 곳으로 일반 객체지향의 method와 비슷합니다.
  • 시스템은 방식이 두가지가 있습니다.
    • 두 방식이 어떨 때 좋을지는 정확히는 잘 모르겠네요.
    • 차이점이라면 두번째는 개체수를 얻을 수 있다는 점과 개인적으로 사용했을 때는 여러 엔티티를 가져와 로직을 돌려야 할 경우 두번째 방식이 더 편하고, 하나만 사용할 경우에는 첫번째가 편하더군요.
  • 기본 템플릿

1. 

using UnityEngine; 
using Unity.Entities; 

public class ClassName : ComponentSystem 
{ 
    public struct StructName
    { 
        public ComponentClass name; 
         
    } 
    protected override void OnUpdate() 
    { 
        foreach(var entity in GetEntities<StructName>()) 
        {

            // 로직 진행
            // ex ) entity.name.property = 0;
        } 
    } 
}

 

2.

using Unity.Entities; 
using UnityEngine; 

public class ClassName : ComponentSystem 
{ 
    public struct StructName
    { 
        public readonly int Length; 
        public ComponentArray<ComponentClass > name; 
    } 
    [Inject] 
    private StructName m_data; 

    protected override void OnUpdate() 
    {         
        for(int i = 0; i < m_data.Length; i++) 
        {

            // 로직 진행
            // ex ) m_data.name[i].property = 0; 
             
        } 
    } 
}

 

  • 사용예시

  • 아래는 인풋제어 컴포넌트를 가진 엔티티들을 불러와 키맵핑을 해주는 시스템입니다.
    • 다른 컴포넌트를 가지고 있든말든 인풋제어만 있으면 다 로직이 돕니다.
using UnityEngine; 
using Unity.Entities; 

//사용자의 입력을 input component에 배정하는 시스템 
// 이동 점프 앉기 공격 등 키입력 맵핑 
public class PlayerInputSystem : ComponentSystem 
{ 
    public struct PlayerData 
    { 
        public PlayerInput input; 
         
    } 
    protected override void OnUpdate() 
    { 
        foreach(var entity in GetEntities<PlayerData>()) 
        { 
            entity.input.move.x = Input.GetAxis("Horizontal"); 

            entity.input.seat = false; 
            entity.input.jump = false; 

            if (Input.GetKey(KeyCode.DownArrow)) entity.input.seat = true; 
            if (Input.GetKey(KeyCode.UpArrow)) entity.input.jump = true; 

        } 
         
    } 
}

 

 

  • 아래는 플레이어블 캐릭터의 컴포넌트들을 가진 엔티티들을 불러와 이동시켜주는 시스템입니다.
    • 마찬가지로 PlayerData에 있는 컴포넌트를 가진 모든 엔티티를 불러옵니다.
using Unity.Entities; 
using UnityEngine; 

// 입력된 input에 맞춰 캐릭터 이동  
public class PlayerMoveSystem : ComponentSystem 
{ 
    public struct PlayerData 
    { 
        public readonly int Length; 
        public ComponentArray<PlayerInput> input; 
        public ComponentArray<Health> health; 
        public ComponentArray<Rigibody2D> rigid; 
    } 
    [Inject] 
    private PlayerData m_data; 

    protected override void OnUpdate() 
    { 
        // 병렬로 전체 캐릭터들이 모두 별도로 이동하고, 나중에 한꺼번에 적용 
        float dt = Time.deltaTime; 
        for(int i = 0; i < m_data.Length; i++) 
        { 
            m_data.rigid[i].AddForce(new Vector2(m_data.input[i].move.x * 4, 0)); 
             
        } 
    } 
}

 

  • 아래는 Health를 가진 모든 오브젝트에 대해 죽음 판별하는 시스템입니다.
    • 캐릭터와 몬스터 모두 Health를 가졌으니 모두를 대상으로 돌겠죠
using UnityEngine; 
using Unity.Entities; 

public class HealthCheckSystem : ComponentSystem 
{ 
    public struct PlayerData 
    { 
        public Health health; 
         
    } 
    protected override void OnUpdate() 
    { 
        foreach(var entity in GetEntities<PlayerData>()) 
        { 
            if(entity.health.value <=0) entity.health.isDead = true;

        } 
         
    } 
} 

 

  • 그래서 필요 기능별로 컴포넌트들을 구분지어야 나중에 시스템을 돌릴때 편해지고 직관적이게 됩니다. 오브젝트를 사용할 때도 컴포넌트만으로 제어하기 편합니다.
    • 예를들어 이 캐릭터는 무적인 특성이 있다 했을 때, 예외처리를 하는게 아니라 단지 그 캐릭터에게 Health 컴포넌트만 제거하면 Health에 관련된 모든 로직을 무시할 수 있게되죠.
    • 마찬가지로, 스킬이나 특성들도 컴포넌트만으로 제어할 수 있겠죠.

 

 

3. 사용 Tip & 오류 및 해결방법

  • 시스템 로직 도는 순서 변경하는 방법

    •  기능별로 시스템이 돌기 때문에 간혹 순서상에 문제가 발생할 수도 있습니다.
      •  물론 이런경우를 발생 안시키는게 베스트이긴 하지만, 부득이할 경우 로직 도는 순서를 변경 시킬 수 있습니다.
      • (디폴트로는 생성 순으로 진행되는 것으로 압니다.)
    • 참고 사이트 - https://docs.unity3d.com/Packages/com.unity.entities@0.0/manual/system_update_order.html
    • 방법 
// 타겟 시스템이 SystemClass 이후에 실행되도록 설정
// 같은 시스템 그룹 내에서 동작
[UpdateAfter(typeof(SystemClass))]

// 타겟 시스템이 SystemClass 이전에 실행되도록 설정
// 같은 시스템 그룹 내에서 동작.
[UpdateBefore(typeof(SystemClass))]

// 타겟 시스템을 SystemGroup에 귀속시킴.
// 디폴트로 개발자가 만든 System은 모두 SimulationSystemGroup에 속함.
[UpdateInGroup(typeof(SystemGroup))]


// 사용 예시
// PlayerInputSystem 실행 이전에 TestSystem (타켓시스템)을 실행하도록 설정.
[UpdateBefore(typeof(PlayerInputSystem))]
public class TestSystem : ComponentSystem
{
    public struct PlayerData
    {
        public PlayerInput input;
    }
    protected override void OnUpdate()
    {
        foreach (var entity in GetEntities<PlayerData>())
        {
        }
    }
}

 

  • 여러 엔티티를 하나의 시스템에서 써야할 때

    • 그냥 두개 inject 해오면 된다.
    public struct PlayerData 
    { 
        public readonly int Length; 
        public ComponentArray<PlayerInput> input; 
        public ComponentArray<Transform> transform; 

    } 
    [Inject] 
    private PlayerData p_data; 

    public struct MinimapData 
    { 
        public readonly int Length; 
        public ComponentArray<Minimap> minimap; 

    } 
    [Inject] 
    private MinimapData m_data;

 

  • Tag처럼 쓰기

    • Tag도 하나의 컴포넌트로써 사용하면 된다.
      • ex) Component로 Human클래스를 만들고 아무 내용없이 오브젝트에 붙여만 놓으면, 시스템에서 Human으로 걸러낼 수 있죠.

 

 

 

 

 

 

 

 

Posted by 검은거북

* 먼저 해당 포스트는 튜토리얼이 아닌 Firebase 사용하는 과정에서 발생한 오류 및 해결과정, TIP 중심의 글임을 알려드립니다.  

* Firebase 설명 자체가 굉장히 잘 되어있으므로 튜토리얼은 Firebase를 참고하세요. 여기서 발생한 오류/정보도 Firebase 가이드에 있으나 놓쳤을 확률이 높습니다

 

 

- Functions는 그냥 서버에 본인이 쓸 API 함수를 작성하여 업로드하는 것으로 생각하면 편안.

 - 접근할 서버의 URL = https://us-central1-프로젝트ID.cloudfunctions.net/    

 - 본인이 올린 API 함수는 위 URL을 통해 API 호출하듯 호출하면 된다. POST든 GET이든

    - ex ) https://us-central1-myproject.cloudfunctions.net/myfunc 

 

1. Functions에서의 외부 API 호출시 무시되는 현상.

 - Paypal 에 요청 API를 보냈을 때 아예 무시가 되는 경우가 발생.

 - 무료버전(spark)은 구글 외의 다른 url로 API 접근이 안된다.

    - Blaze 버전으로 업데이트 필요.

 

 

 

 

Posted by 검은거북

ECS 개요는 알겠는데, 대체 얼마나 빨라지길래 스크립팅 방식을 바꿔가면서까지 제공을 하는 걸까요?
그래서 한 번 유니티에서 제공해주는 샘플앱을 이용해 간단하게 벤치마크 테스트 해보았습니다.

 

* 아래 결과는 제 컴퓨터에서 18년 12월 28일 기준으로 수행된 결과입니다.

  * 사양 - i5-6600 / GTX 970 / Ram 15GB

* 실행 프로젝트는 유니티 ECS 샘플 프로젝트의 TwoStickShooter 입니다.

* job system과 burst compiler를 고려하지 않고, 단순히 오브젝트 리젠 갯수를 늘린 결과입니다.

 

* 오브젝트 무한리젠 ( 매 업데이트(0.02)마다 오브젝트 10개씩 생성)

* Classic

Profiler
Game Play Scene

 - 약 30FPS 아래로 내려갈 때의 프로파일링 결과입니다.

 - 총 오브젝트 갯수가 6800개를 넘어가자 어마어마하게 끊깁니다.

 

* hybrid ECS

- 약 30FPS 아래로 내려갈 때의 결과입니다.

- 총 오브젝트 갯수가 21000개 정도 이상되니 끊기네요

- 특이한 점은 classic은 끊기다가 다시 조금 회복되다 또 끊기는 반면에 Hybrid는 더더더 느려집니다.

 

*Pure ECS

- 30 FPS 이하로 떨어지질 않아요 하단 이미지가 실행중인 이미지인데 저 상태에서도 굉장히 부드럽습니다.

- 다만 특이한 점은 총 오브젝트 갯수가 균일하게 약 2000개 밖에 안 찍힙니다. 화면상으로만 봐도 몇 만개는 되보이는데 말이죠. ( 이 부분에 대해서는 좀 더 ECS 시스템에 대한 공부가 필요할 듯하네요)

 

 

 

 

번외로 Pure ECS가 30 FPS 이하로 떨어지는 구간이 대체 언제쯤일지 테스트를 해보았는데, 매 업데이트(0.02초)마다 적 오브젝트를 50개씩 만드니 아래와 같이 떨어지긴 하더군요 (참고로 적오브젝트는 계속 총알 오브젝트를 날립니다)

 

Result

- 거의 성능 차이가 classic을 1이라 했을 때, hybrid가 3, pure가 5~10 정도로 차이가 나는 듯 보이는 것 같습니다.

 

* 다음 포스팅부터는 hybrid ECS를 사용하는 방법 및 사용하면서 발생했던 오류 위주로 포스팅 시작하도록 하겠습니다.

 

 

* 유니티 샘플 프로젝트 경로를 같이 올리려했는데 반년 사이에 많은 변화가 있었는지 git 저장소에 TwoStickShooter를 비롯해 제가 가진 예전 샘플들이 없어졌더군요 ; (너무 바뀌어서 같은 프로젝트인지도 확실치 않지만 최근 샘플을 공유드립니다.)

 - git https://github.com/Unity-Technologies/EntityComponentSystemSamples

* 글을 쓰는 날(19.5.19)을 기준으로는 ECS 벤치마크 데이터가 빈번하게 검색되어 나오는 것 같네요. 더 궁금하시면 영문으로 찾아보시면 만족할만한 자료가 나올 듯 합니다.

 

* 개인이 공부하며 하는 포스팅이기에 잘못된 부분이 있을 수 있습니다.

 혹시 잘못되거나 문제시 되는 부분이 있으면 지적 부탁드립니다.

Posted by 검은거북
이전버튼 1 2 3 4 이전버튼

블로그 이미지
프로그래밍 공부 요약 및 공부하며 발생한 궁금증과 해결과정을 포스팅합니다.
검은거북

공지사항

Yesterday
Today
Total

달력

 « |  » 2024.5
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

최근에 올라온 글

최근에 달린 댓글

글 보관함