요리사 가 소 를 풀 어 달라 고 부탁 했다. 그 컴 파일 러 가 숨 긴 것 과 U3D 가 준 것 (상)

0x 01 관찰자 모드 부터
디자인 모델 에서 우리 가 자주 사용 하 는 디자인 모델 인 관찰자 모델 이 있다.그렇다면 이런 디자인 모델 은 우리 의 주제 인 '유 니 티 3D 에서 의뢰 를 어떻게 사용 하 느 냐' 와 무슨 관계 가 있 을 까?서 두 르 지 말고 먼저 관찰자 모드 가 무엇 인지 이야기 합 시다.
우선 신문 과 잡지 의 구독 이 어떻게 된 일 인지 살 펴 보 자.
신문사 의 임 무 는 바로 신문 출판 이다
4. 567917. 한 신문사 에 그들의 신문 을 구독 하고 그들 이 새로운 신문 이 출판 되면 너 에 게 발급 할 것 이다.즉, 당신 이 그들의 구독 고객 이 라면 새로운 신문 을 계속 받 을 수 있다 는 것 이다
이 신문 이 더 이상 필요 하지 않 으 면 구독 을 취소 할 수 있다.취소 되면 신문 사 는 다 시 는 새로운 신문 을 보 내지 않 을 것 이다
4. 567917. 신문사 와 구독 자 는 서로 다른 주체 로 신문사 가 계속 존재 하기 만 하면 서로 다른 구독 자 는 구독 하거나 취소 할 수 있다
만약 에 독자 여러분 이 제 가 위 에서 말 한 신문 과 잡 지 를 어떻게 구독 하 는 지 알 수 있다 면 여러분 도 관찰자 모델 이 어떻게 되 는 지 알 게 될 것 입 니 다.명칭 이 다른 것 을 제외 하고 관찰자 모드 에 서 는 신문사 나 출판 자 를 '주제' (Subject) 라 고 부 르 고 구독 자 는 '관찰자' (Observer) 라 고 부른다.위의 신문사 와 구독 자의 관 계 를 관찰자 모드 에 이식 하면 다음 과 같이 된다. 주제 (Subject) 대상 은 특정한 데 이 터 를 관리 하고 주제 안의 데이터 가 바 뀌 면 이미 구독 (등록) 한 관찰자 에 게 알 리 고 이미 등 록 된 주제 의 관찰자 에 게 이때 주제 데이터 가 바 뀌 었 다 는 통 지 를 받 고 업데이트 된다.등록 하지 않 은 대상 은 통지 되 지 않 는 다.
우리 가 관찰자 모델 을 그 리 려 고 할 때 신문 구독 서비스 나 출판 자 와 구독 자 를 비교 할 수 있다.실제 개발 에서 관찰자 모델 은 다음 과 같이 정의 된다.
관찰자 모드: 대상 간 의 다 중 의존 을 정의 합 니 다. 그러면 대상 이 상 태 를 바 꿀 때 모든 의존 자 는 알림 을 받 고 자동 으로 업 데 이 트 됩 니 다.
그렇다면 이렇게 많은 관찰자 모델 의 내용 을 소 개 했 으 니 의뢰 라 고 해 야 하지 않 겠 습 니까?예, C \ # 언어 는 의뢰 를 통 해 리 셋 함 수 를 실현 하 는 메커니즘 이 고 리 셋 함 수 는 매우 유용 한 프로 그래 밍 메커니즘 으로 관찰자 모드 에 광범 위 하 게 사 용 될 수 있 습 니 다.
그렇다면 유 니 티 3D 자체 가 이런 메커니즘 을 제공 하고 있 는 것 일 까?답 도 긍정 적 이다. 그렇다면 의뢰 와 는 어떤 차이 가 있 을 까?다음은 이 화 제 를 이야기 합 시다.
0x 02 유 니 티 3D 의 SendMessage 와 BroadcastMessage 에 안녕 이 라 고 말 합 니 다.
물론 유 니 티 3D 게임 엔진 의 등장 은 게임 개발 자의 큰 복음 임 을 부인 할 수 없다.그러나 유 니 티 3D 의 게임 스 크 립 트 구조 에 결함 이 있다 고 할 수 밖 에 없다.좋 은 예 는 이 절 에서 말 하고 자 하 는 SendMessage 와 BroadcastMessage 를 중심 으로 구 축 된 메시지 시스템 이다.Unity3D 의 이 메시지 시스템 에 결함 이 존재 하 는 이 유 는 SendMessage 와 BroadcastMessage 가 반사 메커니즘 (reflection) 에 지나치게 의존 하여 메시지 에 대응 하 는 리 셋 함 수 를 찾기 때문이다.빈번 한 사용 반 사 는 자연히 성능 에 영향 을 줄 수 있 지만 성능 의 손실 은 가장 심각 한 문제 가 아니다. 더욱 심각 한 문 제 는 이런 메커니즘 을 사용 한 후에 코드 의 유지 보수 비용 이다.왜 이렇게 하 는 것 은 매우 나 쁜 일이 라 고 말 합 니까?하나의 방법 을 문자열 로 표시 하면 많은 위험 이 발생 할 수 있 기 때문이다.예 를 들 어 개발 팀 의 한 개발 자가 일부 코드 를 재 구성 하기 로 결정 했다 면 공교롭게도 이 부분 코드 는 이러한 메시지 에 호출 될 수 있 는 방법 으로 정 의 될 수 있 는 코드 입 니 다. 그러면 방법 이 이름 을 바 꾸 거나 삭제 되면 심각 한 위험 을 초래 할 수 있 습 니까?정 답 은 yes.이런 위험 의 무 서운 점 은 컴 파일 시 오류 가 발생 할 수 있 는 것 이 아니 라 반대로 이런 위험 의 무 서운 점 은 컴 파일 러 가 잘못 보고 하지 않 고 개발 자 에 게 어떤 방법 이 이미 이름 이 바 뀌 었 고 심지어 존재 하지 않 는 다 는 것 을 알려 주 는 것 이다. 정상 적 인 운행 절차 에 직면 하여 경각 심 을 가지 지 않 는 것 이 가장 무 서운 것 이다. 그리고 언제 이 위험 이 폭발 할 까?특정 정 보 를 촉발 시 켜 대응 할 방법 을 찾 지 못 할 때 도 있 지만 이 럴 때 는 문제 가 너무 늦 어 지 는 경우 가 많다.
또 다른 잠재 적 인 문 제 는 반사 체 제 를 사 용 했 기 때문에 유 니 티 3D 의 이 메시지 시스템 도 개인 적 인 방법 으로 호출 할 수 있다 는 것 이다.그러나 개인 적 인 방법 이 성명 류 의 내부 에서 사용 되 지 않 았 다 면 정상 적 인 생각 은 모두 이것 이 폐 코드 라 고 생각 할 것 이다. 왜냐하면 이런 외부 에서 누군가가 그것 을 호출 할 수 없 기 때문이다.그렇다면 폐 코드 에 대한 태 도 는 무엇 일 까?많은 개발 자 들 이 이 폐 코드 를 없 애 는 것 을 선택 할 것 이 라 고 생각 합 니 다. 그러면 똑 같은 위험 이 발생 할 것 입 니 다. 컴 파일 할 때 문제 가 없 을 수도 있 고 심지어 프로그램 도 한동안 정상적으로 실 행 될 수 있 지만 특정한 메 시 지 를 촉발 하고 대응 하 는 방법 이 없 으 면 바로 이런 위험 이 발생 할 때 입 니 다.따라서 유 니 티 3D 의 SendMessage 와 BroadcastMessage 에 안녕 이 라 고 말 할 때 가 되 었 습 니 다. C \ # 의 의뢰 를 선택 하여 자신의 메시지 체 제 를 실현 합 시다.
0x 03 인식 반전 함수 메커니즘 --- 의뢰
비 위탁 관리 코드 C / C + 에 도 유사 한 리 셋 메커니즘 이 존재 하지만, 이 비 구성원 함수 의 주 소 는 메모리 주소 일 뿐이다.이 주 소 는 함수 의 매개 변수 개수, 매개 변수 유형, 함수 의 반환 값 유형 등 추가 정 보 를 가지 고 있 지 않 기 때문에 위탁 관리 C / C + 코드 가 아 닌 리 셋 함 수 는 유형 이 안전 하지 않다 고 말 합 니 다.한편, C \ # 에서 제공 하 는 리 셋 함수 의 메커니즘 은 바로 의뢰 이 고 유형 이 안전 한 메커니즘 이다.의뢰 를 직관 적 으로 이해 하기 위해 서 우 리 는 먼저 코드 를 살 펴 보 자.
using UnityEngine;

using System.Collections;


public class DelegateScript : MonoBehaviour

{  

    //        ,          
    internal delegate void MyDelegate(int num);

    MyDelegate myDelegate;

    void Start ()
    {

        //    MyDelegate   myDelegate     

        // PrintNum

        myDelegate = PrintNum;

        myDelegate(50);

        //    MyDelegate   myDelegate     

        //DoubleNum       

        myDelegate = DoubleNum;

        myDelegate(50);

    }

    void PrintNum(int num)
    {
        Debug.Log ("Print Num: " + num);
    }

    void DoubleNum(int num)
    {
        Debug.Log ("Double Num: " + num * 2);
    }
}

다음은 이 코드 가 하 는 일 을 살 펴 보 겠 습 니 다.처음에 우 리 는 internal 의뢰 유형 인 MyDelegate 의 성명 을 볼 수 있 었 다.의뢰 는 리 셋 방법 서명 을 확인 해 야 합 니 다. 매개 변수 와 리 턴 유형 등 을 포함 합 니 다. 이 예 에서 MyDelegate 가 의뢰 한 리 셋 방법의 매개 변수 유형 은 int 형 이 고 리 턴 유형 은 void 입 니 다.
DelegateScript 류 는 인쇄 에 들 어 오 는 매개 변수 와 인쇄 에 들 어 오 는 매개 변수의 두 배 기능 을 각각 구현 하 는 두 가지 개인 적 인 방법 인 PrintNum 과 DoubleNum 도 정의 했다.Start 방법 에서 MyDelegate 류 의 인 스 턴 스 my Delegate 는 각각 이 두 가지 방법 을 인용 하고 이 두 가지 방법 을 각각 호출 했다.
이 를 보면 독자 여러분 들 이 궁금 증 을 가 질 수 있 을 지 모 르 겠 습 니 다. 왜 한 가지 방법 이 이렇게 my Delegate = PrintNum 을 만 들 수 있 는 지 모 르 겠 습 니 다.'할당' 의뢰 하나 드릴 까요?이것 은 C \ # 2 가 의뢰 에 제 공 된 방법 그룹 전환 을 제기 할 수 밖 에 없다.C \ # 1 을 거 슬러 올 라 가 는 의뢰 메커니즘, 즉 매우 원시 적 인 의뢰 메커니즘 에서 의뢰 실례 를 만 들 려 면 의뢰 유형 과 호출 할 방법 을 동시에 지정 해 야 하기 때문에 방금 그 코드 는 다음 과 같이 바 뀌 어야 한다.
new MyDelegate(PrintNum);

C \ # 1 시대 로 돌아 가도 이 줄 은 새로운 의뢰 인 스 턴 스 를 만 드 는 코드 가 개발 자 에 게 나 쁜 인상 을 주지 않 는 것 처럼 보이 지만 긴 표현 식 의 일부분 이 라면 지루 함 을 느 낄 수 있 습 니 다.새로운 스 레 드 를 시작 할 때 표현 식 이 뚜렷 한 예 입 니 다.
Thread th = new Thread(new ThreadStart(Method));

이렇게 보면 C \ # 1 의 방식 은 간결 하지 않 은 것 같다.따라서 C \ # 2 는 의뢰 를 위해 방법 그룹 전환 체 제 를 도입 했다. 즉, 방법 에서 호 환 되 는 의뢰 유형의 암시 적 전환 을 지원 한다.우리 가 처음 예 에서 했 던 것 처럼.
//        ,      
//               
//      
myDelegate = PrintNum;
Thread th = new Thread(Method);

이 메커니즘 을 방법 그룹 전환 이 라 고 하 는 중요 한 이 유 는 적재량 이 많 기 때문에 한 가지 방법 만 적용 되 는 것 이 아 닐 수도 있다 는 것 이다.예 를 들 어 다음 코드 가 보 여 준 것 처럼:
using UnityEngine;
using System.Collections;

public class DelegateScript : MonoBehaviour
{  
    //        ,          

    delegate void MyDelegate(int num);

    //        ,          

    delegate void MyDelegate2(int num, int num2);

 

    MyDelegate myDelegate;

    MyDelegate2 myDelegate2;


    void Start ()
    {
        //    MyDelegate   myDelegate     
        // PrintNum
        
        myDelegate = PrintNum;
        
        myDelegate(50);
        
        //    MyDelegate2   myDelegate2     
        //PrintNum            

        myDelegate2 = PrintNum;

        myDelegate(50, 50);

    }

    void PrintNum(int num)
    {

        Debug.Log ("Print Num: " + num);

    }

    void PrintNum(int num1, int num2)
    {

        int result = num1 + num2;

        Debug.Log ("result num is : " + result);

    }
}

이 코드 에는 두 가지 방법 이 있 습 니 다. 이름 이 같은 방법 입 니 다.
void PrintNum(int num)

void PrintNum(int num1, int num2)

그러면 방법 그룹 전환 메커니즘 에 따라 하나의 MyDelegate 나 하나의 MyDelegate 2 에 값 을 부여 할 때 PrintNum 을 방법 그룹 (이때 2 개의 PrintNum 이 있 기 때문에 '그룹') 으로 사용 할 수 있 고 컴 파일 러 는 적당 한 리 셋 버 전 을 선택 할 수 있 습 니 다.
물론 의뢰 와 관련 된 또 다른 특징 은 의뢰 매개 변수의 역 변성 과 의뢰 반환 유형의 협 변성 이다.이 특성 은 많은 글 에서 도 소 개 된 적 이 있 지만 여기 서 독 자 를 더욱 깊 은 인상 을 주기 위해 의뢰 의 이러한 특성 을 구체 적 으로 소개 해 야 한다.
인 스 턴 스 인용 방법 을 의뢰 할 때 C \ # 인용 유형의 협 변성 과 역 변성 을 허용 합 니 다.협 변성 이란 방법의 반환 유형 이 의뢰 의 반환 유형 에서 파생 될 수 있 는 파생 류 를 말한다. 즉, 협 변성 은 의뢰 반환 유형 을 묘사 한 것 이다.역 변성 이란 방법 으로 얻 은 매개 변수의 유형 은 의뢰 한 매개 변수의 유형의 기본 클래스 일 수 있 으 며, 다시 말 하면 역 변성 묘 사 는 의뢰 한 매개 변수 유형 이다.
예 를 들 어 우리 프로젝트 에 존재 하 는 기초 단위 류 (BaseUnitClass), 병사 류 (SoldierClass) 와 영웅 류 (HeroClass), 그 중에서 기초 단위 류 인 BaseUnitClass 는 기본 클래스 로 병사 류 SoldierClass 와 영웅 류 HeroClass 를 파생 시 켰 다. 그러면 우 리 는 하나의 의뢰 를 정의 할 수 있다. 아래 와 같다.
delegate Object TellMeYourName(SoldierClass soldier);

그러면 우 리 는 이 의뢰 유형의 인 스 턴 스 를 구성 하여 다음 과 같은 원형 을 가 진 방법 을 참조 할 수 있다.
string TellMeYourNameMethod(BaseUnitClass base);

이 예 에서 TellMeYourNameMethod 방법의 매개 변수 유형 은 BaseUnitClass 이 고 TellMeYourName 이 의뢰 한 매개 변수 유형 SoldierClass 의 기본 클래스 입 니 다. 이러한 매개 변수의 역 변성 은 허 용 됩 니 다.한편, TellMeYourNameMethod 방법의 반환 값 유형 은 string 이 고 TellMeYourName 이 의뢰 한 반환 값 유형 Object 에서 파생 된 것 이기 때문에 이러한 반환 유형의 협 변성 도 허용 된다.그러나 한 가지 지적 해 야 할 것 은 협 변성 과 역 변성 은 인용 유형 만 지원 하기 때문에 값 유형 이나 void 라면 지원 하지 않 는 다 는 것 이다.다음은 다음 과 같은 예 를 들 어 TellMeYourNameMethod 방법의 반환 형식 을 값 형식 int 로 바 꾸 면 다음 과 같 습 니 다.
int TellMeYourNameMethod(BaseUnitClass base);

이 방법 은 반환 형식 이 string (참조 형식) 에서 int (값 형식) 로 바 뀌 는 것 을 제외 하고 아무것도 바 뀌 지 않 았 습 니 다. 그러나 이 방법 을 방금 의뢰 인 스 턴 스 에 연결 하려 면 컴 파일 러 가 잘못 보고 할 수 있 습 니 다.int 형 은 string 형 과 마찬가지 로 Object 류 에서 파생 되 지만 int 형 은 값 유형 이기 때문에 협 변성 을 지원 하지 않 습 니 다.이 점 은 독자 여러분 이 실제 개발 에서 반드시 주의해 야 합 니 다.
자, 이제 우 리 는 의뢰 에 대해 초보적인 직관 적 인 인상 을 가 져 야 한다.이 절 에서 저 는 의뢰 가 코드 에서 어떻게 사용 되 는 지, 그리고 C \ # 2 를 통 해 도 입 된 방법 팀 전환 체 제 를 의뢰 사례 로 적당 한 방법 과 의뢰 의 협 변성 과 역 변성 을 직관 적 으로 인식 하도록 이 끌 었 습 니 다.그럼 이 절 은 여기 서 끝내 고 더 나 은 탐색 의뢰 를 하 겠 습 니 다.

좋은 웹페이지 즐겨찾기