언리얼4의 함정(?)들

Lee Raccoon·2024년 5월 13일
0

언리얼 공부

목록 보기
4/11
post-thumbnail

NDC 2016 프로그래머를 괴롭히는 언리얼4의 함정들
오래된 자료이고 언리얼 4이지만 현업자들의 언리얼에 대한 분노가 흥미로워서 정리해보기로 했다.
아니 근데 2016년의 화질이 이정도인가..

코드 수정 후 컴파일 했는데 적용이 안돼요

발표자님이 말해주신 해결 방법은 에디터 껐다 끄기이다.

내 생각이 맞다면 이 때는 핫리로드 시절이고 라이브 코딩이 없던 시절이었지 않을까?
강의 등을 통해 지금의 나는 헤더나 오브젝트의 생성자 부분에 변경이 있다면 에디터를 끄고 다시 빌드하고, 구현부는 라이브 코딩으로 진행한다는 방법을 알고 있지만 그 당시는 참 골치 아팠을 것 같다.

저장이 안돼요

에디터가 두 개 켜져 있을 확률이 높다. 위 내용 같은 상황 때문에 에디터를 계속 껐다 켰다 하게 되는데 그러다가 일어나는 실수가 아닐까 싶다.

블루프린트를 상속해서 뭔가를 만들 때


가끔 일어나는 현상이라서 안그럴수도 있다고 하는데, 힘든 작업은 아니니 따로 만든 후 부모 클래스를 바꿔주도록 해야겠다.

블루프린트의 주의할 특성

  • 블루프린트 안에 있는 멤버 변수는 스태틱 변수이다.

    예를 들어 캐릭터에 TagMarker라는 화살표를 보였다가 10초뒤에 안보이게 하는 이벤트가 있는데, 이걸 두 캐릭터에서 파랑은 0초에, 초록은 5초에 시작시키면 파랑은 10초에 초록은 15초에 사라질 것 같지만 초록이 10초에 꺼져버린다는 것이다.
    근데 이건 좀.. 이게 진짜라면 진짜 쉽지 않을 것 같은데? 라는 생각으로 테스트를 해봤다.
    일단 이런걸 신경쓰고 개발을 해본적도 없었기 때문에 무서웠다.

    어 근데 잘 되는데..?
    UE5을 쓰고 있어서 그런가 언리얼이 고쳐줬나보다. 그래 블루프린트 변수가 인스턴스끼리 공유가 되버리면 인스턴스를 쓰는 이유가..

오브젝트 생성자에서 쓰면 안되는 것

오브젝트 생성자에서 쓰면 안될 것들에 대해 이야기 해주고 있다.

허허 나는 오브젝트 생성자가 엔진 초기화 때 불러진다는 걸 알고 있지.
때문에 이해가 되는 부분이다.

하지만 SubObject 생성은 꼭 생성자에서 해줘야함을 명심하자

매크로관련

  • UFUNCTION(BlueprintCallable) 사용 시 에러
    꼭 카테고리를 붙여줘야한다고 한다.
    근데 이건 UE5에서는 안그러니 아마 고쳐준 듯 하다.

  • 변수와 함수의 인자가 동일할 때 에러
    이건 UE5에서도 그러길래 인자 이름을 바꿔서 어떻게든 해결했던 기억이 있다.
    이유는 generated.h 헤더를 만들어줄 때 두 개의 심볼이 겹치기 때문이라고 한다.

리플리케이션

지금 생각해도 정신이 나가버릴 것 같은 리플리케이션이다.
알아보도록 하자.

TMap<>은 리플리케이션이 안된다

UE4를 사용할 일이 있다면 주의해야겠다.. 리스트 두개를 쓰는 등의 꼼수를 사용한다고 한다.

변수 리플리케이션 주의점

A=0을 정의한다.
서버에서 A=1 이후 클라이언트의 리플리케이션 함수를 호출하는 이벤트를 발생시킨다.
호출된 리플리케이션 함수에서 A를 불러오면 A는 1이겠지? -> 아니다.
변수 리플리케이션은 항상 틱 마지막에 일어난다.

리플리케이션 함수(RPC) 주의점

일단 하나하나 일아보기 전에 주의점 부터 써보겠다.

  • Actor에서 호출 되어야 한다.
  • Actor는 Replicated 여야 한다.
  • 서버에서 호출, 클라이언트에서 실행의 RPC
    해당 Actor를 실제 소유하고 있는 클라이언트에서만 함수가 실행됨
  • 클라이언트에서 호출, 서버에서 실행의 RPC
    클라이언트는 RPC가 호출되는 Actor를 소유해야 함

RPC의 종류

  • 리플리케이트 되지 않음
  • 서버에서 실행
  • 멀티캐스트
  • 소유 클라이언트에서 실행

리플리케이트 되지 않음

  • 서버는 서버, 클라이언트는 클라이언트의 함수를 실행한다.
  • 서버와 클라이언트 둘 다 실행할 수 있는 함수가 있다면
    그 함수가 실행됐을 때 대체 어디서 실행됐는지 찾아야하는 건 프로그래머의 몫..

서버에서 실행

상자를 여는 경우
상자를 리플리케이션으로 설정하고 서버에서 이를 실행하면 모두에게서 상자가 열리겠지? -> 아니다.
대체 왜? 라고 생각한다면 위의 주의점을 보자

서버에서 호출, 클라이언트에서 실행의 RPC
해당 Actor를 실제 소유하고 있는 클라이언트에서만 함수가 실행됨

상자는 클라이언트가 소유하고 있는 액터가 아니다. 그러므로. 상자는 열리지 않는다.
처음 리플리케이션을 쓸 때 이걸 몰라서 대체 며칠을 내다 버렸는지 모른다..

멀티캐스트

무려 멀티캐스트 (모두에 리플리케이트 됨)인 이 친구는 모두에서 실행이라는 말로 쉽게 해결해줄 것 같이 생겼지만?

(서버인 경우)

내가 만약 키보드 입력을 받아서 리플리케이트 시키려고 하면? 키보드 입력은 플레이어(클라이언트)라서 리플리케이트 되지 않고 클라이언트에서만 실행된다.

아하 ! 그럼 플레이어 컨트롤러에서 입력을 받아서 서버에서 멀티캐스트를 호출하는 방법으로 가면 되겠구나 ! -> 안된다.
플레이어 컨트롤러에서는 서버랑 자기 클라이언트만 멀티캐스트 적용이 된다고 한다.
근데 플레이어 캐릭터에서는 전체 멀티캐스트가 된다(?)
이게 대체 무슨,,

소유 클라이언트에서 실행

여기서는 재밌는 일이 벌어지는데, AI는 서버가 소유자이기 때문에 클라이언트에서 AI의 함수를 호출하면 클라이언트에서 실행되는게 아니라 서버에서 실행이 된다.

아니 그럼 대체 상자를 어떻게 여는데


복잡해서 캡쳐를 떠왔다. 아니 상자 하나 여는데 무슨..
플레이어컨트롤러에서 키보드 입력을 받아서 서버로 리플리케이션 시킨다.
서버에서 모든 상자를 불러서 상자를 여는 함수(멀티캐스트)를 호출한다.
그럼 짜잔하고 상자가 다 열린다.

절망편

나와 상대편과 AI의 캐릭터가 모두 같은 클래스를 사용한다면..
서로가 서로를 공격하는 이벤트는.. 누가 누구를 때리는지 모두 따로.. 오우 쉣

그래도 진짜 글만 있었으면 정신이 나가버렸을 것 같은데 마지막에 멋지게 도식화해서 보여주셔서 참 좋았다.
그건 링크를 타고 들어가서 보도록 하자. 너무 많기 때문에..

profile
영차 영차

0개의 댓글