미디어 콘텐츠 스터디
10. 손으로 상호 작용하기I 본문
1. 장면 만들기
이전 장에서 사용된 Diorama 장면부터 시작하여 다음과 같이 GroundPlane과 PhotoPlane을 제외한 모든 장면을 제거하여 활용해도 됩니다.
① Diorama 장면을 엽니 다.
② XR Origin, XR Interaction Manager, Directional Light, GroundPlane 및 PhotoPlane을 제외한 모든 개체를 제거합니다.
③ XR Origin을 Transform의 Position (0, 0, -1)로 설정하여 장면 원점 위치에서 몇 피트 떨어진 곳에 배치합니다.
④ File | Save Scene As으로 저장하고 이름을 'Balloons' 지정합니다.
1.1 바닥 만들기
① 하이러키 창에서 왼쪽 상단 에있는 + (create) 메뉴(또는 메인 GameObject 메뉴)를 클릭합니다.
② 3D Object | Plane를 선택합니다.
③ Transform 값을 Reset으로 설정합니다.
④ 기본 평면이 장면에 추가되고, Position (0, 0, 0)의 접지 평면 중심으로 합니다.
Inspector 창에서 이름을 ‘GroundPlane’으로 변경합니다.
1.2 벽면 만들기
① 파일 시스템에서 Unity 프로젝트의 Textures 폴더로 사진 이미지를 드래그합니다. 이름은 GrandCanyon.jpg입니다.
② GameObject | 3D Object | Quad로 이동하여 ‘PhotoPlane’라는 이름을 붙여 3D 사각형(단순한 사각형) 오브젝트를
만듭니다.
③ Inspector 창에서 필요한 경우 Transform을 초기화합니다 (Transform | 3-dot-icon | Reset).
④ PhotoPlane의 크기에 맞게 조정합니다. Transform의 Scale을 (10, 10, 10)으로 설정합니다
⑤ PhotoPlane의 위치를 조정합니다. Transform의 Position을 (0, 5, 5)로 설정하여 GroundPlane의 가장자리로 이동합니다.
⑥ Project 창의 Materials / 폴더에서 ‘GrandCanyon’ 재질이라는 이름의 다른 재질 (마우스 오른쪽 버튼을 클릭하고
Create | Material로 이동)을 만듭니다.
⑦ Project 창에서 GrandCanyon 재질을 Scene (또는 Hierarchy 목록)의 PhotoPlane 으로 드래그앤드롭하여 설정합니다.
⑧ Inspector 창에서 Base Map(or Albedo) 옆에 있는 작은 도넛 형 아이콘을 선택하여 Select Texture 대화 상자를 연 다음
더블 클릭하여 GrandCanyon을 선택합니다.
⑨ 색상 칩을 클릭하고 흰색 (#FFFFFF)을 선택하여 Base Map을 풀 컬러 (흰색)로 설정합니다.
이제 장면 단계가 설정되었으므로 먼저 풍선 게임 오브젝트를 정의하고 이를 프리팹으로 만들고, 하이러키 창에 빈 오브젝트를 추가하여 풍선 프리팹을 인스턴스화 할 스크립트를 연결합니다.
2. 풍선 만들기
풍선 모델은 원하는 경우 GameObject |3D Object | Sphere 메뉴를 선택하여 구를 사용하거나 Unity 에셋 스토어 또는 다른 곳에서 오브젝트를 찾아서 사용할 수 있습니다.
2.1 풍선 오브젝트 정의
프로젝트로 모델을 가져와 사용하는 경우 다음 단계를 따릅니다.
① Project 창에서 Assets 폴더에 Models 폴더를 만듭니다 (프로젝트 창에서 Create | Folder를 마우스 오른쪽 단추로 클릭하고 이름을 지정합니다).
② Project 창에서 Assets 폴더에 Models 폴더로 풍선모델 BalloonModel.fbx 파일을 끌어 놓습니다. 또는 Models 폴더를 선택한 상태에서 주메뉴의 Assets | Import New Asset 를 통해서 가져옵니다.
이제 장면에 모델을 추가하면 다음과 같이 객체의 상위(다른 객체의 하위 항목으로 만들기) 및 위치를 조정하여 풍선 모델의 하단이 원본(피봇 지점)이 되도록 합니다.
① Hierarchy 창에서 빈 오브젝트 (+ | Create Empty)를 만들고 이름을 Balloon으로 변경합니다.
② Hierarchy 창에서 Balloon를 선택하고 Inspector 창에서 Transform 컴포넌트를 초기화합니다 ((Transform | 3-dot-icon | Reset).
③ Hierarchy 창에서 Balloon의 하위에 풍선 모델을 추가합니다 (예 : Assets / Models / 폴더에서).
④ Hierarchy 창에서 Balloon을 선택하고 Inspector창에서 Transform의 Position(0, 0.5, 0)을 설정하여 장면 창에서 이동 도구를 사용하여 모델의 위치를 조정하여 바닥과 같은 원점으로 정렬합니다.
2.2 풍선 프리팹 만들기
다음과 같이 Rigidbody를 추가하고 오브젝트를 프리 팹으로 만듭니다.
① Hierarchy에서 Balloon을 선택합니다.
② 메뉴에서 Component | Physics | Rigidbody 메뉴를 선택합니다.
③ Rigidbody의 Use Gravity 체크란의 선택을 해제합니다.
④ Hierarchy 창에서 Balloon을 선택하여 Project 창의 Assets폴더의 Prefabs / 폴더로 끌어서 프리팹으로 만듭니다.
⑤ Hierarchy 창에서 원래 Balloon을 삭제합니다.
2.3 풍선 생성 스크립트 작성하기
① Hierarchy 창에서 빈 게임 오브젝트 (+ | Create Empty)를 만들고 이름을 Balloon Controller로 변경하고, Inspector 창에서 Transform을 초기화 (Transform | 3dot-icon | Reset) 합니다.
② Hierarchy 창에서 Balloon Controller를 선택하고 새 스크립트 BalloonController.cs를 만듭니다 (inspector에서 Add Component | New Script | BalloonController로 이동).
③ 코드를 작성합니다.
BalloonController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR;
public class ButtonInputController : MonoBehaviour
{
private InputDevice targetDevice;
void Start()
{
List<InputDevice> devices = new List<InputDevice>();
InputDeviceCharacteristics rightController = InputDeviceCharacteristics.Right | InputDeviceCharacteristics.Controller;
InputDevices.GetDevicesWithCharacteristics(rightController, devices);
/*foreach (var item in devices)
{
Debug.Log(item.name + item.characteristics);
// scoreText.text = item.name + item.characteristics;
}
*/
targetDevice = devices[0];
}
void Update()
{
if (targetDevice.TryGetFeatureValue(CommonUsages.trigger, out float triggerValue) && triggerValue == 1.0f)
{
Debug.Log("Trigger down");
// scoreText.text = "Trigger down" + triggerValue ;
}
else if (targetDevice.TryGetFeatureValue(CommonUsages.trigger, out float triggerValue2) && triggerValue2 == 0.0f)
{
Debug.Log("Trigger up");
// scoreText.text ="Trigger up" + triggerValue2 ;
}
}
}
3. 트리거로 풍선 제어하기
트리거를 누르면 장면 창에서 Balloon 프리팹을 인스턴스화하여 새 풍선을 만듭니다..
트리거를 놓으면 풍선 객체가 하늘로 떠오를 수 있습니다. 트리거 버튼을 누르고 있는 동안 풍선의 크기가 커집니다.
3.1 새 풍선 만들기
트리거 버튼을 누를 때 새 풍선을 만들기 위해서 BalloonController.cs 스크립트의 Update 함수를 다음과 같이 변경합니다.
BalloonController.cs
public class BalloonController : MonoBehaviour
{
public GameObject balloonPrefab;
private GameObject balloon;
void Update()
{
if (targetDevice.TryGetFeatureValue(CommonUsages.trigger, out float triggerValue) && triggerValue == 1.0f)
{
CreateBalloon();
}
}
public void CreateBalloon()
{
balloon = Instantiate(balloonPrefab);
}
}
3.2 풍선 해제하기
일정시간이 지나면 풍선을 장면창에서 없어지도록 하기 위해서 BalloonController.cs 스크립트를 다음과 같이 변경합니다.
BalloonController.cs
public class BalloonController : MonoBehaviour
{
...
public float floatStrength = 20f;
void Update()
{
if (targetDevice.TryGetFeatureValue(CommonUsages.trigger, out float triggerValue) && triggerValue == 1.0f)
{
CreateBalloon();
}
else if (targetDevice.TryGetFeatureValue(CommonUsages.trigger, out float triggerValue2) && triggerValue2 == 0.0f)
{
ReleaseBalloon();
}
}
...
public void ReleaseBalloon()
{
Rigidbody rb = balloon.GetComponent<Rigidbody>();
Vector3 force = Vector3.up * floatStrength;
rb.AddForce(force);
GameObject.Destroy(balloon, 10f);
balloon = null;
}
}
파일을 저장하고 Unity로 돌아가서 다음과 같이 스크립트의 변수에 Balloon 프리팹을 할당합니다.
① Hierarchy 창에서 Balloon Controller를 선택합니다.
② Project 창에서 Assets|Prefabs폴더에서 Balloon 프리팹을 찾습니다.
③ Project 창에서 Inspector 창으로 BalloonController의 Balloon Prefab에 Balloon 프리팹을 드래그앤드롭 합니다.
이제 BalloonController는 Inspector에서 다음과 같이 보입니다 :
(실행결과)
3.3 풍선 부풀리기
트리거 버튼을 누르고 있는 동안 풍선을 부풀립니다.
풍선은 작게 시작해서 트리거를 누르는 동안 현재 풍선의 크기를 초당 1.5 배 점점 더 커지도록 합니다.
① BalloonController.cs 스크립트에 CreateBalloon() 함수 수정합니다.
public void CreateBalloon()
{
balloon = Instantiate(balloonPrefab);
balloon.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f);
}
② BalloonController.cs 스크립트에 풍선 크기를 변경하는 데 사용할 growRate 변수를 선언합니다. 1.5로 초기화하지만 나중에 Inspector에서 해당 값을 조정할 수 있습니다.
public class BalloonController : MonoBehaviour
{
...
public float growRate = 1.5f
...
}
③ BalloonController.cs 스크립트에 세 번째 if 조건으로 Update 함수를 수정합니다.
void Update()
{
...
if (balloon != null)
{
GrowBalloon();
}
}
④ BalloonController.cs 스크립트에 GrowBalloon() 함수를 추가합니다.
public void GrowBalloon()
{
float growThisFrame = growRate * Time.deltaTime;
Vector3 changeScale = balloon.transform.localScale * growThisFrame;
balloon.transform.localScale += changeScale;
}
4. 트러거 입력 이벤트 만들기
입력 버튼의 상태를 읽고 이벤트를 호출하도록 별도의 입력 컨트롤러를 생성합니다. 다음 다이어그램은 입력 컨트롤러 간의 관계를 보여줍니다.
4.1 이벤트 호출 스크립트 만들기
① Hierarchy 창에서 빈 게임 오브젝트 (+ | Create Empty)를 만들고 이름을 ButtonInput ontroller로 변경하고, Transform을 초기화합니다.(Transform | 3dot-icon | Reset)
② Hierarchy 창에서 ButtonInputController를 선택하고 여기에 새 스크립트(ButtonInputController.cs)를 만듭니다 (Add
Component | New Script).
③ 트리거 버튼을 눌렀을 때 ButtonInputController가 이벤트를 트리거하고 버튼을 놓을 때 다른 이벤트가 발생하도록
먼저, 스크립트 상단에서 Unity 이벤트 API를 사용하고 있음(using UnityEngine.Events)을 선언해야합니다.
④ ButtonInputController.cs에 호출할 두 개의 UnityEvent를 선언합니다. Update () 함수는 발생하는 이벤트 중 하나만 호출하면 됩니다.
ButtonInputController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.XR;
public class ButtonInputController : MonoBehaviour
{
private InputDevice targetDevice;
public UnityEvent ButtonDownEvent = new UnityEvent();
public UnityEvent ButtonUpEvent = new UnityEvent();
void Start()
{
List<InputDevice> devices = new List<InputDevice>();
InputDeviceCharacteristics rightController = InputDeviceCharacteristics.Right | InputDeviceCharacteristics.Controller;
InputDevices.GetDevicesWithCharacteristics(rightController, devices);
targetDevice = devices[0];
}
// Update is called once per frame
void Update()
{
if (targetDevice.TryGetFeatureValue(CommonUsages.trigger, out float triggerValue) && triggerValue == 1.0f)
{
ButtonDownEvent.Invoke();
}
else if (targetDevice.TryGetFeatureValue(CommonUsages.trigger, out float triggerValue2) && triggerValue2 == 0.0f)
{
ButtonUpEvent.Invoke();
}
}
}
4.2. 입력 이벤트로 호출되는 스크립트 수정하기
이벤트로 호출될 때 사용하는 BalloonController.cs를 수정합니다.
BalloonController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR;
using UnityEngine.UI;
public class BalloonController : MonoBehaviour
{
//public Text scoreText;
private InputDevice targetDevice;
public GameObject balloonPrefab;
private GameObject balloon;
public float floatStrength = 20f;
public float growRate = 1.5f;
void Start()
{
}
// Update is called once per frame
void Update()
{
if (balloon != null)
{
GrowBalloon();
}
}
public void GrowBalloon()
{
float growThisFrame = growRate * Time.deltaTime;
Vector3 changeScale = balloon.transform.localScale * growThisFrame;
balloon.transform.localScale += changeScale;
}
public void CreateBalloon(GameObject parentHand)
{
Rigidbody rb = balloon.GetComponent<Rigidbody>();
Vector3 force = Vector3.up * floatStrength;
rb.AddForce(force);
GameObject.Destroy(balloon, 10f);
balloon = null;
}
public void ReleaseBalloon()
{
Rigidbody rb = balloon.GetComponent<Rigidbody>();
Vector3 force = Vector3.up * floatStrength;
rb.AddForce(force);
GameObject.Destroy(balloon, 10f);
balloon = null;
}
}
풍선 제어를 위한 입력 이벤트를 연결하려면 다음 단계를 수행합니다.
① Hierarchy 창에서 ButtonInputController를 선택하고 Inspector 창을 확인합니다.
② 스크립트에서 선언 한 것처럼 이제 스크립트 구성 요소에 두 개의 이벤트 목록이 있음을 알 수 있습니다.
③ Button Down Event 목록에서 오른쪽 하단 모서리에 있는 +를 클릭하여 새 항목을 만듭니다.
④ Hierarchy창에서 BalloonController를 빈 개체 슬롯으로 드래그앤드롭 합니다.
⑤ 함수 선택 목록에서 BalloonController | CreateBalloon을 선택합니다.
Button Up 이벤트에 대해 다음과 같이 프로세스를 반복합니다.
① Button Up Event 목록에서 오른쪽 하단의 +를 눌러 새 항목을 만듭니다.
② Hierarchy창에서 BalloonController를 빈 개체 슬롯으로드래그앤드롭 합니다.
③ 함수 선택 목록에서 BalloonController | ReleaseBalloon을 선택합니다.
구성 요소는 다음과 같아야합니다.
5. 손 위치 추적 만들기
손의 위치 추적을 활용하려면 XR Origin에 포함된 핸드 컨트롤러인 LeftHandController 및 RightHandController로 플레이어의 핸드 컨트롤러로 활용합니다.
5.1 풍선을 손으로 제어하기
풍선 제어할 때 어느 손이 트리거 버튼을 눌렀는지 알고 풍선을 해당 컨트롤러 오브젝트의 부모로 지정해야 합니다.
① CreateBalloon() 함수에 손 객체를 매개변수로 전달한 후 해당 손객체의 Transform을 Instantiate() 함수에 전달합니다.
public void CreateBalloon(GameObject parentHand)
{
balloon = Instantiate(balloonPrefab, parentHand.transform);
balloon.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f);
}
② ReleaseBalloon()함수는 다음과 같이 풍선을 떠오르기 전에 손에서 풍선을 분리하도록 수정합니다.
public void ReleaseBalloon()
{
balloon.transform.parent = null;
balloon.GetComponent<Rigidbody>().AddForce(Vector3.up * floatStrength);
GameObject.Destroy(balloon, 10f);
balloon = null;
}
Inspector에서 이제 게임 오브젝트 인수가 필요하므로 Button Down Event 함수를 업데이트해야합니다.
③ Hierarchy 창에서 Button Input Controller를 선택하고 Inspector 창에서 Button Down Event() 함수에서 None(GameObject)를 확인할수 있습니다.
④ Hierarchy 창에서 XR Origin을 펼치고 RightHand Controller를 Inspector 창에서 Button Down Event() 함수에서 None(GameObject)에 드래그앤드롭하여 설정합니다.
버튼 입력 컨트롤러 구성 요소는 이제 다음과 같습니다.
실행하기
5.2 풍선이 똑바로 떠오르게하기
처음 지면에서 풍선을 인스턴스화했을 때 기본 수직 회전 방향도 지정되었느나 풍선이 손 컨트롤러의 자식으로 인스턴스화되어 손을 회전하면 회전 (위치 및 위치)을 기준으로 방향이 변경됩니다. 따라서 스크립트를 작성하여 Balloon prefab 객체에 추가합니다.
① Proejct 창에서 Assets |Prefabs 폴더에서 Balloon 프리 팹을 선택합니다.
② 새 스크립트 KeepUpright.cs 만들어 추가합니다 (구성 요소 추가 | 새 스크립트 | KeepUpright | 만들기 및 추가로 이동).
③ KeepUpright.cs 코드를 작성합니다.
KeepUpright.cs
public class KeepUpright : MonoBehaviour
{
public float speed = 5f;
void Update()
{
transform.rotation = Quaternion.Slerp(transform.rotation,
Quaternion.identity, Time.deltaTime * speed);
}
}
실행하기
'가상현실(Virtual Reality) > 가상현실 맛보기' 카테고리의 다른 글
12. 풍선 터트리기 (0) | 2021.08.17 |
---|---|
11. 풍선 총으로 상호 작용하기 (0) | 2021.07.28 |
09. 좀비 죽이는 효과 만들기 (0) | 2021.07.12 |
08. 좀비 만들기 (0) | 2021.07.12 |
07. 시선 방향으로 이동하기 (0) | 2021.07.12 |