Player Prefab은 이미 Character Controller컴포넌트가 이미 설정되어 있고 실행하면 Idle 애니메이션을 취하고 있다.
주인공 캐릭터 이동및 회전
프로젝트뷰에서 Scripts폴더안에 새로운 스크립트를 하나 만들고 이름을 Movement로 변경한다. 작성후 Player에 적용한다.
Player의 이동처리는 CharacterController의 SimpleMove함수를 이용한다.
// 주인공 캐릭터 이동처리
controller.SimpleMove(moveDir * moveSpeed);
Plane객체는 지정한 지점에 가상의 바닥을 생성한다.
// 가상의 바닥을 주인공의 위치를 기준으로 생성
plane = new Plane(transform.up, transform.position);
Turn() 함수에서는 ScreenPointToRay 함수를 이용해 마우스 커서의 위치값을 이용해 Ray를 생성한다.
// 마우스의 2차원 좌푯값을 이용해 3차원 광선(레이)를 생성
ray = camera.ScreenPointToRay(Input.mousePosition);
생성된 ray는 Plane.Raycast를 사용해 가상의 바닥으로 광선을 투사해 Ray.GetPoint로 닿은 지점을 계산한다.
// 가상의 바닥에 레이를 발사해 충돌한 지점의 거리를 enter 변수로 반환
plane.Raycast(ray, out enter);
// 가상의 바닥에 레이가 충돌한 좌푯값 추출
hitPoint = ray.GetPoint(enter);
가상의 바닥과 닿은 지점과 Player의 위치를 차이는 회전해야할 방향벡터이고 마우스 커서가 있는 지점으로 회전하게 된다.
// 회전해야 할 방향의 벡터를 계산
Vector3 lookDir = hitPoint - transform.position;
lookDir.y = 0;
// 주인공 캐릭터의 회전값 지정
transform.localRotation = Quaternion.LookRotation(lookDir);
이 방법은 가상의 바닥의 충돌지점을 얻어 오기 때문에 지상의 구조물을 포인팅하면 엉뚱한 곳으로 돈다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Movement : MonoBehaviour {
// 컴포넌트 캐시 처리를 위한 변수
private CharacterController controller;
private new Transform transform;
private Animator animator;
private new Camera camera;
// 가상의 Plane에 레이캐스팅하기 위한 변수
private Plane plane;
private Ray ray;
private Vector3 hitPoint;
// 이동 속도
public float moveSpeed = 10.0f;
void Start() {
controller = GetComponent<CharacterController>();
transform = GetComponent<Transform>();
animator = GetComponent<Animator>();
camera = Camera.main;
// 가상의 바닥을 주인공의 위치를 기준으로 생성
plane = new Plane(transform.up, transform.position);
}
void Update() {
// 자신이 생성한 네트워크 객체만 컨트롤
Move();
Turn();
}
// 키보드 입력값 연결
float h => Input.GetAxis("Horizontal");
float v => Input.GetAxis("Vertical");
// 이동 처리하는 함수
void Move() {
Vector3 cameraForward = camera.transform.forward;
Vector3 cameraRight = camera.transform.right;
cameraForward.y = 0.0f;
cameraRight.y = 0.0f;
// 이동할 방향 벡터 계산
Vector3 moveDir = (cameraForward * v) + (cameraRight * h);
moveDir.Set(moveDir.x, 0.0f, moveDir.z);
// 주인공 캐릭터 이동처리
controller.SimpleMove(moveDir * moveSpeed);
// 주인공 캐릭터의 애니메이션 처리
float forward = Vector3.Dot(moveDir, transform.forward);
float strafe = Vector3.Dot(moveDir, transform.right);
animator.SetFloat("Forward", forward);
animator.SetFloat("Strafe", strafe);
}
// 회전 처리하는 함수
void Turn() {
// 마우스의 2차원 좌푯값을 이용해 3차원 광선(레이)를 생성
ray = camera.ScreenPointToRay(Input.mousePosition);
float enter = 0.0f;
// 가상의 바닥에 레이를 발사해 충돌한 지점의 거리를 enter 변수로 반환
plane.Raycast(ray, out enter);
// 가상의 바닥에 레이가 충돌한 좌푯값 추출
hitPoint = ray.GetPoint(enter);
// 회전해야 할 방향의 벡터를 계산
Vector3 lookDir = hitPoint - transform.position;
lookDir.y = 0;
// 주인공 캐릭터의 회전값 지정
transform.localRotation = Quaternion.LookRotation(lookDir);
}
}
Resources/PhotonNetwork 폴더 하위에 있는 AngryBotResources 패키지를 임포트한다.
스테이지 설치와 라이트 매핑
AngryBotResources/Prefabs 폴더에 있는 Environment 프리팹을 하이라키 뷰로 드래그해 배치한다.
라이트 매핑을 위해 메뉴에서 [Window]-[Rendering]-[Lighting]을 선택해 라이팅 뷰를 연다. [Scene]탭을 선택하고 [New Lighting Settings] 버튼을 클릭해 SampleScene의 라이트 매핑 정보를 저장할 에셋을 생성한다. 생성된 라이팅에셋은 Scenes폴더로 이동시킨다.
라이팅 세팅 에셋을 생성하면 라이팅뷰의 Lighting Setting 옵션이 활성화된다. 좀더 빠른 라이팅 매핑을 위해 Lightmap Resolution 속성을 기본값이 40에서 10 또는 20 정도로 설정한다.
라이팅뷰 아래에 있는 [Generate Lighting] 버튼을 클릭해 라이트 맵 베이킹을 시작한다.
다음 화면은 베이킹후 라이트매핑이 완료된 화면이며 비네팅 효과로 모서리 부분이 어둡게 표현되었다.(약하게 하였다)
Bloom, Tonemapping 효과
Global Volume의 인스펙터뷰에서 [Add override] 버튼을 클릭해 Tonemapping을 추가한후 Mode Option을 체크후 ACES를 선택한다. 조명의 밝기를 HDR에서 사람이 인식할 수 있는 범위로 조정하는 효과를 말한다.
하이라키뷰의 Direct Light를 선택후 인스펙터뷰에서 [Light]-[Emission]-[Intensity]를 1에서2로 변경해서 밝게한다
다시 [Add override] 버튼을 클릭해 Bloom효과를 추가하고 Intensity를 1.5로 설정한다. 광원주위를 과장되게 표현하는 효과이다.