nomalized
대각선도 1로 만들어주기

회전
오일러 Euler
Degree = 사람이 읽을 수 있음
0 ~ 360도
오일러 회전
순서대로 하나의 축씩 회전
짐벌락 이슈
x축만 돌려도 x, y축 병합됨

x축이 안보임
쿼터니언 Quaternion
회전축 개념이라 사람이 읽을 수 없음
쿼터니언 회전
가상의 축 기반으로 3축이 동시에 회전
사람이 알아보기 힘든 회전 값
허수, 복소수, 쿼터니언 등 개념이 들어감
허수축 개념

x의 몫을 구할 수 없음
따라서 가상의 축(허수축)을 그어서

-i, i(허수) 찾아냄
Inspector view에서 debuger 체크하면 회전값 보임


디버그 모드로 잘 보진 않음
스크립트 쓸 땐
내부적으로 쿼터니언인데 오일러로 쓸 수 있음
쿼터니언이랑 오일러 왔다갔다 할 수 있음
초기화
void Start()
{
// 자기 자신의 위치를 0, 0, 0으로 설정
transform.position = Vector3.zero;
// 자기 자신의 회전을 0, 0, 0으로 설정
transform.rotation = Quaternion.identity; // 월드 기준으로 정면을 바라보는 원점 회전
// 자기 자신의 크기를 1, 1, 1로 설정
transform.localScale = Vector3.one;
}
해당 코드는 다음 동작과 똑같음

회전 종류
Rotate
특정 축으로 회전
일반적으로는 y축 기준으로 회전함

Vector로 임의로 각도를 만들어서 transform.rotation에 넣으려고 하면 타입 에러가 남
따라서 오일러 → 쿼터니언 변환해줘야 함
// 원하는 각도로 회전 바꾸는 코드
transform.rotation = Quaternion.Euler(newRotation);
반대로 쿼터니언 → 오일러 변환도 가능
// 사용자가 보려면 쿼터니언 -> 오일러 변환 필요
Debug.Log(transform.rotation.eulerAngles);
최종 코드
void Start()
{
Vector3 newRotation = new Vector3(0, rot, 0); // y축으로 30도
// 원하는 각도로 회전 바꾸는 코드
transform.rotation = Quaternion.Euler(newRotation);
// 사용자가 보려면 쿼터니언 -> 오일러 변환 필요
Debug.Log(transform.rotation.eulerAngles);
// 자기 자신의 위치를 0, 0, 0으로 설정
transform.position = Vector3.zero;
// 자기 자신의 회전을 0, 0, 0으로 설정
transform.rotation = Quaternion.identity; // 월드 기준으로 정면을 바라보는 원점 회전
// 자기 자신의 크기를 1, 1, 1로 설정
transform.localScale = Vector3.one;
}
계속 회전 시키기
public float rotSpeed = 30f;
void Update()
{
// 자기 자신이 Y축으로 회전하는 코드
transform.Rotate(rotSpeed * Time.deltaTime * Vector3.up);
}
transform : 자기 자신의
Rotate : 회전
Vector3.up : y축으로
rotSpeed : 속도는 30f로
Time.deltaTime : deltaTime으로
실행 결과

에러 해결
코드 짜는데 이런 에러가 남

'Vector3' is an ambiguous reference between 'UnityEngine.Vector3' and 'System.Numerics.Vector3'
읽어보니 System.Numerics에도 Vector3가 있어서 에러가 남
나는 유니티의 벡터를 사용할 것이기 때문에 using 문에 System.Numerics를 제거해줌
아마 뭐 코드 수정하다가 자동 using 된 듯
using System.Collections;
using System.Collections.Generic;
using System.Numerics; <-
using UnityEngine;
에러 해결!
빈 게임 오브젝트 표시하기
잘 안보이기 때문에 보통 아래와 같은 방법을 사용함
Inspector View에서 정육면체 눌러서 라벨 달 수 있음


RotateAround
특정 대상 기준으로 회전하는 코드

// 특정 대상 기준으로 회전하는 코드
transform.RotateAround(target.position, Vector3.up, rotSpeed * Time.deltaTime);
// 회전할 물체 특정 대상 회전축
유니티에서 target 할당


자기 자신 회전 + 타겟 대상 회전

LookAt
특정 방향을 바라보는 기능
Vector3 dir = new Vector3(h, 0, v).normalized; // 입력한 값으로 Vector3 선언 및 할당
transform.position += dir * moveSpeed * Time.deltaTime; // 입력한 값으로 이동 기능
// 캐릭터가 이동하려는 방향을 바라보게 하는 코드
Vector3 targetPos = transform.position + dir; // 목표 위치
// 현재 위치(자기 자신의 위치) + 입력 값에 의한 방향
transform.LookAt(targetPos); // 목표 위치를 바라보는 코드

키를 누를 때만 회전하도록 조건을 걸어줘야 버그 방지 가능
손을 뗐을 때 캐릭터가 회전하면 안됨
if (h != 0 || v != 0) // h, v로 입력 들어올 때 = wasd중 하나라도 눌렀을 때
{
// 캐릭터가 이동하려는 방향을 바라보게 하는 코드
Vector3 targetPos = transform.position + dir; // 목표 위치
// 현재 위치(자기 자신의 위치) + 입력 값에 의한 방향
transform.LookAt(targetPos); // 목표 위치를 바라보는 코드
}
3차원에서 태양계 회전
유니티에서 에셋 다운
https://assetstore.unity.com/packages/3d/environments/planets-of-the-solar-system-3d-90219

근데 깨짐(Magenta : Hi)

Built-in(지금 프로젝트), URP(다운 받은 에셋) 충돌 이슈
Built-in은 구버전, URP는 신버전

깨진 항목 잡아서 쉐이더 변경
현재 Hidden = 설정 안되어 있다고 보면 됨


그러면 나오긴 함

받은 Scene 열기

태양은 URP로 안해서 이상하게 나옴

임시 수정

렌더링 모드, Albedo 수정

Emission 체크해서 방출 색 변경

결과물

플레이 하면서 수정했던 값들을 남기고 싶으면 속성 복사해서 붙여넣기 하면 됨

Material은 그냥 꺼도 남아있음
자전, 공전 스크립트
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RotationTarget : MonoBehaviour
{
public Transform target;
public float rotSpeed, rotAroundSpeed = 0f;
void Start()
{
}
void Update()
{
// 자전
// 자기 자신이 회전하는 기능 -> Rotate
transform.Rotate(Vector3.up, rotSpeed * Time.deltaTime);
// 공전
// 다른 대상을 기준으로 회전하는 기능 -> RotateAround
transform.RotateAround(target.position, Vector3.up * rotAroundSpeed * Time.deltaTime);
}
}
Skybox 바꾸기

드래그앤드랍으로 적용 가능

메인 카메라에 원근법 적용

크기, 위치 조정 후 스크립트 넣기

아래처럼 랜덤으로 회전 스피드 값 넣어줄 수 있음

스피드 천천히 가도록 조절한 결과물

근데 달이 이상하게 돌고 있음

해결하려면 계층 구조를 잡아줘야 함
→ 달이 지구와 같은 계층에서 움직이는 지구를 따라가는 게 아니라, 지구의 자식이 되어 그 안에서 지구를 기준으로 돌도록 하면 해결됨


카메라가 object 따라가는 단축키 : shift + f
콜라이더 Collider
충돌 또는 감지하는 영역
충돌이나 감지를 선택적으로 하는 Component
충돌과 감지를 위해서는 콜라이더 + 리자드바디가 필요함
ex. 상호작용 - 이벤트 발생
캐릭터 이동 키, 공격 키 → 입력 이벤트 발생
캐릭터가 이동하다 벽에 부딪힘 → 충돌 이벤트 발생

콜라이더 종류

Mesh Collider
Mesh : 형태, 모양 데이터
Mesh 기반의 콜라이더


이런 느낌으로 면마다 콜라이더가 만들어짐
= 면마다 물리적으로 충돌, 감지하는 기능이 있음
⇒ 하이폴리로 너무 세세하게 되어있으면 게임 터짐 = 안돌아감
ex. 화살 맞을 때 화살 꽂히는 모습 등
특별한 경우가 아니면 잘 안씀
보통 단순화해서 사용함

Collider 영역 수정


Edit Collider 버튼 누르면 수정 가능한 점이 생김

점을 drag&drop으로 움직여서 직접 변경 가능

숫자값으로도 변경 가능

Is Trigger
충돌, 감지 선택

자동차의 충돌 Collision 이벤트


총알의 감지 Trigger 이벤트


is Trigger에 따라 충돌, 감지가 바뀜
isTrigger = false일 경우
충돌 이벤트 발생 → 적이 총알과 충돌하여 넘어짐

isTrigger = true일 경우
감지 이벤트만 발생 → 총알을 감지하여 체력 감소 등등 적용 가능

Rigidbody
물리 연산을 하는 Component
Collider는 영역이라면 Rigidbody는 계산
컴포넌트 추가


중력 적용됨

파란 공 isTrigger 체크하니 뚫고 지나감(감지함)

Plain은 기본적으로 Mesh Collider가 설정되어 있지만 그냥 Box Collider를 사용하기도 함
Event 3단계
Event는 기본적으로 3단계임
시작 → 실행중 → 종료
Start() → Update() → OnDestroy()
GetKeyDown → GetKey → GetKeyUp
이는 충돌 이벤트, 감지 이벤트도 마찬가지
충돌 이벤트 Collision Event
onCollisionEnter → OnCollisionStay → OnCollisionExit
감지 이벤트 Trigger Event
OnTriggerEnter → OnTriggerStay → OnTriggerExit
Collider Event 스크립트 작성
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ColliderEvent : MonoBehaviour
{
public void OnCollisionEnter(Collision collision)
{
Debug.Log("충돌 Enter");
}
public void OnCollisionStay(Collision collision)
{
Debug.Log("충돌 Stay");
}
public void OnCollisionExit(Collision collision)
{
Debug.Log("충돌 Exit");
}
}
예상 시나리오
해당 스크립트를 땅(Plain)에 적용하면 공이 땅에 충돌하는 순간 땅에서 감지할 예정


Stay는 1-3초 있다가 무시함(추가로 로그가 쌓이지 않음)
공을 위로 보내니 Exit가 뜸
Trigger Event 스크립트 작성
public void OnTriggerEnter(Collider other)
{
Debug.Log("감지 Enter");
}
public void OnTriggerStay(Collider other)
{
Debug.Log("감지 Stay");
}
public void OnTriggerExit(Collider other)
{
Debug.Log("감지 Exit");
}

문 예제 만들어보기
문은 회전축이 중요함
빈게임 오브젝트 만들어서 v(vertex snap)으로 회전축 위치 이동

계층 만들어주기

ctrl+6으로 Animation 키기

녹화 버튼 누르면 AddKey 가능

완성

번외 : 회전문

ㅋㅋ이렇게 하면 360도를 넘어가기 때문에 Quaternion이 됨
추가
장갑 만드는 법
손(부모) 기준으로 장갑(자식)이 있기 때문에 Local Position 이용
-> 먼저 만든 왼쪽 장갑의 Transform -> Copy -> Component로 복사하여 복사한 오른쪽 장갑에 붙여넣기하면 됨


간단한 3인칭 이동 만들기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TPSMovement : MonoBehaviour
{
float h;
float v;
float moveSpeed = 10f;
public float rotSpeed = 50f;
void Update()
{
h = Input.GetAxis("Horizontal");
v = Input.GetAxis("Vertical");
Move();
Turn();
}
private void Move() // W, S 이동
{
transform.Translate(Vector3.forward * v * moveSpeed * Time.deltaTime);
}
private void Turn() // A, D 회전
{
transform.Rotate(Vector3.up, h * rotSpeed * Time.deltaTime);
}
}

사담
오늘은 새로 접하는 개념이 많이 나와서 재밌었다!
이동이 가장 기본적인 기능이라 할만하지 않을까? 생각했는데 역시 세상에 쉬운 일 없다고
다양한 방법이 있고 자신이 추구하는 기획에 맞춰 구현해야 한다고 강사님이 설명해주셨다. (+딥하게 들어가면 여러개념이 있다~)
그래도 차근차근하니까 되긴 되네...
재밌다!
nomalized
대각선도 1로 만들어주기

회전
오일러 Euler
Degree = 사람이 읽을 수 있음
0 ~ 360도
오일러 회전
순서대로 하나의 축씩 회전
짐벌락 이슈
x축만 돌려도 x, y축 병합됨

x축이 안보임
쿼터니언 Quaternion
회전축 개념이라 사람이 읽을 수 없음
쿼터니언 회전
가상의 축 기반으로 3축이 동시에 회전
사람이 알아보기 힘든 회전 값
허수, 복소수, 쿼터니언 등 개념이 들어감
허수축 개념

x의 몫을 구할 수 없음
따라서 가상의 축(허수축)을 그어서

-i, i(허수) 찾아냄
Inspector view에서 debuger 체크하면 회전값 보임


디버그 모드로 잘 보진 않음
스크립트 쓸 땐
내부적으로 쿼터니언인데 오일러로 쓸 수 있음
쿼터니언이랑 오일러 왔다갔다 할 수 있음
초기화
void Start()
{
// 자기 자신의 위치를 0, 0, 0으로 설정
transform.position = Vector3.zero;
// 자기 자신의 회전을 0, 0, 0으로 설정
transform.rotation = Quaternion.identity; // 월드 기준으로 정면을 바라보는 원점 회전
// 자기 자신의 크기를 1, 1, 1로 설정
transform.localScale = Vector3.one;
}
해당 코드는 다음 동작과 똑같음

회전 종류
Rotate
특정 축으로 회전
일반적으로는 y축 기준으로 회전함

Vector로 임의로 각도를 만들어서 transform.rotation에 넣으려고 하면 타입 에러가 남
따라서 오일러 → 쿼터니언 변환해줘야 함
// 원하는 각도로 회전 바꾸는 코드
transform.rotation = Quaternion.Euler(newRotation);
반대로 쿼터니언 → 오일러 변환도 가능
// 사용자가 보려면 쿼터니언 -> 오일러 변환 필요
Debug.Log(transform.rotation.eulerAngles);
최종 코드
void Start()
{
Vector3 newRotation = new Vector3(0, rot, 0); // y축으로 30도
// 원하는 각도로 회전 바꾸는 코드
transform.rotation = Quaternion.Euler(newRotation);
// 사용자가 보려면 쿼터니언 -> 오일러 변환 필요
Debug.Log(transform.rotation.eulerAngles);
// 자기 자신의 위치를 0, 0, 0으로 설정
transform.position = Vector3.zero;
// 자기 자신의 회전을 0, 0, 0으로 설정
transform.rotation = Quaternion.identity; // 월드 기준으로 정면을 바라보는 원점 회전
// 자기 자신의 크기를 1, 1, 1로 설정
transform.localScale = Vector3.one;
}
계속 회전 시키기
public float rotSpeed = 30f;
void Update()
{
// 자기 자신이 Y축으로 회전하는 코드
transform.Rotate(rotSpeed * Time.deltaTime * Vector3.up);
}
transform : 자기 자신의
Rotate : 회전
Vector3.up : y축으로
rotSpeed : 속도는 30f로
Time.deltaTime : deltaTime으로
실행 결과

에러 해결
코드 짜는데 이런 에러가 남

'Vector3' is an ambiguous reference between 'UnityEngine.Vector3' and 'System.Numerics.Vector3'
읽어보니 System.Numerics에도 Vector3가 있어서 에러가 남
나는 유니티의 벡터를 사용할 것이기 때문에 using 문에 System.Numerics를 제거해줌
아마 뭐 코드 수정하다가 자동 using 된 듯
using System.Collections;
using System.Collections.Generic;
using System.Numerics; <-
using UnityEngine;
에러 해결!
빈 게임 오브젝트 표시하기
잘 안보이기 때문에 보통 아래와 같은 방법을 사용함
Inspector View에서 정육면체 눌러서 라벨 달 수 있음


RotateAround
특정 대상 기준으로 회전하는 코드

// 특정 대상 기준으로 회전하는 코드
transform.RotateAround(target.position, Vector3.up, rotSpeed * Time.deltaTime);
// 회전할 물체 특정 대상 회전축
유니티에서 target 할당


자기 자신 회전 + 타겟 대상 회전

LookAt
특정 방향을 바라보는 기능
Vector3 dir = new Vector3(h, 0, v).normalized; // 입력한 값으로 Vector3 선언 및 할당
transform.position += dir * moveSpeed * Time.deltaTime; // 입력한 값으로 이동 기능
// 캐릭터가 이동하려는 방향을 바라보게 하는 코드
Vector3 targetPos = transform.position + dir; // 목표 위치
// 현재 위치(자기 자신의 위치) + 입력 값에 의한 방향
transform.LookAt(targetPos); // 목표 위치를 바라보는 코드

키를 누를 때만 회전하도록 조건을 걸어줘야 버그 방지 가능
손을 뗐을 때 캐릭터가 회전하면 안됨
if (h != 0 || v != 0) // h, v로 입력 들어올 때 = wasd중 하나라도 눌렀을 때
{
// 캐릭터가 이동하려는 방향을 바라보게 하는 코드
Vector3 targetPos = transform.position + dir; // 목표 위치
// 현재 위치(자기 자신의 위치) + 입력 값에 의한 방향
transform.LookAt(targetPos); // 목표 위치를 바라보는 코드
}
3차원에서 태양계 회전
유니티에서 에셋 다운
https://assetstore.unity.com/packages/3d/environments/planets-of-the-solar-system-3d-90219

근데 깨짐(Magenta : Hi)

Built-in(지금 프로젝트), URP(다운 받은 에셋) 충돌 이슈
Built-in은 구버전, URP는 신버전

깨진 항목 잡아서 쉐이더 변경
현재 Hidden = 설정 안되어 있다고 보면 됨


그러면 나오긴 함

받은 Scene 열기

태양은 URP로 안해서 이상하게 나옴

임시 수정

렌더링 모드, Albedo 수정

Emission 체크해서 방출 색 변경

결과물

플레이 하면서 수정했던 값들을 남기고 싶으면 속성 복사해서 붙여넣기 하면 됨

Material은 그냥 꺼도 남아있음
자전, 공전 스크립트
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RotationTarget : MonoBehaviour
{
public Transform target;
public float rotSpeed, rotAroundSpeed = 0f;
void Start()
{
}
void Update()
{
// 자전
// 자기 자신이 회전하는 기능 -> Rotate
transform.Rotate(Vector3.up, rotSpeed * Time.deltaTime);
// 공전
// 다른 대상을 기준으로 회전하는 기능 -> RotateAround
transform.RotateAround(target.position, Vector3.up * rotAroundSpeed * Time.deltaTime);
}
}
Skybox 바꾸기

드래그앤드랍으로 적용 가능

메인 카메라에 원근법 적용

크기, 위치 조정 후 스크립트 넣기

아래처럼 랜덤으로 회전 스피드 값 넣어줄 수 있음

스피드 천천히 가도록 조절한 결과물

근데 달이 이상하게 돌고 있음

해결하려면 계층 구조를 잡아줘야 함
→ 달이 지구와 같은 계층에서 움직이는 지구를 따라가는 게 아니라, 지구의 자식이 되어 그 안에서 지구를 기준으로 돌도록 하면 해결됨


카메라가 object 따라가는 단축키 : shift + f
콜라이더 Collider
충돌 또는 감지하는 영역
충돌이나 감지를 선택적으로 하는 Component
충돌과 감지를 위해서는 콜라이더 + 리자드바디가 필요함
ex. 상호작용 - 이벤트 발생
캐릭터 이동 키, 공격 키 → 입력 이벤트 발생
캐릭터가 이동하다 벽에 부딪힘 → 충돌 이벤트 발생

콜라이더 종류

Mesh Collider
Mesh : 형태, 모양 데이터
Mesh 기반의 콜라이더


이런 느낌으로 면마다 콜라이더가 만들어짐
= 면마다 물리적으로 충돌, 감지하는 기능이 있음
⇒ 하이폴리로 너무 세세하게 되어있으면 게임 터짐 = 안돌아감
ex. 화살 맞을 때 화살 꽂히는 모습 등
특별한 경우가 아니면 잘 안씀
보통 단순화해서 사용함

Collider 영역 수정


Edit Collider 버튼 누르면 수정 가능한 점이 생김

점을 drag&drop으로 움직여서 직접 변경 가능

숫자값으로도 변경 가능

Is Trigger
충돌, 감지 선택

자동차의 충돌 Collision 이벤트


총알의 감지 Trigger 이벤트


is Trigger에 따라 충돌, 감지가 바뀜
isTrigger = false일 경우
충돌 이벤트 발생 → 적이 총알과 충돌하여 넘어짐

isTrigger = true일 경우
감지 이벤트만 발생 → 총알을 감지하여 체력 감소 등등 적용 가능

Rigidbody
물리 연산을 하는 Component
Collider는 영역이라면 Rigidbody는 계산
컴포넌트 추가


중력 적용됨

파란 공 isTrigger 체크하니 뚫고 지나감(감지함)

Plain은 기본적으로 Mesh Collider가 설정되어 있지만 그냥 Box Collider를 사용하기도 함
Event 3단계
Event는 기본적으로 3단계임
시작 → 실행중 → 종료
Start() → Update() → OnDestroy()
GetKeyDown → GetKey → GetKeyUp
이는 충돌 이벤트, 감지 이벤트도 마찬가지
충돌 이벤트 Collision Event
onCollisionEnter → OnCollisionStay → OnCollisionExit
감지 이벤트 Trigger Event
OnTriggerEnter → OnTriggerStay → OnTriggerExit
Collider Event 스크립트 작성
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ColliderEvent : MonoBehaviour
{
public void OnCollisionEnter(Collision collision)
{
Debug.Log("충돌 Enter");
}
public void OnCollisionStay(Collision collision)
{
Debug.Log("충돌 Stay");
}
public void OnCollisionExit(Collision collision)
{
Debug.Log("충돌 Exit");
}
}
예상 시나리오
해당 스크립트를 땅(Plain)에 적용하면 공이 땅에 충돌하는 순간 땅에서 감지할 예정


Stay는 1-3초 있다가 무시함(추가로 로그가 쌓이지 않음)
공을 위로 보내니 Exit가 뜸
Trigger Event 스크립트 작성
public void OnTriggerEnter(Collider other)
{
Debug.Log("감지 Enter");
}
public void OnTriggerStay(Collider other)
{
Debug.Log("감지 Stay");
}
public void OnTriggerExit(Collider other)
{
Debug.Log("감지 Exit");
}

문 예제 만들어보기
문은 회전축이 중요함
빈게임 오브젝트 만들어서 v(vertex snap)으로 회전축 위치 이동

계층 만들어주기

ctrl+6으로 Animation 키기

녹화 버튼 누르면 AddKey 가능

완성

번외 : 회전문

ㅋㅋ이렇게 하면 360도를 넘어가기 때문에 Quaternion이 됨
추가
장갑 만드는 법
손(부모) 기준으로 장갑(자식)이 있기 때문에 Local Position 이용
-> 먼저 만든 왼쪽 장갑의 Transform -> Copy -> Component로 복사하여 복사한 오른쪽 장갑에 붙여넣기하면 됨


간단한 3인칭 이동 만들기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TPSMovement : MonoBehaviour
{
float h;
float v;
float moveSpeed = 10f;
public float rotSpeed = 50f;
void Update()
{
h = Input.GetAxis("Horizontal");
v = Input.GetAxis("Vertical");
Move();
Turn();
}
private void Move() // W, S 이동
{
transform.Translate(Vector3.forward * v * moveSpeed * Time.deltaTime);
}
private void Turn() // A, D 회전
{
transform.Rotate(Vector3.up, h * rotSpeed * Time.deltaTime);
}
}

사담
오늘은 새로 접하는 개념이 많이 나와서 재밌었다!
이동이 가장 기본적인 기능이라 할만하지 않을까? 생각했는데 역시 세상에 쉬운 일 없다고
다양한 방법이 있고 자신이 추구하는 기획에 맞춰 구현해야 한다고 강사님이 설명해주셨다. (+딥하게 들어가면 여러개념이 있다~)
그래도 차근차근하니까 되긴 되네...
재밌다!