유니티와아두이노를활용한 -...

Preview:

Citation preview

㈜헬로앱스 코딩교육

유니티와 아두이노를 활용한

VR 컨트롤러 개발

김영준

공학박사, 목원대학교 겸임교수前 Microsoft 수석연구원

splduino@gmail.comhttp://www.helloapps.co.kr

유니티와 아두이노를 활용한 VR 컨트롤러 개발

목차 1. 툴 설치

2. 아두이노 컨트롤러 개발 실습

3. 유니티 기본 명령어 실습

4. 유니티 VR 콘텐츠 개발 실습

5. 블루투스를 이용한 아두이노 컨트롤러 연동 실습

유니티와 아두이노를 활용한 VR 컨트롤러 개발

SW 설치

유니티와 아두이노를 활용한 VR 컨트롤러 개발

SW 설치

Java SE (JDK) 설치

http://www.oracle.com/technetwork/java/javase/downloads/index.html

Google Android Studio 설치

https://developer.android.com/studio/index.html

유니티 설치

http://www.unity3d.com (회원 가입후 로그인 필요)

아두이노 코딩 SW 설치

(초보자) http://www.helloapps.co.kr/download

(전문가) http://www.arduino.cc

유니티와 아두이노를 활용한 VR 컨트롤러 개발

아두이노 컨트롤러 개발 실습

유니티와 아두이노를 활용한 VR 컨트롤러 개발

조이스틱 연결하기

Y축

X축

버튼

아날로그 0번

아날로그 1번

디지털 2번

아두이노 보드

유니티와 아두이노를 활용한 VR 컨트롤러 개발

아두이노 명령어

• digitalWrite (핀번호, 값)

• d = digitalRead(핀번호)

• a = analogRead(핀번호)

• delay(밀리초)

• a = map(a, 0, 1023, 0, 500)

유니티와 아두이노를 활용한 VR 컨트롤러 개발

LED 점멸 제어 실습

void setup()

{

}

void loop()

{

DigitalWrite(13, HIGH)

Delay(1000)

DigitalWrite(13, LOW)

Delay(1000)

}

실습)• LED 점멸 간격을 더 짧게 조절하기void setup()

{

pinMode(13, OUTPUT);

}

void loop()

{

digitalWrite(13, HIGH);

delay(1000);

digitalWrite(13, LOW);

delay(1000);

}

유니티와 아두이노를 활용한 VR 컨트롤러 개발

버튼값 읽기

void setup(){

}

void loop(){

d2 = DigitalRead(2)PrintLine(d2)Delay(100)

}

실습)• 버튼이 눌려지면 LED 켜기

void setup(){

pinMode(2, INPUT);Serial.begin(115200);

}

void loop(){

int d2 = digitalRead(2);Serial.println(d2);delay(100);

}

유니티와 아두이노를 활용한 VR 컨트롤러 개발

구구단 출력하기

Print와 PrintLine 명령어를 이용하여 다음과 같이 출력하시오

7 x 1 = 77 x 2 = 147 x 3 = 217 x 4 = 287 x 5 = 357 x 6 = 427 x 7 = 497 x 8 = 567 x 9 = 63

Print와 PrintLine 명령어를 이용하여 원하는문자열을 생성해 낼 수 있어야 함

유니티와 아두이노를 활용한 VR 컨트롤러 개발

조이스틱값 읽기

void setup(){

}

void loop(){

x = AnalogRead(0)y = AnalogRead(1)Print(x)Print(" / ")PrintLine(y)Delay(100)

}

조이스틱의 Y축 -> 아날로그 0번에 연결

조이스틱의 X축 -> 아날로그 1번에 연결

조이스틱을 옆으로 회전하여 사용하기 때문에

프로그램에서는 X축과 Y축을 변경하여 사용

Y축

X축

버튼

아날로그 0번

아날로그 1번

디지털 2번

void setup(){

Serial.begin(115200);}

void loop(){

int x = analogRead(0);int y = analogRead(1);Serial.print(x);Serial.print(" / ");Serial.println(y);delay(100);

}

유니티와 아두이노를 활용한 VR 컨트롤러 개발

Map 함수를 이용하여 값 변환하기

void setup(){

}

void loop(){

x = AnalogRead(0)y = AnalogRead(1)

x = map(x, 0, 1023, -500, 500)y = map(y, 0, 1023, -500, 500)

Print(x)Print(" / ")PrintLine(y)Delay(100)

}

void setup(){

Serial.begin(115200);}

void loop(){

int x = analogRead(0);int y = analogRead(1);

x = map(x, 0, 1023, -500, 500);y = map(y, 0, 1023, -500, 500);

Serial.print(x);Serial.print(" / ");Serial.println(y);delay(100);

}

유니티와 아두이노를 활용한 VR 컨트롤러 개발

Map 함수를 이용하여 값 변환하기

void setup(){

}

void loop(){

x = AnalogRead(0)y = AnalogRead(1)

x = map(x, 0, 1023, -500, 500)y = map(y, 0, 1023, -500, 500)

if (abs(x) < 30)x = 0

if (abs(y) < 30)y = 0

Print(x)Print(" / ")PrintLine(y)Delay(100)

}

void setup(){

Serial.begin(115200);}

void loop(){

int x = analogRead(0);int y = analogRead(1);

x = map(x, 0, 1023, -500, 500);y = map(y, 0, 1023, -500, 500);

if (abs(x) < 30)x = 0;

if (abs(y) < 30)y = 0;

Serial.print(x);Serial.print(" / ");Serial.println(y);delay(100);

}

유니티와 아두이노를 활용한 VR 컨트롤러 개발

외부 전송 데이터 생성하기

void loop(){

d = DigitalRead(2)x = AnalogRead(0)y = AnalogRead(1)

x = map(x, 0, 1023, -500, 500)y = map(y, 0, 1023, -500, 500)

if (abs(x) < 30)x = 0

if (abs(y) < 30)y = 0

Print("<")Print(d)Print(",")Print(x)Print(",")Print(y)PrintLine(">")Delay(100)

}

<d,x,y>

void setup(){

pinMode(2, INPUT);Serial.begin(115200);

}

void loop(){

int d = digitalRead(2);int x = analogRead(0);int y = analogRead(1);x = map(x, 0, 1023, -500, 500);y = map(y, 0, 1023, -500, 500);if (abs(x) < 30)

x = 0;if (abs(y) < 30)

y = 0;Serial.print("<");Serial.print(d);Serial.print(",");Serial.print(x);Serial.print(",");Serial.print(y);Serial.println(">");delay(100);

}

유니티와 아두이노를 활용한 VR 컨트롤러 개발

유니티 기본 명령어 실습

유니티와 아두이노를 활용한 VR 컨트롤러 개발

3D물체 생성하기

Object Component

Component

Component

Component

CubeTransform

Box Collider

Mesh Renderer

유니티와 아두이노를 활용한 VR 컨트롤러 개발

물체 제어하기

• Scene_Main으로 씬 저장

• Cube 오브젝트 추가

• Scripts 폴더 생성

• 새로운 C# 스크립트 생성

• 스크립트 이름은 RotateObject 로 수정

• Cube 오브젝트에 스크립트 연결

유니티와 아두이노를 활용한 VR 컨트롤러 개발

물체 제어하기

using System.Collections;using System.Collections.Generic;using UnityEngine;

public class RotateObject : MonoBehaviour {

Transform TR;

void Start () {TR = transform;

}

void Update () {TR.Rotate( new Vector3(0, 1, 0) );

}}

유니티와 아두이노를 활용한 VR 컨트롤러 개발

키보드로 물체 제어하기 (회전)

using System.Collections;using System.Collections.Generic;using UnityEngine;

public class RotateObject : MonoBehaviour {

Transform TR;

void Start () {TR = transform;

}

void Update () {float h = Input.GetAxis("Horizontal");TR.Rotate(new Vector3(0, h, 0));

}}

using System.Collections;using System.Collections.Generic;using UnityEngine;

public class RotateObject : MonoBehaviour {

Transform TR;

void Start () {TR = transform;

}

void Update () {float h = Input.GetAxis("Horizontal");float v = Input.GetAxis("Vertical");TR.Rotate(new Vector3(v, h, 0));

}}

유니티와 아두이노를 활용한 VR 컨트롤러 개발

키보드로 물체 제어하기 (이동)

using System.Collections;using System.Collections.Generic;using UnityEngine;

public class RotateObject : MonoBehaviour {

Transform TR;

void Start () {TR = transform;

}

void Update () {float h = Input.GetAxis("Horizontal");float v = Input.GetAxis("Vertical");

TR.Rotate(new Vector3(0, h, 0));TR.Translate(TR.forward * v);

}}

유니티와 아두이노를 활용한 VR 컨트롤러 개발

에셋 추가하기

• 유니티 에셋스토어 접속

• Free Sci-Fi Textures 검색

• Download 및 설치

유니티와 아두이노를 활용한 VR 컨트롤러 개발

에셋 추가하기

• Plane 추가

• 바닥에 텍스처 추가

• Cube에 텍스처 추가

유니티와 아두이노를 활용한 VR 컨트롤러 개발

키보드로 물체 생성하기

• Cube 오브젝트에서 RotateObject 스크립트 제거

• Cube 오브젝트에 질량을 추가해 준다.

• 빈 오브젝트 생성

• 이름을 GameControlObject로 수정

• 새로운 C# 스크립트 생성

• 스크립트 이름은 MainControlScript 로 수정

• 빈 오브젝트에 스크립트 연결

유니티와 아두이노를 활용한 VR 컨트롤러 개발

키보드로 물체 생성하기

public class MainControlScript : MonoBehaviour {

public GameObject CubeObject;

void Start () {

}

void Update () {

if (Input.GetKeyDown(KeyCode.Space)){

Instantiate(CubeObject, new Vector3(0, 5, 0), Quaternion.identity);}

}}

유니티와 아두이노를 활용한 VR 컨트롤러 개발

랜덤 위치에 물체 생성하기

public class MainControlScript : MonoBehaviour {

public GameObject CubeObject;

void Start () {

}

void Update () {

if (Input.GetKeyDown(KeyCode.Space)){

float x = Random.Range(-10f, 10f);float z = Random.Range(-10f, 10f);Instantiate(CubeObject, new Vector3(x, 10, z), Quaternion.identity);

}

}}

유니티와 아두이노를 활용한 VR 컨트롤러 개발

임의의 방향으로 떨어지도록 하기

public class MainControlScript : MonoBehaviour {

public GameObject CubeObject;

void Start () {

}

void Update () {

if (Input.GetKeyDown(KeyCode.Space)){

float x = Random.Range(-10f, 10f);float z = Random.Range(-10f, 10f);

float o_x = Random.Range(-45f, 45f);float o_y = Random.Range(-45f, 45f);float o_z = Random.Range(-45f, 45f);

GameObject new_object = Instantiate(CubeObject, new Vector3(x, 10, z), Quaternion.identity);new_object.transform.eulerAngles = new Vector3(o_x, o_y, o_z);

}

}}

유니티와 아두이노를 활용한 VR 컨트롤러 개발

유니티 VR 콘텐츠 개발 실습

유니티와 아두이노를 활용한 VR 컨트롤러 개발

탄성 기능 추가

• 바닥에 RigidBody 컴포넌트 추가

• IsKinematic 선택

유니티와 아두이노를 활용한 VR 컨트롤러 개발

탄성 기능 추가

• Asset -> Create -> Physical Materials 생성

• Cube와 Plane에 할당

유니티와 아두이노를 활용한 VR 컨트롤러 개발

일정한 간격으로 자동으로 떨어지도록 기능 수정

public class MainControlScript : MonoBehaviour {

public GameObject CubeObject;

float temp_time = 0;

void Start () {

}

void Update () {

if ((Time.time - temp_time) > 1){

temp_time = Time.time;

float x = Random.Range(-10f, 10f);float z = Random.Range(-10f, 10f);

float o_x = Random.Range(-45f, 45f);float o_y = Random.Range(-45f, 45f);float o_z = Random.Range(-45f, 45f);

GameObject new_object = Instantiate(CubeObject, new Vector3(x, 10, z), Quaternion.identity);new_object.transform.eulerAngles = new Vector3(o_x, o_y, o_z);

}}

}

유니티와 아두이노를 활용한 VR 컨트롤러 개발

종료기능 추가

public class MainControlScript : MonoBehaviour {

public GameObject CubeObject;float temp_time = 0;void Start () {

}

void Update () {

if ((Time.time - temp_time) > 1){

temp_time = Time.time;

float x = Random.Range(-10f, 10f);float z = Random.Range(-10f, 10f);

float o_x = Random.Range(-45f, 45f);float o_y = Random.Range(-45f, 45f);float o_z = Random.Range(-45f, 45f);

GameObject new_object = Instantiate(CubeObject, new Vector3(x, 10, z), Quaternion.identity);new_object.transform.eulerAngles = new Vector3(o_x, o_y, o_z);

}

if (Input.GetKeyDown(KeyCode.Escape))Application.Quit();

}}

유니티와 아두이노를 활용한 VR 컨트롤러 개발

실행 파일 빌드 테스트 (윈도우 버전)

유니티와 아두이노를 활용한 VR 컨트롤러 개발

VR 세팅

유니티와 아두이노를 활용한 VR 컨트롤러 개발

AR 카메라 추가

유니티와 아두이노를 활용한 VR 컨트롤러 개발

AR 카메라 설정

유니티와 아두이노를 활용한 VR 컨트롤러 개발

AR 카메라 설정

유니티와 아두이노를 활용한 VR 컨트롤러 개발

AR 카메라 설정

유니티와 아두이노를 활용한 VR 컨트롤러 개발

안드로이드 빌드하기

유니티와 아두이노를 활용한 VR 컨트롤러 개발

안드로이드 배포하기

• 생성된 APK 파일을 USB 케이블로 복사 후 설치

• 케이블이 없는 경우, 본인의 이메일로 파일 배포후 설치

유니티와 아두이노를 활용한 VR 컨트롤러 개발

블루투스를 이용한 아두이노

컨트롤러 연동 실습

유니티와 아두이노를 활용한 VR 컨트롤러 개발

아두이노 보드에 블루투스 연결하기

• 아두이노 보드의 디지털 0번과 1번에 각각 블루투스 Rx, Tx 케이블을 연결한다.

• GND와 5V 케이블도 아두이노의 GND와 5V 핀에 연결한다.

유니티와 아두이노를 활용한 VR 컨트롤러 개발

블루투스 패키지 설치하기

• 강사를 통해 배포된 HelloApps 블루투스 커스텀 패키지 복사 및 설치

HelloAppsBT.unitypackage

유니티와 아두이노를 활용한 VR 컨트롤러 개발

블루투스 패키지 설치하기

유니티와 아두이노를 활용한 VR 컨트롤러 개발

블루투스 패키지 설치하기

유니티와 아두이노를 활용한 VR 컨트롤러 개발

블루투스 패어링하기

• 안드로이드 스마트폰에서 블루투스 켜기

• 장치 추가한 후, 아두이노에 연결되어 있는 블루투스 이름 검색후 추가

• 비밀번호는 “1234” 입력

유니티와 아두이노를 활용한 VR 컨트롤러 개발

블루투스 디바이스 이름 추가하기using UnityEngine;using System.Collections;

public class BTBasicScript : MonoBehaviour{

string fromArduino = "" ;

void Start (){

BtConnector.moduleName ("SPL V3 B0015");BtConnector.connect();

}

void Update(){

if (Input.GetKeyDown(KeyCode.Escape)){

BtConnector.close();}

if (BtConnector.isConnected() && BtConnector.available()){

fromArduino = BtConnector.readLine();}

}

void OnGUI(){

GUI.Label(new Rect(0, 20, Screen.width, Screen.height*0.1f),"Arduino : " + fromArduino);GUI.Label(new Rect(Screen.width * 0.5f, 20, Screen.width, Screen.height * 0.1f), “Status : " + BtConnector.readControlData());

}}

유니티와 아두이노를 활용한 VR 컨트롤러 개발

디바이스 연결 테스트

• 앱 빌드후 배포

• 아두이노 보드 전원 재연결

• 앱 실행

프로그램 상단에 연결 및 메시지 정보 표시되는 지 확인

유니티와 아두이노를 활용한 VR 컨트롤러 개발

카메라 이동과 회전 제어

using System.Collections;using System.Collections.Generic;using UnityEngine;

public class BTControl_Sample_01 : MonoBehaviour{

public GameObject AR_Camera_Container;public GameObject Cube_Object;

string fromArduino = "";

Transform TR = null;

void Start(){

TR = AR_Camera_Container.transform;

BtConnector.moduleName("SPL V3 B0015");BtConnector.connect();

}

…}

void Update(){

if (Input.GetKeyDown(KeyCode.Escape)){

BtConnector.close();}

if (BtConnector.isConnected() && BtConnector.available()){

fromArduino = BtConnector.readLine();

if (fromArduino.StartsWith("<") && fromArduino.EndsWith(">")){

string data = fromArduino.TrimStart('<').TrimEnd('>');string[] arr = data.Split(new char[] { ',' });

string btn = arr[0];float x = float.Parse(arr[1]);float y = float.Parse(arr[2]);

x = x / 500f;y = y / 500f;

TR.Translate(transform.forward * Time.deltaTime * y * 5);TR.Rotate(new Vector3(0, Time.deltaTime * x * -10, 0));

}}

}

유니티와 아두이노를 활용한 VR 컨트롤러 개발

박스 발사하는 기능 추가

using System.Collections;using System.Collections.Generic;using UnityEngine;

public class BTControl_Sample_02 : MonoBehaviour {

public GameObject AR_Camera_Container;public GameObject AR_Camera;public GameObject Cube_Object;

string fromArduino = "";

Transform TR = null;

void Start(){

TR = AR_Camera_Container.transform;

BtConnector.moduleName("SPL V3 B0015");BtConnector.connect();

}

}

void Update(){

if (Input.GetKeyDown(KeyCode.Escape)){

BtConnector.close();}

if (BtConnector.isConnected() && BtConnector.available()){

fromArduino = BtConnector.readLine();

if (fromArduino.StartsWith("<") && fromArduino.EndsWith(">")){

string data = fromArduino.TrimStart('<').TrimEnd('>');string[] arr = data.Split(new char[] { ',' });

string btn = arr[0];float x = float.Parse(arr[1]);float y = float.Parse(arr[2]);

x = x / 500f;y = y / 500f;

TR.Translate(transform.forward * Time.deltaTime * y * 5);TR.Rotate(new Vector3(0, Time.deltaTime * x * -10, 0));

if (btn == "0"){

GameObject new_object = Instantiate<GameObject>(Cube_Object, TR.position, TR.rotation);

Rigidbody rb = new_object.transform.GetComponent<Rigidbody>();

rb.AddForce(AR_Camera.transform.forward * 1000);}

}}

}

Recommended