경일게임아카데미 멀티 디바이스 메타버스 플랫폼 개발자 양성과정 20220721 2022/04/04~2022/12/13

Jinho Lee·2022년 7월 21일
0

경일 메타버스 20220721 16주차 4일 수업내용. 유니티 & C# - 좀비 서바이버 : 열거형, 반복자 메소드, 코루틴, 애니메이션 - 전진운동학 & 역운동학, 레이캐스트, 확장 메소드, C#의 다형성

정리

열거형

  • 문법은 C++와 같으나 몇 가지 차이점이 있음
    1. 열거형으로 만든 기호상수 사용 시 꼭 열거형을 앞에 적어줘야 함. 즉, 이름 공간이 따로 있음.

      ex) State.Ready

    2. int 타입으로 암시적 형 변환 불가능. 명시적 형 변환 해야 함.

    3. C++보다 좀 더 풍성한 기능 지원

반복자 메서드(Iterator Method)

  • IEnumerable / IEnumerator를 반환 타입으로 가지는 메서드

  • 반복자 메서드에서는 yield문 사용 가능. yield문을 만나면 실행을 중단한다.

    • yield return : 반환값과 함께 중단
    • yield break : 반환값 없이 중단
  • MoveNext()가 호출될 때마다 이전에 중단됐던 지점부터 실행하며, 메서드가 끝나거나 yield문을 만날 때까지 실행한다.

코루틴(Coroutine)

  • 반복자 메소드를 활용해 함수의 명시적 실행 없이도 내부적으로 알아서 실행 시켜주는 시스템

  • 시간 혹은 순차적 처리를 구현할 때 직관적으로 코드를 작성할 수 있어 유용하다.

  • WaitForSeconds : ~초 동안 중단

운동학

  • 순운동학(FK; Forward Kinematics) :
    상위 조인트의 변환에 따라 하위 조인트도 같이 변환이 되는 것

  • 역운동학(IK; Inverse Kinematics) :
    하위 조인트의 변환에 따라 상위 조인트도 같이 변환이 되는 것

  • OnAnimatorIK() : IK가 적용될 때마다 호출

    • SetIKPositionWeight()
    • SetIKPosition()
    • SetIKRotationWeight()
    • SetIKRotation()

레이어

  • 레이어는 씬에 존재하는 게임 오브젝트를 구분할 수 있게 해주는 도구

  • 충돌 검출에 활용

  • 레이어 마스크를 이용하면 성능 향상의 이점이 있음.

레이캐스트

  • Ray를 기반으로 충돌 검출을 하는 것

  • Physics.Raycast()

확장 메소드

  • 확장 메소드(Extension Method)는 기존 타입에 메소드를 추가할 수 있게 한다.

  • 정적 메소드로 구현하며, 첫 번째 매개변수에 this 키워드와 함께 확장시킬 타입을 적는다.

  • 확장 메소드는 확장하는 타입의 private에 접근할 수 없다.
    즉, 캡슐화의 원칙을 위배할 수 없다.

C#의 객체 지향 프로그래밍

  • 가상 함수는 virtual 키워드를 붙인다.

  • 오버라이딩은 override 키워드를 붙인다.

  • 추상 클래스 / 메소드를 만들려면 abstract 키워드를 붙인다.

    • 추상 메소드는 반드시 자식에서 오버라이딩을 해야 한다.

C#의 열거형

  • 문법은 C++과 거의 같으나 몇 가지 차이점이 있다.

    1. 열거형의 선언 시 반드시 이름을 지어주어야 한다.

    2. 열거형으로 만든 기호상수를 사용할 때 꼭 열거형의 이름을 앞에 적어줘야 한다.
      즉, 이름 공간이 따로 있다.
      ex) State.Ready

    3. int 타입으로 암시적 형 변환이 불가
      반드시 캐스팅(명시적 형 변환)을 해야 한다.

    4. C++보다 좀 더 풍성한 기능 지원

  • 열거형 형식 예시 코드

public enum State
{
	One,
	Two,
	Three
}

State.One;
public State state { get; private set };

반복자 메소드(Iterator Method)

  • IEnumerable / IEnumerator반환 타입으로 가지는 메소드

  • yield문 사용 가능

    • yield : 영어로 “양보하다”는 뜻

    • yield return :
      반환 값과 함께 중단

    • yield break :
      반환 값 없이 중단

  • MoveNext() 메소드가 호출될 때마다 이전에 중단됐던 지점부터 실행하며,
    메소드가 끝나거나 yield문을 만날 때까지 실행한다.

  • 예시 코드

    IEnumerator<int> TestIteratorMethod()
    {
        yield return 1;
        yield return 2;
        yield return 3;
        yield return 4;
        yield return 5;
        yield return 6;
        yield return 7;
        yield return 8;
        yield return 9;
        yield return 10;
    }
    
    IEnumerator<int> enumerator = TestIteratorMethod();
    
    while(enumerator.MoveNext())
    {
        Console.WriteLine(enumerator.Current);
    }
  • 위 코드를 실행해보자.

    • 결과 :

      컨테이너처럼 가상의 배열에 값을 저장하고,

      enumerator가 값을 순회한다.

      위의 IEnumerator 타입 enumerator에 할당할 때에도,

      TestIteratorMethod 함수 본문은 실행되지 않는다.

      enumerator.MoveNext()는 호출되면서

      이전에 실행한 위치(마지막 실행)을 기억하고,

      그 곳으로 돌아가 yield에 걸리면 "양보”하고

      다음 yield로 넘어가 return을 실행하면서 값을 반환한다.

  • 이러한 반복자 메소드를 응용한 것이 코루틴(Coroutine)이다.

코루틴(Coroutine)

  • Coroutine : 도와주는 함수라는 의미.

  • 명시적 실행 없이도 내부적으로 알아서 실행을 시켜주는 함수

    • 코루틴을 StartCoroutine으로 등록만 해준다면 호출 없이도 알아서 실행한다.

    • 시간 혹은 순차적 처리를 구현할 때 직관적으로 코드를 작성할 수 있어 유용하다.

  • C#의 반복자 메소드를 이용해 구현되었다.
    yield문의 활용 등

  • 코루틴은 멀티스레드가 아니며,
    싱글스레드인 유니티 이벤트 스크립트 라이프사이클 안에 포함되어있다.

    • 유니티 스크립트 라이프사이클 상에서,
      yield 코루틴모든 Update 함수끝난 후에 실행된다.
  • StartCoroutine(코루틴) :
    코루틴을 시작한다, 등록한다.

  • WaitForSeconds() :
    ~초 동안 중단

  • 기존 델타타임을 활용한 코드와 코루틴을 활용한 코드의 비교

    // 델타타임 활용
    void Update()
    {
        _elapsedTime += Time.deltaTime;
        if(_elapsedTime >= 0.5f)
        {
            _elapsedTime = 0f;
    
            GameObject bullet = Instantiate(BulletPrefab, transform);
            bullet.transform.LookAt(Player);
        }
    }
    
    // 코루틴 활용
    StartCoroutine(Shot());
    
    IEnumerator Shot()
    {
        while (true)
        {
            GameObject bullet = Instantiate(BulletPrefab, transform);
            bullet.transform.LookAt(Player);
    
            yield return new WaitForSeconds(0.5f);
        }
    }

레이캐스트(Raycast)

  • 특수한 충돌 처리

  • 발사된 광선이 다른 콜라이더와 충돌하는 지 검사하는 처리

  • Ray 타입

    • 광선(레이)의 정보
  • RaycastHit 타입 오브젝트

    • 레이와 충돌한 단일 게임 오브젝트 / 충돌 위치 / 충돌 표면 방향 등의 정보
  • bool Physics.Raycast // 오버로딩이 매우 많다. 아래는 한 얘시
    (Vector3 origin, Vector3 direction, out RaycastHit hitInfo, float maxDistance, int layerMask, QueryTriggerInteraction queryTriggerInteraction);

    • 무언가에 충돌을 하면 true
    1. origin :
      레이의 시작점

    2. direction :
      레이의 방향

    3. out hitInfo :
      레이가 충돌한 경우 out 키워드로 간접 참조된 충돌 정보

    4. maxDistance :
      레이 충돌을 검사할 최대 거리

    5. layerMask :
      충돌 처리를 무시할 레이어

레이어 기반 충돌 감지 :
오브젝트 인스펙터 상단, tag의 옆 layer는 tag처럼 오브젝트들을 묶어주는 역할이지만,
그 묶어진 그룹 내에서만 충돌할 수 있게 설정할 수 있다.

  • RaycastAll()
    • 일직선의 레이투과하여 충돌(접촉)한 모든 게임 오브젝트와 그 정보를 반환

전진 운동학 & 역운동학

  • 전진 운동학(순운동학; FK; Forward Kinematics) :
    큰 관절의 변화에 의해서 작은 관절들의 위치, 회전이 영향을 받는다.

  • 역운동학(IK; Inverse Kinematics) :
    작은 관절들의 변화에 의해서 큰 관절의 위치, 회전이 영향을 받는다.

    • Unity에도 IK를 지원하는 애니메이션 관련 메소드 / 이벤트가 있다.

확장 메소드

  • C#에서 지원하는 확장 메소드외부 패키지(타입)사용자가 정의한 메소드추가할 수 있다.

  • 조건

    1. 정적 메소드로 구현한다.

    2. 첫 번째 매개변수this 키워드와 함께 확장시킬 타입을 적는다.

    3. 확장하는 타입private접근할 수 없다.
      캡슐화의 원칙을 위배할 수 없다.

다형성

  • C#에서의 가상 함수

    • 가상 함수 키워드 virtual

    • 오버라이딩 키워드 override

    • 순수 가상 함수 (추상 클래스) 키워드 abstract

      • 상속 받으면 구현(오버라이딩)강제한다.

      • 강제성을 부각한다.

      • 인터페이스와 유사

        • 인터페이스와의 차이점

          • 문법적인 관점에서,
            추상 클래스는 클래스이고
            인터페이스는 클래스가 아닌 인터페이스이다.
            때문에

            • 추상함수 :

              1. 하나만 상속 가능

              2. 메소드 뿐만 아니라 필드 등의
                다양한 데이터

              3. 객체 역할을 정의

            • 인터페이스 :

              1. 여러 개를 상속 가능

              2. 메소드만 보유

              3. 메시지만을 정의

  • 예시 코드

    class Base
    {
        public virtual void Foo() { Console.WriteLine("Base의 Foo"); }
    }
    
    class Derived : Base
    {
        public override void Foo()
        {
            base.Foo();
        }
    }
    
    abstract class AbstractBase
    {
        public abstract void Foo();
    }
    
    class Derived2 : AbstractBase
    {
        public override void Foo()
        {
        }
    }

0개의 댓글