1. Directional right
: 멀리 있는 광원을 모티브로 제작된 오브젝트로, 위치는 상관이 없지만 각도(Rotation)에 따라 그림자의 위치가 달라진다.
: 각도를 바꾸다보면 어두워지는데 광원때문이라기보단 Light Box - Sky Box 형태 때문.
- Light - Type :
Spot: 연극같은 것 할 때, 특정 위치만 쏠 때.
Point: 이 공간에만 은은하게 퍼지는 빛.
Area: 특정 공간을 설정해두고 그 공간에만 빛이 나오는, 예를 들면 천장의 전등같은것. 근데 이건 베이크 단계를 거쳐서 맵을 만들어야 쓸 수 있다.
- Color : 광원의 색깔.
컴퓨터에서 진행하는 작업은 대부분 2의 배수.
이게 색상 명도 채도.
H: 색상
S: 채도
V: 명도
A: 알파값. 조명에선 별로 쓸 일이 없음. UI의 스프라이트 이미지 같은 다른 건 영향을 받음.
색상코드도 입력 가능.
Swatches : 게임에 주로 사용되는 배색들을 할 때마다 수치를 넣는 것이 귀찮으니까 체크 시, 프리셋에 저장함.
- Mode : 조명의 빛반사에 대한 품질 설정.
RealTime : 빛이 반사하며 산란하는 색들의 값을 실시간으로 계산해서 그래픽을 그려준다. 고사양. 사실적인 표현에 좋음.
Mixed : RealTime과 Baked 두 가지를 섞어서 효율적인 부분을 Baked로, 사실적으로 보일 곳은 RealTime으로 계산.
Baked : 산란되는 빛의 값을 한 번 계산하여 저장하는 것(빵을 굽다의 그 Bake). 저장된 정보값으로 저장된 시점의 값을 계속 쓰기에 연산 부하를 줄일 수 있다. 저사양 디바이스.
- Intensity : 조명의 밝기 정도. 클수록 밝아지고 0이 될 수록 어두워짐.
- Shadow Type : 그림자의 품질 설정.
Resolution : 그림자의 퀄리티 선택 가능.
2. 조명(Lighting)
- 직접 조명: 빛을 받아 직접적으로 반사가 되어 빛나는 부분.
- 간접 조명(반사광): 다수의 조명들이 전부 각자의 위치에서 빛이 쏴져 물체에 부딪혔을 때, 빛을 튕겨내고 색깔을 보이도록 산란하는 부분. 사람 피부를 표현할 때, 분명 살색인데 파란 물감을 섞어 표현하듯 주변 환경의 색깔을 같이 표현하곤 한다.
왼쪽은 물체의 색이 있지만 명암이 없는 상태(≒텍스쳐만 입힌 상태).
가운데는 조명이 하나만 있으며 직접조명만 있는 상태. 조명이 직접 비치는 부분만 볼 수 있다.
오른쪽은 보다 현실에 가까운, 빛이 주변으로 산란하며 반사광에 입에 물체에 색이 입혀진 상태.
유니티에서 조명을 다루기 위해선 새로운 창을 열어야 한다.
Window → Rendering → Lighting
3D 게임엔 워낙 자주 사용해서 Inspector창 옆에 두고 쓰기도 한다.
뉴 라이트 세팅을 누르면 아래에 파일이 생긴다. 파일은 어떤 폴더에 있든 상관 없지만 일단 Scene에 넣기로 했다.
- Realtime Lighting
Realtime Global Illu : 씬 전체적으로 산란하는 외곽같은 부분의 빛들을 연산하겠다는 의미. 굳이 고사양게임이 아니면... 체크 해제.
- Mixed Lighting
Baked Global Illumi : 위의 연산을 저장해 이용하겠다는 것인데 해제.
위에서 Directional Light 조정하며 밤이 되고 그런 것이 Skybox 설정때문이라 했는데, 이는 게임 화면상에 보여지는 배경을 의미하지 씬이나 카메라의 배경은 아니다. 공백을 어떻게 보여줄 것인가를 의미한다.
- Skybox Material : 직접 제작할 수 있다. 보통 Skybox로 되어있는데 재밌게도, None으로 하면 화면에 대한 표현이 없어져 어두워보인다.
- Environment Lighting - Source : 오브젝트들에게 각 색깔에 대한 간접조명이 들어가게 한다. 단순하지만 효율적인 방법.
Skybox : 설정된 스카이박스로 조명을 넣는다.
Gradient : 그라데이션으로 조명을 조명을 넣는다. 하늘의 색, 지평선의 색, 땅의 색을 각각 정할 수 있다.
Color : 한 가지 색으로 정한다.
3. Navigation
애너미들이 돌아다니는 구역을 설정한다.
일단 먼저, 움직이지 않는 오브젝트들은 Transform값이 변경되지 않도록 고정시킬 수 있다.
Level(≒맵)의 Inspector창에서 Static 체크.
당연히 레벨 안에 있는 모든 오브젝트들을 고정시킬 것이기 때문에 Yes.
이제 Window → AI → Navigation.
돌아다니는 애너미의 설정이 Agent.
돌아다닐 영역을 저장(Bake)한다.
- Agent Radius : 원기둥(=실제로 움직일 수 있는 공간)의 넓이. 맵상의 콜라이더들엔 겹쳐지면 안되니까, 이런 콜라이더를 기준으로 근처에 못 가게 한다.
파란 원기둥 근처의 회색 선은 '콜라이더를 기준으로 어느 정도의 여백을 두고 움직이게 설정할거냐'는 의미이다.
여기까지 Bake하면 씬에 파란 부분이 보이는데 이게 돌아다닐 수 있는 영역이다.
그 외 Agent Height는 높차나 경사 있는 맵에서나 쓰이는 것이라 패스.
4. 카메라 컴포넌트Camera Component
씬에 기본적으로 생성되는 그 카메라.
카메라 오브젝트엔 위치 정보 외에 Camera와 Audio Listener 라는 컴포넌트가 기본적으로 있다.
오디오는 객체들이 내는 사운드에 가까이 갈수록 소리가 크게 잡히고 멀어지면 작게 잡히는 것을 말한다.
때문에 씬 상에 하나의 오브젝트에만 붙어 있는 것이 좋다.
- Depth : 카메라의 순서. 당연히 0이 첫 번째이다.
- Clipping Planes : 카메라의 시야 범위 정도.
Near : 적혀진 숫자보다 작아지면 잘라낸다.
Far : 적혀진 숫자보다 크면 잘라낸다.
- Filed of View : 카메라의 확대축소 정도인데 Cinemachine을 만들 경우, 걔가 조정하기 때문에 카메라에선 건드릴 수 없게 된다.
4-1. 시네머신Cinemachine 만들기.
카메라는 계속 캐릭터를 보여줘야 한다.
예전엔 카메라가 보여주는 위치에 어떤 충돌체가 있느냐에 따라 앵글을 바꾼다거나 줌인을 한다는 등의 움직임을 직접 구현해줘야 했다.
당연히 매우 비효율적이었기 때문에 유니티에선 자체적으로 관리하는 컴포넌트를 만들었고, 쉬운 방법으로 움직임을 구현할 수 있게 됐다.
리본메뉴 → Cinemachine → Create virtual camera.
Hierarchy에 CM vcam1 이라는 오브젝트가 자동으로 생성된다.
그리고 카메라 옆에는 이상한 빨간 아이콘이 생기고 컴포넌트도 추가된다. 이제 카메라는 캐릭터가 잘 보이도록 자동으로 움직여 줄 것이다.
- Follow : 따라가고자 하는 오브젝트 설정. 플레이어를 끌어다 설정한다.
- Aim 은 Do nothing
- Body는 frame transposer
Screen X, Y : 얼마나의 X, Y 값으로 따라갈지 조정. 어깨 시점이나 그런 것을 이것으로 설정한다.
Camera Distence : 카메라 줌인 줌아웃 정도. 숫자가 작을 수록 가깝다.
CM vcam1 오브젝트를 누르고 게임 화면을 보면 이렇게 보인다.
Follow dot : 팔로우 찍힌 점.
Dead zone : 이 캐릭터를 따라가다보면 콜라이더 때문에 너무 많이 줌인되는 곳이 있는데 이 이상으로 줌인하지 말라는 존.
Soft zone : 위와 반대로, 이 이상 줌아웃하지 말라는 존.
완성.
5. 포스트 프로세싱Post processing 효과 추가
사진 어플을 사용하면, 뽀샤시 효과라던지 화면에 효과를 주는 것 처럼
블러나 색상 보정으로 분위기를 주는 효과를 말한다.
'효과를 준다'는 것은 결국 카메라에서 공간에 잡혀 있는 물체를 그려주는 것이므로 렌더링(메쉬들을 계산해서 보여주는 것) 작업을 마친 후에 하는 것.
Camera → Add component → Rendering → Post-process layer.
카메라를 트리거로 두고
Layer : 하이어라키상에 올라와있는 오브젝트들이 어떤 종류인지 구분해서 종류별로 다른 작업을 해주고 싶을 때 이걸 사용한다.
오브젝트 이름 밑에 레이어가 있는데 기본적으로 Default와 유니티 기본 설정의 레이어가 있다.
다만, 포스트 프로세싱 하는 애들만 지정해서 커스텀하고 싶으므로 레이어를 새로 만든다.
1. 오브젝트 이름 아래, Layer 선택창에서 Add Layer... 를 선택한다.
2. Edit → Project Setting → Tag and Layers
아무 빈 레이어에 이름을 붙여주고,
Camera → Post-process Layer 의 레이어를 만든 레이어로 설정한다.
- Anti-aliasing : 메쉬가 끝나는 외곽선 부분 표면이 픽셀 단위로 까끌까끌하게 보이는데 그걸 부드럽게 처리하는 것. 부하가 좀 든다.
Fast Approximate... : 계산 빨리할 수 있는 연산. 저사양 게임같지 않고 그래픽이 좀 더 고급져 보인다.
5-1. 포스트 프로세싱 볼륨 만들기
여기까진 카메라에 Post-process Layer를 보이게 만들었다면,
이걸 오브젝트에 저장시켜 활용하게 만들어야 한다.
Hierarchy 우클릭 → Empty.
레이어를 방금 만든 레이어로 바꾼다.
Add component → Rendering → Post-processing Volumes 추가
- Profile : new 하면 자동으로 Scene 폴더에 프로필 폴더가 생기고 파일이 들어가게 된다.
효과 추가하기
Overrides → Add effect 로 효과를 추가하는 것이라 처음 만들 때는 아무 것도 없는 것이 정상이다.
몇 개를 추가해보자.
- Tonemapping - Mode - ACES : 영화같은 거 촬영할 때 이런 효과를 쓴다고... 아무튼 톤을 정리하는 역할.
씬 내 조명의 광원이 퍼지고 안퍼지고를 설정할 수 있음.
- Threshold : 빛이 많이 번져지는 물체들의 한계값. 숫자가 0에 가까울수록 밝고 뿌얘짐.
구석진 곳들은 사실, 좀 더 현실적인 그래픽이라면 반사광이 줄어서 어둡게 표현되어야 한다. 그런 차이를 극대화해준다.
- Intensity : 커질수록 구석진 부분들이 어두워짐.
- Thickness Modifier : 어두워지는 영역들을 확장시킴.
'화면상의' 가장자리에 효과를 주는 것.
오목/볼록 렌즈처럼 화면이 보이게 만듦.
Q. 카메라가 캐릭터랑 너무 가까움!
A. 카메라에서 조정하는 것이 아니고 CM vcam1에서 조정하는 것. 시네마틱 머신에 들어가면 Lens가 있는데 거기서 Field Of View의 값을 키우면 된다.
+ 버튼은 회색이 '활성화 가능' 인거고 검은색이 선택된 것. 어떤 버튼은 또 반대라서 헷갈리긴 한데... 잘 눌러보자.
6. 게임 오버 / 클리어 UI 뜨게 만들기
UI는 다른 오브젝트와는 다르게 별도의 좌표를 갖고 있다. 화면 중간에 떠야 하기 때문이다.
Hierarchy → UI → Image
자동으로 Canvas와 Event System 오브젝트가 생성된다. 이미지는 Canvas의 자식객체로 생성된다.
모든 오브젝트는 transform 컴포넌트를 가지고 있지만 캔버스 오브젝트는 좀 다르게 Rect Trensform 이 생긴다.
더블클릭해서 보면 혼자 공중에 크게 떠있다. 즉, UI는 월드 내에 있는 것이 아니다.
혹시 좀 편하게 보고 싶으면 씬, 애니메이터 밑에 2D버튼을 활성화.
월드 좌표와 다르게 설정되어 있음.
게임을 하게 되면 월드-캐릭터-화면 효과들이 다 보이고 UI는 가장 마지막에 그려주는 거라고 생각하면 됨.
랙트 트랜스폼을 가진 것들은 월드로 옮겨도 보이지 않음. 차원이 다르다고 생각하면 편할듯?
- Render Mode : Overay
World space : 월드 좌표계에서 쓰는 UI, 예를 들어 캐릭터 위에 HP바가 떠있어야 하거나, 유저 이름이 머리 위에 떠있는 것은 월드 좌표계 내에서 사용되어야 하는 것이 해당.
- Sort order : 어떤 캔버스에 있는 것을 먼저 띄울 것인지. 피피티의 앞으로 오게 하기, 뒤로 가게 하기와 비슷하다.
숫자가 크면 클수록 마지막, 가장 앞에, 가장 위에 있다. 캔버스 하나만 할거면 그냥 0.
- Canvas scale : 모바일은 기종따라 보이는 크기가 다르게 보이게 만드는 것인데 우린 모바일 게임 아니니까 필요 없어서 삭제한다.
- Graphic raycast : 레이어를 쏴서 어떤 충돌이 있는지 검색하는 것. 월드에선 콜라이더로 충돌을 해놨는데, UI는 클릭을 한 좌표 상에 오브젝트가 있는지를 확인해봐야 하는데, 유니티 상에선 그걸 레이저를 쏜다고 말함. 버튼 요소가 있을 때 그걸 검출하기 위한 컴포넌트인데 여기선 필요 없어서 삭제
제2의나라 터치 UI라고 생각하면 되나?
이제 Image → Ract Transform
노란색 점이 어디를 기점으로 원점을 둘 것이냐는 의미.
캔버스는 특정한 설정을 하지 않는 이상 화면 전체를 의미한다. Image는 캔버스=화면 전체를 기점으로 어디에 갈지 선택해야 한다.
PosX는 '캔버스 안에서 이미지의 위치'를 말하지만 캔버스의 화면 내 원점 위치는 저 타겟모양에서 정의된다.
- Aanchors
Pivot : 오브젝트(이미지)의 원점. 위 사진 중 파란 점이며, 0일수록 왼쪽, 1일수록 오른쪽이다.
정렬중에 부모의 꼭짓점에 맞춰 정렬되는 애가 있고, 화면의 넓이에 따라 정렬하라는 것도 있다.
Stretch(파란 화살표). 이걸로 하면 POS X 등이 위치가 아니라 '얼마나 여백을 줄 것이냐'로 바뀜. 해상도가 바뀌는 게임을 만들 때 이걸 설정하면 해상도에 맞춰서 보여줄 수 있다.
화면 전체를 가득 채우고 싶다면?
여백을 0으로 줘서 이미지를 캔버스 가득 채운다.
- Source Image : 보여주고 싶은 이미지를 끌어다 넣는다.
- Color : 알파값도 조절이 가능하다. 0으로 갈수록 투명해진다.
하이어라키 상에서 아래 있을 수록 마지막에 그린다: 나중에 그린 것들이 먼저 보인다. 하이어라키 위치로 순서를 정할 수 있다.
- Set Navites Size : 이미지 원본 사이즈를 가져옴.
- Preserve Aspect : 체크! 안하면 비율이랑 상관 없이 부모 이미지의 사이즈를 꽉 채우는 대로 들어가게 된다. 이미지의 비율을 깨지 않고 여백을 적용시키고 싶다면 체크해야 된다.
6-1. UI가 보이지 않았다가 나중에 보이게 만들기
이제 UI가 원랜 안보이다가 게임 탈출을 하게 되면 그때 보여야 한다.
두 장의 이미지 동시에 알파값을 옮겨야 하는데
(해당) Image → Add Component → Layout → Canvas Group.
캔버스 안에 있는 모든 자식 오브젝트는 하나로 취급해서 설정이 가능하다.
알파값: 정규화된 값. 0~1까지의 값. 반투명하게 하고 싶으면 0.5 0은 알파값이 없다=투명하다.
일단 투명하게 되었다.
이제, 엔딩에 다다르면 UI를 띄워줘야 하는데 그러려면 특정 좌표에 '도착 혹은 진입 혹은 충돌'했음을 파악하고 띄워야 한다 = 콜라이더.
Hierarchy 우클릭 → Empty.
Add Component → Physics → Box collider.
캐릭터가 여기에 와서 부딪히면 엔딩UI를 띄우도록 스크립트 할 것.
그런데 콜라이더는 '물리적인 실체를 갖게 만드는 것'이라 캐릭터는 해당 콜라이더 앞에서 막히게 된다.
그러나 우리는 충돌만 검출하고 싶지, 실제 장애물로 인식되고 싶은 것이 아니다.
즉, 다른 콜라이더가 와도 겹쳐질 수 있게 하고 싶다.
→ Is Trigger 체크하면, 벽처럼 막힌 것이 아니고 뚫을 수 있게 된다. (=이건 충돌체라기보단 트리거의 역할을 맡은 것)
이제 GameEnding이란 C# 스크립트를 만들고 게임엔딩 오브젝트에 붙인다.
(오늘자의 스크립트가 없다!
내일 작성할 스크립트와 합쳐진 바람에 둘을 구분할 수가 없어서 9-5에 완성본을 넣었다...!)
(아래는 작성 과정...)
UI와 SceneManagement를 상속받는 네임스페이스.
오늘 우리가 할 것은
닿으면 UI 띄우게 할 거니까
using UnityEngine.UI
충돌한 물체가 캐릭터면 엔딩UI를.
OnTriggerEnter : 콜라이더 컴퍼넌트에서 다른 콜라이더가 충돌해서 겹쳐지는 첫 프레임 그 순간 한 번, 호출한다.
((OnTriggerStay : 콜라이더가 다른 콜라이더와 겹쳐져 있는 내내 호출.
((OnTriggerExit : 두 콜라이더가 떨어지는 순간 한 번 호출.
플레이어 캐릭터 외에 다른 콜라이더 부딪혔다고 엔딩UI가 뜨면 안되니까 플레이어 캐릭터만 검출해서 UI를 띄우도록 결정해야 한다. → if문
부딪힌 아더라는 게임 오브젝트가 플레이어인지 아닌지 검출.
--→ (위에 전역변수로 player 만들어 두고) if (other.gameObject == player) 라는 조건으로 쓸 수도 있음.
어쨌든 지금 이 if문 값이 트루라면(캐릭터가 맞다면) 엔딩을 보여준다.
→ UI가 한번에 띡 보이는게 아니라 여러 프레임으로 알파값이 올라가 완전히 보여주게, 이쁘게 만들자.
→ 업데이트 메서드
bool isPlayerExit = false로 일단 플레이어가 없다는 값을 주고(전역변수),
이 값이 부딪히면 트루로 바뀌어야 하니까 if문에 조건 넣어주고,
위에 만든 업데이트 메서드에 if로 만약 isPlayerEixt 조건을 걸고
캔버스 그룹에 접근이 가능해야 얘가 조정할 수 있으니까
public CanvasGroup exitImageCanvasGroup 전역변수 생성.
만약 isPlayerExit 되면, exitImageCanvasGroup의 alpha의 타이머(전역변수float timer = 0f; 생성, public float fadeDuration; 생성.)
타이머는 돌아가기 시작한 시간이고 페이드듀레션에 가깝게 되도록 1이 되도록.
엑시트 됐을 때부터 타이머가 올라가야 함 = Time.deltaTime : 컴퓨터 성능에 따라 프레임 업데이트가 다르다. 그러면 사람마다 업데이트 되는 속도가 다르니까 그걸 보정해주는 값. 1초에 몇 프레임이라고 정해져 있음.
그리고 타이머의 숫자가 어느정도 커졌으면 게임이 종료가 되도록 다시 if문, timer가 fadeDuration보다 커지면 어플이 꺼지도록.
문제는 이렇게 하면 바로 UI 제대로 보지도 못하고 꺼져버린다 = 타이머를 또 설정해준다.
public float displayExitImageDuration;
이 더한 숫자만큼 후에 어플리케이션이 꺼지게 된다.
타이머가 시간이 갈 수록 증가해야 함. = )))
완성
이제 유니티로 가보면 아까 만든 퍼블릭 변수들이 보이게 된다.
완성! 비록 엔진형태라 어플리케이션이 꺼지진 않았지만... UI는 잘 보인다!
'메타버스기반게임콘텐츠기획 > 그날의 강의' 카테고리의 다른 글
(10-1) 유니티unity 클리커 게임 만들기 - 버튼을 누르면 골드를 획득하는 스크립트 (0) | 2021.12.27 |
---|---|
(9-5) 유니티unity - 게임오버 오브젝트 및 빌드, 게임오버 에너미, 게임오버UI, 씬 이동, 루트 제작, 음향 효과, 게임 실행파일 만들기 (0) | 2021.12.24 |
(9-3) 유니티unity : 다운 받은 에셋으로 캐릭터, 움직임, 애니메이션 만들기 (0) | 2021.12.22 |
(9-2) 유니티unity 코딩: 매개변수, $, Beginner Code-for문 (0) | 2021.12.21 |
(9-1) 유니티unity - 오브젝트에 스크립트 컴포넌트 추가하기 (0) | 2021.12.20 |