머터리얼 인스턴스에서는 scalar, texture, vector 파라미터 값을 얻을 수 있다.
머터리얼 인스턴스 당 여러 개의 Texture parameter = 텍스처 슬롯의 이름 – 텍스처 경로 정보
텍스처 파라미터 값 얻기
레벨에 존재하는 모든 StaticMeshActor에 특정 머터리얼 인스턴스 부여하기
언리얼 Python API와 블루프린트의 유사성
레벨 블루프린트에서도 비슷한 방식으로 머터리얼을 스태틱 메시 액터에 적용할 수 있다.
파이썬 API로 진행했을때와 다른 점은 애셋을 직접 변경하지 않고 런타임에서만 확인할 수 있다는 점이다. StaticMeshComponent의 GetNumMaterials 노드를 사용하여 메시에 몇 개의 머터리얼이 사용되었는지 확인할 수 있고, 이것은 드로 콜이 많은 메시를 시각적으로 파악하는데 사용할 수 있다.
- sky Lighting과 shadow는 루멘에서 파이널 게더의 일부가 됨, 야외보다 훨씬 어두운 실내 공간을 표현할 수 있게 해줌
- 낮은 퀄리티의 일루미네이션을 반투명 및 볼류메트릭 포그에 제공한다.
- 이미시브 머터리얼은 루멘의 파이널 게더를 통해 추가 비용 없이 라이트를 전파할 수 있다.
- 간접 스페큘러나 리플렉션을 머터리얼 러프니스 값의 제한 없이 해결한다.
- 더 이상 라이트맵을 구울 필요가 없다.
- 모바일을 지원하지 않음
루멘을 사용하면 스태틱 라이팅에서 사전 연산된 라이팅이 제거된다.
사전 연산 라이팅 비활성화 : 프로젝트 세팅 > 스태틱 라이트 허용 체크 해제
- 셰이더 퍼뮤테이션(셰이더 분리)으로 스태틱 라이팅 오버헤드를 줄일 수 있다.
또한 머터리얼 앰비언트 오클루전 입력을 지원하고 머터리얼 bent 노멀이 루멘 글로벌 일루미네이션과 연동된다.
1. Surface Cache : 루멘은 주변 씬의 표면에 대한 자동 파라미터화를 생성한다.
씬에서 레이가 히트되는 지점의 라이팅을 빠르게 확인할 때 사용한다. 카드들로 구성된다.
카드 : 각 메시의 머터리얼 프로퍼티를 여러 각도에서 캡처한다. 캡쳐 포지션을 카드라고 부른다. 기본적으로 메시 하나당 카드를 12개만 배치하지만 스태틱 메시 에디터에서 Max Lumen Mesh Cards 세팅으로 조정할 수 있다. 복잡한 인테리어에서 늘리면 유용하다.
각 메시에 대하 오프라인으로 생성된다.
2. 스크린 트레이싱 : 스크린에 대해 레이 트레이싱, 루멘 씬과 트라이앵글 씬 간의 불일치 해소
- 히트가 발견되지 않거나 표면 뒤로 지나가면 안정적인 메서드를 사용한다.
- 다수의 트레이싱 메서드 중 먼저 사용된다.
3. 레이 트레이싱 : 소프트웨어 레이트레이싱은 다양하게 동작, 하드웨어는 특정 기기에서만 동작
소프트웨어 레이 트레이싱 : Signed Distance Field에 사용됨 프로젝트 세팅에서 Generate Mesh Distance Field가 활성화 되어있으면 됨
하드웨어 레이 트레이싱 : 다양한 종류의 지오메트리 타입을 지원
루멘으로 작업하기
루멘과 소프트웨어 레이 트레이싱의 요구 사항 : 셰이더 모델5, Direct3D 11 이상을 지원하는 디바이스
루멘은 언리얼5 프로젝트에 기본으로 활성화되어 있다. 프로젝트 세팅 > 렌더링 > Global illumination
하드웨어 레이 트레이싱은 기본 활성화가 아니라서 수동으로 켜줘야 함
- 하드웨어 레이 트레이싱에서의 리플렉션 : Ray Lighting Mode를 선택할 수 있음, Surface Cache vs Hit Lighting for Reflections 전자 성능 후자 퀄리티
소프트웨어 레이 트레이싱을 사용할 떄 어디에 사용할 지 고를 수 있음 Detail Tracing vs Global Tracing 전자 퀄리티 후자 성능
포스트 프로세스 볼륨이 GI와 리플렉션 방식을 오버라이드 할 수 있다는 점을 주의해야 한다.
루멘의 한계
라이트맵의 스태틱 라이팅과 함께 사용할 수 없다.
폴리지도 제대로 지원되지 않는다.
루멘의 파이널 게더는 이동 오브젝트에 상당한 노이즈 현상이 발생한다.
반투명에 대한 리플렉션 지원X
소프트웨어 레이 트레이싱의 한계
스태틱 메시, 인스턴스드 스태틱 메시, 계층형 인스턴스드 스태틱 메시, 랜드스케이프만 루멘 씬에 표시될 수 있다.
서버가 클라이언트의 최신 상태를 유지하기 위해 주로 사용하는 것은 액터이다. 서버가 특정 클라이언트를 업데이트할 때가 되면, 서버는 지난 번 업데이트 이후 변경되었다고 보는 연관 액터 전부를 수집한 다음 해당 액터의 최신 상태를 유지하기에 충분할 만큼의 정보를 클라이언트에 전송한다.
네트워크 모드의 종류
1. NM_Standalone
ㄴ 로컬 머신에서 실행되며 원격 머신에서 클라이언트를 받지 않는 서버. 싱글 플레이어, 로컬 멀티플레이 게임에 적합
2. NM_DedicatedServer
ㄴ 로컬 플레이어가 없어 그래픽, 사용자 입력, 플레이어 관련 기능을 처리하지 안하도 되어 효율적인 실행이 가능한 전용 서버, 퍼포먼스가 중요해서 신뢰성있는 서버가 필요한 경우에 사용된다.
3. NM_ListenServer
ㄴ 로컬 플레이어가 있는 서버(호스트로). 원격 플레이어에게도 접속을 허락한다.
ㄴ 데디케이티드 서버가 불필요한 경쟁 또는 협력 게임에 좋다.
ㄴ 호스트에게는 네트워크 지연 시간이 없어 유리하게 작용할 여지가 있다.
ㄴ 호스트에 의해 게임이 중단될 수 있다.
4. NM_Client
ㄴ 1~3은 서버 모드고, 4번은 클라이언트 모드
ㄴ 2, 3 서버에 접속할 수 있다.
ㄴ 서버측 로직은 실행되지 않는다.
에디터에서 테스트할 때는 Editor Preferences > Level Editor > Multiplayer Options에서 네트워크 모드를 지정해 테스트할 수 있다.
캐릭터의 스켈레탈 메시와 애니메이션 블루프린트 등의 겉모습을 표현하는 컴포넌트는 리플레케이트되지 않습니다. 하지만 캐릭터의 속도와 같이 게임플레이 및 무브먼트와 연관성이 있는 변수는 리플리케이트되며, 애니메이션 블루프린트는 업데이트될 때 이러한 변수를 읽어 들입니다. 게임플레이 변수가 정확하게 업데이트되면 각 클라이언트 측 캐릭터 사본 또한 시각적 표현을 업데이트할 것입니다.
RepNofity로 플레이어 체력 리플리케이트하기
플레이어에게는 게임플레이 도중 대미지를 가할 수 있는 체력 값이 필요합니다. 이 값은 모든 클라이언트가 각 플레이어의 체력에 대해 동기화된 정보를 갖도록 리플리케이트되어야 하며, 대미지를 입는 플레이어에게 피드백을 제공해야 합니다
ThirdPersonMPCharacter.h
/** 플레이어의 현재 체력. 0이 되면 죽은 것으로 간주됩니다.*/
UPROPERTY(ReplicatedUsing=OnRep_CurrentHealth)
float CurrentHealth;
/** 현재 체력에 가해진 변경에 대한 RepNotify*/
UFUNCTION()
void OnRep_CurrentHealth();
발사체가 오브젝트에 충돌할 때 호출할 함수, 유효한 액터와 부딪힐 경우 ApplyPointDamage 함수를 호출하여 발생한 위치에 대미지를 가하며, 발사체는 소멸된다.
//발사체 충돌 함수를 히트 이벤트에 등록
if (GetLocalRole() == ROLE_Authority)
{
SphereComponent->OnComponentHit.AddDynamic(this, &AThirdPersonMPProjectile::OnProjectileImpact);
}
서버만 이 게임플레이 로직을 실행하도록 OnProjectileImpact 등록 전에 GetLocalRole() == ROLE_Authority 을 확인합니다.
발사체 발사하기 (RPC 함수 사용하기)
UPROPERTY(EditDefaultsOnly, Category="Gameplay|Projectile")
TSubclassOf<class AThirdPersonMPProjectile> ProjectileClass;
/** 발사 딜레이, 단위는 초. 테스트 발사체의 발사 속도를 제어하는 데 사용되지만, 서버 함수의 추가분이 SpawnProjectile을 입력에 직접 바인딩하지 않게 하는 역할도 합니다.*/
UPROPERTY(EditDefaultsOnly, Category="Gameplay")
float FireRate;
/** true인 경우 발사체를 발사하는 프로세스 도중입니다. */
bool bIsFiringWeapon;
/** 무기 발사 시작 함수*/
UFUNCTION(BlueprintCallable, Category="Gameplay")
void StartFire();
/** 무기 발사 종료 함수. 호출되면 플레이어가 StartFire를 다시 사용할 수 있습니다.*/
UFUNCTION(BlueprintCallable, Category = "Gameplay")
void StopFire();
/** 발사체를 스폰하는 서버 함수*/
UFUNCTION(Server, Reliable)
void HandleFire();
발사체 발사에 사용할 변수와 함수입니다. HandleFire 는 이 튜토리얼에서 구현하는 유일한 RPC로, 서버에서 발사체를 스폰합니다. Server 지정자가 있기 때문에 클라이언트에서 이를 호출하려는 모든 시도는 네트워크를 통해 서버의 권위 있는 캐릭터로 전달됩니다.
HandleFire 에는 Reliable 지정자도 있기 때문에 호출될 때마다 신뢰할 수 있는 RPC의 큐 등록에 배치되며, 서버가 수신에 성공하면 큐 등록에서 제거됩니다. 이는 서버가 이 함수의 호출을 확실하게 수신하도록 보장합니다. 그러나 너무 많은 RPC가 제거 없이 동시에 배치되면 신뢰할 수 있는 RPC의 큐 등록이 추가분을 유발할 수 있으며, 그 경우 사용자가 강제로 연결 해제됩니다. 그러므로 플레이어가 이 함수를 호출하는 빈도에 주의해야 합니다.
HandleFire 는 서버 RPC이며 CPP 파일의 구현에서는 반드시 함수 이름에 접미사 _Implementation 이 추가되어야 하기 때문입니다. 여기서의 구현은 캐릭터의 회전 제어를 사용하여 카메라가 향한 방향을 구한 다음 해당 방향으로 발사체를 스폰하여 플레이어가 조준할 수 있게 합니다. 그러면 발사체의 발사체 무브먼트 컴포넌트가 해당 방향을 향한 이동을 처리합니다.
HandleFire_Implemetation이 아닌 HandleFire으로 선언했어도 빌드 과정에서 HandleFire_Implementation 선언부가 생성되는듯 하다.