BallController Script를 만든다
SetBallPosition()이라는 함수를 만든다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BallController : MonoBehaviour
{
Rigidbody rb; //녹색은 값을 넣어줘야함.
//공이 준비 상태인지 확인하는 변수
bool isReady = true;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody>();
//리지드 바디의 물리 능력을 비활성화
rb.isKinematic = true;
}
// Update is called once per frame
void Update()
{
//공을 카메라 전방 하단에 배치
SetBallPosition(Camera.main.transform);
}
void SetBallPosition(Transform anchor)
{
//카메라의 위치로부터 일정 거리만큼 떨어진 위치 설정
// Vector3 = anchor로 부터 앞으로 0.5+ anchor로 부터 아래로 0.2
Vector3 offset = anchor.forward * 0.5f + anchor.up * -0.2f;
//공의 위치를 offset만큼 이동
transform.position = anchor.position + offset;
}
}
Ball에 스크립트를 끌어다 놓고
공을 발사하고 3초후 공을 다시 만들어 주기위해 타이머를 만들어야 하는데 수업에서는 invoker를 사용하였다.
3초가 지나면 Ball을 Reset()해줘 위치를 초기화 해준다.
void Update()에서 터치후 드래그시 공에 addForce로 공을 약간 위로 나가게 해준다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class BallController : MonoBehaviour
{
Rigidbody rb;
// 공이 준비 상태인지 확인하는 변수
bool isReady = true;
// 터치 시작 지점
Vector2 startPos;
// 공을 초기화 할 시간
float resetTime = 3f;
// 포획 확률
float captureRate = 0.5f;
// 포획 결과 텍스트
public Text result;
// Start is called before the first frame update
void Start()
{
// 포획 결과 텍스트 초기화
result.text = "";
rb = GetComponent<Rigidbody>();
// 리지드 바디의 물리 능력을 비활성화
rb.isKinematic = true;
}
// Update is called once per frame
void Update()
{
if (!isReady)
{
return;
}
// 터치가 입력 되었고, 공이 준비 상태라면
if (Input.touchCount > 0 && isReady)
{
Touch touch = Input.GetTouch(0);
// 만약 터치를 시작했다면
if (touch.phase == TouchPhase.Began)
{
// 시작 지점 저장
startPos = touch.position;
}
// 터치가 끝났다면
else if (touch.phase == TouchPhase.Ended)
{
// 드래그한 y축 거리를 계산
float dragDistance = touch.position.y - startPos.y;
// 카메라를 기준으로 45도 각도 계산
Vector3 throwAngle = (Camera.main.transform.forward
+ Camera.main.transform.up).normalized;
// 물리 능력 활성화
rb.isKinematic = false;
// 준비 상태 변경
isReady = false;
// 던질 방향과 드래그 거리만큼 공에 물리적 힘을 더함
rb.AddForce(throwAngle * dragDistance * 0.005f, ForceMode.VelocityChange);
// 3초 뒤에 공의 위치와 속도 초기화
Invoke("ResetBall", resetTime);
}
}
// 공을 카메라 전방 하단에 배치
SetBallPosition(Camera.main.transform);
}
void SetBallPosition(Transform anchor)
{
// 카메라의 위치로부터 일정 거리만큼 떨어진 위치 설정
// Vector3 = anchor로부터 앞으로 0.5 + anchor로부터 아래로 0.2
Vector3 offset = anchor.forward * 0.5f + anchor.up * -0.2f;
// 공의 위치를 카메라 위치로부터 offset만큼 이동
transform.position = anchor.position + offset;
}
void ResetBall()
{
// 물리 능력 비활성화
rb.isKinematic = true;
// 속도 초기화
rb.velocity = Vector3.zero;
// 준비 상태로 변경
isReady = true;
}
private void OnCollisionEnter(Collision collision)
{
if (isReady)
{
return;
}
// 포획 확률을 랜덤한 값으로 설정
float draw = Random.Range(0, 1f);
// 만약 랜덤 값이 captureRate 보다 작다면 포획 성공
if (draw <= captureRate)
{
result.text = "포획에 성공했습니다!";
}
// 그렇지 않다면 포획 실패
else
{
result.text = "포획에 실패하여 도망쳤습니다.";
}
// 마커 오브젝트 제거
Destroy(collision.gameObject);
// 공 비활성화
gameObject.SetActive(false);
}
}
하이라키+를 눌러 Leagacy Text를 추가해준다.
Canvas Scaler는 Scale with Screen Size로 해주고 해상도는 다음과 같이해준다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class BallController : MonoBehaviour
{
Rigidbody rb;
// 공이 준비 상태인지 확인하는 변수
bool isReady = true;
// 터치 시작 지점
Vector2 startPos;
// 공을 초기화 할 시간
float resetTime = 3f;
// 포획 확률
float captureRate = 0.5f;
// 포획 결과 텍스트
public Text result;
public GameObject effect;
// Start is called before the first frame update
void Start()
{
// 포획 결과 텍스트 초기화
result.text = "";
rb = GetComponent<Rigidbody>();
// 리지드 바디의 물리 능력을 비활성화
rb.isKinematic = true;
}
// Update is called once per frame
void Update()
{
if (!isReady)
{
return;
}
// 터치가 입력 되었고, 공이 준비 상태라면
if (Input.touchCount > 0 && isReady)
{
Touch touch = Input.GetTouch(0);
// 만약 터치를 시작했다면
if (touch.phase == TouchPhase.Began)
{
// 시작 지점 저장
startPos = touch.position;
}
// 터치가 끝났다면
else if (touch.phase == TouchPhase.Ended)
{
// 드래그한 y축 거리를 계산
float dragDistance = touch.position.y - startPos.y;
// 카메라를 기준으로 45도 각도 계산
Vector3 throwAngle = (Camera.main.transform.forward
+ Camera.main.transform.up).normalized;
// 물리 능력 활성화
rb.isKinematic = false;
// 준비 상태 변경
isReady = false;
// 던질 방향과 드래그 거리만큼 공에 물리적 힘을 더함
rb.AddForce(throwAngle * dragDistance * 0.005f, ForceMode.VelocityChange);
// 3초 뒤에 공의 위치와 속도 초기화
Invoke("ResetBall", resetTime);
}
}
// 공을 카메라 전방 하단에 배치
SetBallPosition(Camera.main.transform);
}
void SetBallPosition(Transform anchor)
{
// 카메라의 위치로부터 일정 거리만큼 떨어진 위치 설정
// Vector3 = anchor로부터 앞으로 0.5 + anchor로부터 아래로 0.2
Vector3 offset = anchor.forward * 0.5f + anchor.up * -0.2f;
// 공의 위치를 카메라 위치로부터 offset만큼 이동
transform.position = anchor.position + offset;
}
void ResetBall()
{
// 물리 능력 비활성화
rb.isKinematic = true;
// 속도 초기화
rb.velocity = Vector3.zero;
// 준비 상태로 변경
isReady = true;
}
private void OnCollisionEnter(Collision collision)
{
if (isReady)
{
return;
}
// 포획 확률을 랜덤한 값으로 설정
float draw = Random.Range(0, 1f);
// 만약 랜덤 값이 captureRate 보다 작다면 포획 성공
if (draw <= captureRate)
{
result.text = "포획에 성공했습니다!";
}
// 그렇지 않다면 포획 실패
else
{
result.text = "포획에 실패하여 도망쳤습니다.";
}
//이펙트생성
Instantiate(effect, collision.gameObject.transform.position, Camera.main.transform.rotation);
// 마커 오브젝트 제거
Destroy(collision.gameObject);
// 공 비활성화
gameObject.SetActive(false);
}
}
Asset Store에서 이펙트를 찾아 다운로드해주고
Import해준다.
스크립트에 effect변수에 import한 이펙트를 끌어다 놔준다. UI LegacyText로 끌어다 놔준다
실행해서 마커를 촬용하면 고양이가 나오고 볼을 드래그해서 맞추면 폭발이 일어나는데 확율에 의해 성공과 실패가 나뉜다.
실제 해보면 공의 초기 위치와 고양이의 위치가 비슷해 고양이가 공위에 있다. AddForce가 앞으로 날라가기때문에 맞지 않는다. 공위로 고양이가 있을때 억지로 가깝게 해서 맞춰줘야야만 한다. 난 공을 좀더 카메라쪽(-) 고양이를 뒤로 위치시켜 거리를 만들어 공이 앞으로 날라가다 맞게 해주었다
'AR > 24 KMOOC 비주얼심화과정' 카테고리의 다른 글
Unity 타이머 (0) | 2024.07.08 |
---|---|
Unity 타이머 (0) | 2024.07.06 |
7/3 강의 마커기반 AR (0) | 2024.07.03 |
7/1 FaceTracking2 (1) | 2024.07.03 |
4일차 FaceTracking (6.30 강의) (3) | 2024.06.30 |