1. PCG란?
- 알고리즘을 이용해 자동으로 다양한 콘텐츠를 생성하여 게임의 다양성과 재생성을 높이는 기술
1) 사용 분야
- 게임 디자인: 랜덤화된 맵, 레벨, 퀘스트, 적 배치 등을 생성
- 지형 생성: 자연 경관, 도시, 던전 등의 복잡한 지형을 자동으로 생성
- 텍스처 및 모델 생성: 다양한 텍스처와 3D 모델을 생성하여 게임의 비주얼을 풍부하게 하고, 아트 자원을 효율적으로 관리
- 시뮬레이션: 가상 환경에서의 데이터 생성이나 복잡한 시스템의 시뮬레이션을 위해 사용되며, 예를 들어 생태계나 도시 시뮬레이션 등에 적용
2. PCG 셋업(프로젝트 생성 및 플러그인) 및 나무 생성하기
- 언리얼 엔진5의 Plug-in에서 PCG를 검색 후 아래 두 개의 플러그인을 설치
- Preocedural Content Generation Framework
- Preocedural Content Generation Framework Geometry Script Interop
- FAB에서 Black Alder 검색 후 프로젝트에 추가
- New Level 로 Basic 레벨 생성. 새 폴더(Map)을 만들고 저장하기
- 기존의 Floor 지우고 랜드스케이프 생성하기
- Tool Strength 0.1로 완만한 언덕을 만들어주기
- Selection 모드로 돌아가서 PCG Graph로 가서 모드를 설정할 것
- Content 안에 새로운 폴더를 만들어 PCG로 지정. 그 안에 PCG 그래프를 만들기
- PCG Graph로 들어가서 Get Landscape Data 생성하기
- 뷰포트에 PCG Graph를 드래그 하고 크기를 키워서 언덕에 배치하기
- 표면에 배치하겠다는 Surface Sampler 노드 생성
- 랜드 스케이프 데이터를 가져와 표면에 생성하겠다는 것
- 노드를 눌러 d를 누르면 배치할 위치들의 포인트들이 보이게 됨
- 컬러는 강도를 보여주는 것. (흰색 1, 검정 0)
- 포인트들마다 메쉬를 할당할 수 있는 노드인 Static Mesh Spawner 생성하기
- Mesh 검색 후 Mesh Entries에서 Static Mesh 안에 PCG_Seedling_01 선택
- 다시 Surface Spawner에 D를 누르면 확인이 됨
- Staic Mesh Spawner에 E를 눌러 Disable 시키고 Surface Sampler에 A를 눌러 포인트들의 속성을 확인
- 점의 개수, 밀도를 조정해보기. Points Per Squared Meter를 늘려봤자 PointExtents가 넓으면 소용이 없음. 그러므로 이 값을 줄여줘야 영향을 받음
- Looseness 점 사이의 간격. 숫자가 늘면 간격이 넓어짐. 밀도는 Point Extents의 영향을 받음. 작으면 작을 수록 많이 생김
- 잔디를 만들 땐 밀도가 높고 많아져야 함. 값을 설정 후 Static Mesh Spawner에 E를 눌러 켜기
- 나무 심어보기. 많을 필요가 없어서 다음과 같이 값 설정 후 메쉬 바꾸기
- 다른 나무 종류도 넣기 위해 Mesh Entries에 Index를 추가해서 다양한 메쉬 넣기
- 게임 모드로 나무가 어떻게 보이는지 확인하기
- 나무 방향의 회전과 크기도 랜덤하기 바꿔보기
- Transform Points 노드를 생성해서 연결. 최대 값 및 최소 값을 조정해서 범위 내에서 크기가 조정되도록 하기
- 나무에 가까이 못가는 이유는 Surface Sampler에 겹쳐졌기 때문
- 고해상도 모델을 실시간으로 렌더링할 수 있게 하여, 디테일을 유지하면서 성능을 최적화를 위해 나무 메쉬의 나나이트를 모두 켜주기
- 잔디를 깔기 위해 PCG Graph로 이동해 잔디용 노드 만들어 놓기
- transforms spawner에 rotation Max Z 를 360로 설정
- 3개의 메쉬를 넣어주기
- 밟고 지나가기 위해 콜리전 없애기 → 세 가지 모두 No collision
- 크기를 최소 0.05 최대 0.1로 설정
- 움직이는 것 방지하기 위해 해당 잔디 메쉬의 머티리얼의 부모를 찾아가 마스터 머티리얼을 수정 → 두 가지 노드의 연결을 끊기
- 메쉬의 크기에 개입되지 않고 포인트의 바운드 크기만 줄이기 → Bounds Modifier
- 잔디의 양을 늘리기 위해 설정값 변경
- 나무 근처에는 잔디가 없게 하기 → Differnece 노드 생성
- Differnece의 강도를 설정하기
- 나무의 위치를 올곧게 하기 위해서는 Transform Points 노드에서 Absolute Rotation 체크
3. PCG 돌 만들기
- PCG 기본 노드 셋팅을 하고 Static Mesh에 돌 메쉬를 넣은 후 나나이트도 켜주기
- 바위가 너무 많고 가깝기 때문에 겹쳐있으면 겹친 것 중 하나를 빼도록 함 → Self Pruning
- 바위 근처에는 잔디가 안자라도록 하기 위해 Foliage의 Differnce 노드에 Self Pruning연결. 영역이 너무 넓어 Bounds Modifier를 한 번 더 추가해 영역 줄여주기
- 바위와 잔디 사이의 영역을 조절하기
- Distance를 Foliage 부분과 연결하고 Set Density 체크 후 값을 200정도로 설정하기
- 잔디 Modifier를 1로 수정하면 보임
- Density Noise 노드를 검색해서 추가 (Attribute Noise로 보임)
- 서서히 랜덤을 주겠다 → Mode : Add
- Output Target도 Density로 설정
- Density Filter노드를 추가하고 Lower Bound를 0.3으로 설정
- Stone의 Bounds Modifier으로 돌과 잔디 사이 영역 크기를 조절
4. 파라미터 만들기
- Graph Setting을 눌러 Parameters에 가서 추가
- PCG Component 클릭, 만든 파라미터 활성화
- Stone에 Math를 검색하면 뜨는 Multiply 노드 연결. Input B에는 내가 만든 파라미터를 검색해서 가져와서 연결. Input Source1을 Scale로 변경
- 파라미터 값을 바꾸면 메쉬의 크기를 키울 수 있음
- 파라미터를 2개 더 생성해서 나무와 잔디의 크기를 조절할 수 있게 함
- 기본 값은 모두 1로 설정
- 밀도도 파라미터로 조절하기. 밀도는 Surface Sampler에서 관여
- 파라미터를 만들고 이걸 Surface Sampler 항목들에 연결
- Self Pruning으로 완전히 다 붙지는 않음
- Tree와 Foliage의 Density, Looseness의 파라미터를 만들어서 노드 연결
- 메쉬를 교체할 수 있는 Parameter 만들기. Type을 Static Mesh → Object Reference 로 하고 Array로 변경
- Move Up / Down으로 파라미터 항목 정리하기
- Tree에 Match And Set Attrubutes 노드 생성 후 연결
- 뒤의 Multiply의 Output Target을 Scale로 변경해주기
- Mesh Selector Type을 바꾸고 Tree Meshes 파라미터를 Match Data와 연결
- 빼 올 데이터인 Attrubute의 이름을 정확히 적어주면 연결 완료
- 같은 방식으로 Foliage, Stone도 같이 메쉬 변경 파라미터 만들어주기
- Math : Multiply를 꺼내 0.1을 곱하도록 함
- 상수를 쓸 때 Create Attribute를 꺼내 사용함. Type을 Float로 하고 0.1로 설정
- 다음과 같이 연결 후 , Looseness에도 연결
- 갯수를 설정할 수 있도록 만들어보기
- Content 안에 Structure 폴더를 만들고 블루프린트 Structure 생성
- 편집창에서 Mesh로 이름을 바꾸고 Static Mesh로 타입을 바꾸기
- 아까 만든 Structure를 선택
- Mesh의 이름을 바꾸고 Math Weight Attribute를 활성화해서 Weight로 이름 설정
5. 길 만들기
- 스플라인을 만들고 이를 따라서 패스를 만드는 방법 익히기
- Blueprint 폴더를 만들어 Blueprint Actor를 생성하기
- 편집창 내 Components에서 Add Spline하기
- 태그를 하면 어딘가로 부를 수 있음
- 스플라인을 뷰포트로 불러와서 길을 만들기
- PCG Graph에서 Geet Spline Data와 Spline Sampler를 불러와 연결
- All World Actors로 설정
- Tag에 아까의 PathSpline 입력
- Bound Modifier를 생성하고 min max의 Y 값을 100으로 설정
- 거리마다 생기도록 Distance로 바꿈
- 길에 잔디, 돌, 나무가 닿지 않도록 Projection 노드 생성 후 Differnce 노드와 연결
- 길을 부드럽게 하기 위해 Steepness 켜기
닫힌 형태의 스플라인 만들기
- 블루프린트 액터 생성 후 Components에 Spline 추가, Tag를 생성(ClosedSpline)
- Spline Generation Panel로 형태를 잡기
- Closed Loop로 하나로 연결시키기
- 점 위가 아닌 점 안에 샘플링을 해야 함 → On Interior
- 듬성듬성 하게 만들기 위해 Density noise 노드 생성 후 Density Filter를 연결
- 더 듬성듬성 하력면 Select points로
- 잔디가 안나도록 Density filter에서 Inverse filter 체크를 사전 설정을 하고, Difference를 연결
- 자주 쓰는 노드 두 개를 하나로 묶을 수 있음
- 노드 검색이 되도록 노드 안으로 들어가 Expose to Library 체크
- PCG 인스턴스를 만들어서 가공해서 쓸 수있음 (원본 변형 X)
- 만든 PCGI (인스턴스) 적용
6. 레이 히트(RayHit)
- 물리적 상호작용이나 충돌 감지를 위해 사용되는 기술
- 특정 지점에서 시작하여 주어진 방향으로 레이를 쏘는 방식으로 작동. 레이가 어떤 오브젝트에 부딪히면, 그 충돌 정보를 반환하게 됨
- 블루프린트 클래스 → 액터 생성
- Add에서 PCG 컴포넌트 생성 후 PCG 그래프도 생성해서 저장
- Box Collision도 생성. 크기는 70 70 70
- 이 블루프린트 클래스를 뷰포트로 이동. 내부에 액터배치
- PCG_RayHit가 생성되고, 여기 그래프에서 Surface Sampler, World Rayt Hit Query 생성 후 연결, 디버그
- 다음과 같이 Settings 값 변경
- 액터의 크기를 키울 땐 강제 재생성(Force Regen)
- Collision 을 BlockAll로 설정
- World Static이 Block이 될 것인가가 중요
- Ignore Landscape Hits는 바닥 부분은 포인트들이 무시된다는 것
- HitMesh라는 태그를 만들고 액터들에도 태그를 달면 적용됨
- 다시 No Tag Filter로 바꿈
- PCG그래프에 노드를 만들어 Static Mesh를 스폰시킬 것
- 메쉬를 생성할 수 있는 노드 셋팅
- 잔디를 모으기 위해 Gather
- 스테틱 메쉬를 넣어서 적용해주기
- Use Complex Collision As Simple은 Sandstone의 Collision Complexity를 좀 더 단순하게 허용하겠다는 설정
- PCG_RayHit도 Collision BlockAll로 설정
- 랜드의 히트는 무시하도록 Ignore Landscape Hits 체크, 셀프 히트가 무시된 것은 체크
- Loseness로 가까이 붙여주고, Transform Points를 조정해서 좀 더 자유로운 배치로 만들기
- 이제 풀을 심어보자
- 풀 부분의 Static mesh는 Nocollision으로 설정
- 볼륨 안쪽에만 생성이 됨
- Collision 충돌 영역에만 생성이 되기 때문에 확인 필요
7. 메쉬 샘플러(Mesh Sampler)
- 나무, 돌 뿐 아니라 나무에 버섯 달기
- 메쉬에 포인트를 달고, 조건을 설정해서 할당하자
- PCG Graph를 생성하기
- 공유받은 파일 중 나무 하나와 버섯 액터들 셋팅
- 액터를 가져오기 위해 Get Actor Data 노드 생성
- 나무 오크 트리 하나에만 생성을 위해 Mode를 Get Single Point로 지정
- Static Mesh Spawner에 오크를 넣고 다음과 같이 노드들 연결
- 뷰포트에 PCG 그래프를 옮기기
- 정확한 숫자 계산을 위해 Set으로 설정
- 위치 변경에 따라 랜덤 값을 주고 싶음. → Transform Points
- 나무 크기를 유지하기 위해 Absolute Scale → 절대 크기를 유지
- 메쉬 샘플러와 오크 나무 기둥을 연결해보기
- 너무 많은 포인트가 잡혀서 Self Pruning으로 좀 더 듬성한 느낌으로
- 위쪽으로만 자랄 수 있게 Z축 노말 방향 이용하기. 위쪽에만 밀도를 주겠다
- Z축으로 조금 아래로, Transform 값 설정
- 랜드스케이프에 메쉬샘플러 나무 파일 적용해보기
- MeshSampler 복붙 → Sub MeshSampler
- Input에 Input이름 지정하고 타입은 point
- 검색할 때 나올 수 있도록 Exposes Library
- 나무의 크기를 알아야 함
- 랜드스케이프 PCG에서 만든 Sub Mesh Sampler 노드 가져오기
- 랜드스케이프 맵에 나무 오크들이 많이 적용됨
- 풀과 나무에 겹쳐지지 않도록 셋팅하기
- Difference에 연결해서 겹쳐지지 않도록 설정 → Sub Meshsampler 안에서 Difference해주기
- 인풋 하나 더 만들어서 DifferenceMask 이름 지정
- 타입은 공간정보 : Spatial → 공간정보를 받아와서 Difference를 하겠다
- Dencity Function : Binary
- 나무 / 돌 / 길이 생기는 곳에 오크가 안 생기도록 Differnce Mask 연결
- 풀이 자란 곳 위는 생성되어 있고 길, 나무, 돌과 겹쳐지지 않은 지 확인
'4. 언리얼 엔진(Unreal Engine) 공부 > Unreal Engine 5' 카테고리의 다른 글
25. [UE5] Dialogue 대화 기능 구현 - 작성중 (0) | 2024.11.11 |
---|---|
24. [UE5] NPC 만들기(정적/동적/Socket) (2) | 2024.11.03 |
23. [UE5] UI Interaction(Widget) (0) | 2024.10.30 |
22. [UE5] 다른 액터와 캐릭터가 상호작용 하기(Overlap, CutScene, LevelBlueprint) (1) | 2024.10.23 |
21. [UE5] 블루프린트를 위한 프로그래밍 기초 (1) | 2024.10.18 |