07. 시선 방향으로 이동하기
에단을 랜덤하게 이동하는 것이 아니라 어디든지 원하는 위치로 이동할 것입니다. 장면의 VR 카메라 오브젝트는 머리와 함께 움직입니다. 즉, 카메라가 지면에 투과할 때까지 카메라에서 바라보는 방향으로 선을 그려서 지상의 어디를 보고 있는지 알 수 있습니다.
유니티에서는 레이캐스팅(Ray Casting)을 사용하여 이 작업을 수행합니다. 그것은 카메라에서 광선을 쏘고 그것이 무엇과 충돌히는지 보는 것과 같습니다. 레이캐스팅은 충돌체가 연결된 오브젝트에서 감지됩니다. 현재 사용 중인 대부분의 오브젝트는 기본 3D게임 오브젝트(큐브,구 등)이며 기본적으로 Unity의 3D기본 게임 오브젝트에는 이미 충돌기가 연결되어 있습니다.
1. 시선을 따라 이동 스크립트 작성
레이캐스팅(Ray Casting)을 사용하여 시선(카메라)이 지면에 투과할 때까지 시선(카메라)이 바라보는 방향의 지상으로 에단을 이동해 봅니다.
① 하이러키 창에서 WalkTarget 오브젝트를 선택합니다.
② 인스펙터 창에서 [Add Component] 버튼을 클릭합니다.
③ 맨 아래의 New Script를 선택합니다.
④ 이름을 LookMoveTo로 입력합니다.
⑤ [Create And Add] 버튼을 클릭합니다.
⑥ RandomPosition 스크립트 컴포넌트를 비활성화하거나 제거합니다.
LookMoveTo.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LookMoveTo : MonoBehaviour
{
Transform camera;
public GameObject ground;
void Start()
{
camera = Camera.main.transform;
}
void Update()
{
Ray ray;
RaycastHit hit;
GameObject hitObject;
Debug.DrawRay(camera.position, camera.rotation * Vector3.forward * 100.0f);
ray = new Ray(camera.position, camera.rotation * Vector3.forward);
if (Physics.Raycast(ray, out hit))
{
hitObject = hit.collider.gameObject;
if (hitObject == ground)
{
Debug.Log("Hit (x,y,z): " + hit.point.ToString("F2"));
transform.position = hit.point;
}
}
}
}
<실행결과>
2. 3D 커서 추가
시선(카메라)이 지면에 닿는 위치가 항상 명확하지 않아서 장면에 3D 커서를 추가합니다.
① 하이러키 창에서 WalkTarget 오브젝트를 마우스 오른쪽 버튼으로 클릭하고 3D Object | Cylinder 메뉴를 선택합니다. 이름을 CursorDisk로 변경합니다.
② 하이러키 창에서 CursorDisk 오브젝트를 선택하고 인스펙터 창에서 Transform컴포넌트를 초기화합니다.
③ 하이러키 창에서 CursorDisk 오브젝트를 선택하고 인스펙터 창에서 Scale(0.4, 0.05, 0.4)로 변경합니다.
④ 하이러키 창에서 CursorDisk 오브젝트를 선택하고 인스펙터 창에서 Capsule Collider를 비활성화합니다.
⑤ 성능 최적화를 위해서 Mesh Renderer에서 Cast Shadows, Light Probes 및 Reflection Probes를 비활성화/Off설정합니다.
⑥ 원하면 CursorDisk 오브젝트를 선택하고 재질을 추가해도 됩니다.

3. 장애물을 통해 관찰
장애물 오브젝트 위로 시선을 움직일 때 3D 커서가 멈춘 것처럼 보일 것 입니다. 이는 물리 엔진이 어떤 물체에 먼저 닿았는지, 지면에 닿지 않았는지를 결정했기 때문입니다.
시선이 장애물 오브젝트를 바라보는 경우 3D 커서는 바닥에 유지하고 위치가 변경되지 않고 멈추게 하기 위해서 Physics.RaycastAll()을 이용합니다.
다음과 같이 Update () 코드를 변경합니다.
LookMoveTo.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LookMoveTo : MonoBehaviour
{
Transform camera;
public GameObject ground;
void Start()
{
camera = Camera.main.transform;
}
void Update()
{
Ray ray;
RaycastHit[] hits;
GameObject hitObject;
Debug.DrawRay(camera.position, camera.rotation * Vector3.forward * 100.0f);
ray = new Ray(camera.position, camera.rotation * Vector3.forward);
hits = Physics.RaycastAll(ray);
for (int i = 0; i < hits.Length; i++)
{
RaycastHit hit = hits[i];
hitObject = hit.collider.gameObject;
if (hitObject == ground)
{
Debug.Log("Hit (x,y,z): " + hit.point.ToString("F2"));
transform.position = hit.point;
}
}
}
}
<실행결과>