• 검색 결과가 없습니다.

VR 컨트롤러 개발

N/A
N/A
Protected

Academic year: 2021

Share "VR 컨트롤러 개발"

Copied!
49
0
0

로드 중.... (전체 텍스트 보기)

전체 글

(1)

㈜헬로앱스 코딩교육

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

김영준

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

(2)

목차 1. 툴 설치

2. 아두이노 컨트롤러 개발 실습 3. 유니티 기본 명령어 실습

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

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

(3)

SW 설치

(4)

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

(5)

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

(6)

조이스틱 연결하기

Y축 X축 버튼

아날로그 0번 아날로그 1번

디지털 2번

아두이노 보드

(7)

아두이노 명령어

• digitalWrite (핀번호, 값)

• d = digitalRead(핀번호)

• a = analogRead(핀번호)

• delay(밀리초)

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

(8)

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);

}

(9)

버튼값 읽기

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);

}

(10)

구구단 출력하기

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

7 x 1 = 7 7 x 2 = 14 7 x 3 = 21 7 x 4 = 28 7 x 5 = 35 7 x 6 = 42 7 x 7 = 49 7 x 8 = 56 7 x 9 = 63

Print와 PrintLine 명령어를 이용하여 원하는

문자열을 생성해 낼 수 있어야 함

(11)

조이스틱값 읽기

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);

}

(12)

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);

}

(13)

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);

}

(14)

외부 전송 데이터 생성하기

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);

}

(15)

유니티 기본 명령어 실습

(16)

3D물체 생성하기

Object

Component Component Component Component

Cube

Transform Box Collider

Mesh Renderer

(17)

물체 제어하기

• Scene_Main으로 씬 저장

• Cube 오브젝트 추가

• Scripts 폴더 생성

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

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

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

(18)

물체 제어하기

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) );

} }

(19)

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

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));

} }

(20)

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

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);

} }

(21)

에셋 추가하기

• 유니티 에셋스토어 접속

• Free Sci-Fi Textures 검색

• Download 및 설치

(22)

에셋 추가하기

• Plane 추가

• 바닥에 텍스처 추가

• Cube에 텍스처 추가

(23)

키보드로 물체 생성하기

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

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

• 빈 오브젝트 생성

• 이름을 GameControlObject로 수정

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

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

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

(24)

키보드로 물체 생성하기

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);

}

} }

(25)

랜덤 위치에 물체 생성하기

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);

} } }

(26)

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

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);

}

} }

(27)

유니티 VR 콘텐츠 개발 실습

(28)

탄성 기능 추가

• 바닥에 RigidBody 컴포넌트 추가

• IsKinematic 선택

(29)

탄성 기능 추가

• Asset -> Create -> Physical Materials 생성

• Cube와 Plane에 할당

(30)

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

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);

}

(31)

종료기능 추가

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))

(32)

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

(33)

VR 세팅

(34)

AR 카메라 추가

(35)

AR 카메라 설정

(36)

AR 카메라 설정

(37)

AR 카메라 설정

(38)

안드로이드 빌드하기

(39)

안드로이드 배포하기

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

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

(40)

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

컨트롤러 연동 실습

(41)

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

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

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

(42)

블루투스 패키지 설치하기

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

HelloAppsBT.unitypackage

(43)

블루투스 패키지 설치하기

(44)

블루투스 패키지 설치하기

(45)

블루투스 패어링하기

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

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

• 비밀번호는 “1234” 입력

(46)

블루투스 디바이스 이름 추가하기

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());

(47)

디바이스 연결 테스트

• 앱 빌드후 배포

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

• 앱 실행

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

(48)

카메라 이동과 회전 제어

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));

} } }

(49)

박스 발사하는 기능 추가

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);

} }

참조

관련 문서

* 주위에서 실제 발생하는 복사 열전달

 자원보유국이 필요로 하는 신재생에너지 기술의 개발 경험과 대외경제협력 기금 지원을 통해 win-win 전략 도모.  정책자금과 연계한 은행권의 협조융자 제도와

- ESCO 투자 민간자금 확대 및 합리적인 사업성과 평가방법 (M&amp;V) 지속 개발 보급을 통해 ESCO 사업 활성화.. 에너지공급자

스키의 과학적 원리 를 재미있는 활동을 통해 이해할 뿐만 아니라 VR기술도 자연스럽게 경험하게 됨으로써 스포츠 외에 VR 기술을 활용하는 다양한

Ÿ 점도가 높은 액제의 단위시간당 이동거리가 달라짐을 관찰하고, 이를 이용 하여 점도에 따는 혈액점도 측정용 종이미세유체칩 개발 및 실제 혈액을 통해

교사 연구회에서의 공동 수업 연구 및 개발 활동을 통해 각 교사에게 더 많은 교육적 아이 디어를 제공하는 것은 물론, 서로 다른 교과의 융합을 통해 더욱 다양한 교과와의

학생 참여형 과학수업 형태의 STEAM 수업프로그램 개발 및 생활기록부 기재까지 연계한 평가 계획 ․적용을 통해 교육 트렌드에

도시개발구역 지정을 위한 도시계획위원회 상정 전 공공기여시설 설치량 , 공공기여시설의 종류 및 위치, 설치 방법 등을 인천시와 협상을