벡터의 정규화
w,a,s,d 입력이 가능하게 해놓은 상태에서 대각선으로 이동할 경우, 이동 거리가 늘어나게 되는 문제가 있음.
이러한 문제를 해결하기 위해 벡터의 정규화 사용.
Normalize(): 길이가 1인 벡터를 만들어줌.
direction.Normalize();
rotDirection.Normalize();
회전 구현
① 먼저 rotDirection을 선언.
② a, d를 누를 때 회전할 수 있도록 rotDirection에 값 넣기
if (Input.GetKey(KeyCode.A))
{
rotDirection += -transform.right;
}
if (Input.GetKey(KeyCode.D))
{
rotDirection += transform.right;
}
③ rotDirection 값이 있을 경우, 바라볼 방향을 현재 내 방향으로 회전하는 값 로컬 설정.
④ 회전 값 transform에 넣기.
if (rotDirection.sqrMagnitude > 0.001f)
{
// newRot 계산
// transform.rotation은 현재 내가 보고 있는 방향
// Quaternion.LookRotation(direction) // 내가 바라볼 방향이다.
// Quaternion의 RotateToward는 current -> new 로 회전할 값을 정하는데
// 그 양이 Time.fixedDeltaTime * rotSpeed 값이다.
Quaternion newRot = Quaternion.RotateTowards(transform.rotation,
Quaternion.LookRotation(rotDirection), rotSpeed * Time.fixedDeltaTime);
// newRot으로 회전
charObj.transform.rotation = newRot;
}
Quaternion
: 회전을 나타내는 구조체.
아직 물리 수학을 배우지 않아 자세한 내용은 가르쳐주지 않으심.
● LookRotation : Vector를 Quaternion으로 변경해주는 함수. 방향에 대한 벡터.
● RotateTowards : from에서 to로 maxDegreesDelta만큼 회전
결과
점프 구현
Rigidbody의 AddFoce 함수를 이용하여,
Space를 누를 시 위로 순간적인 힘이 가하겠끔 함.
if (Input.GetKeyDown(KeyCode.Space))
{
GetComponent<Rigidbody>().AddForce(Vector3.up * jumpPower, ForceMode.Impulse);
}
● Rigidbody.AddForce: 오브젝트에 힘을 가하는 함수
● ForceMode.Impulse: 순간적으로 속도를 붙여줌. 정지 상태에서 이동을 시작하려 할 때 적합.
다중 점프 방지
위의 코드로 작성할 경우, 점프를 끝내기 전에 점프를 하는 문제가 발생함.
이를 방지하기 위해,
플레이어가 땅에 닿아있을 때만 점프를 할 수 있게 작성함.
① bool 타입 isGrounded을 false로 정의
bool isGrounded = false;
② 점프의 조건에 isGrounded 추가
③ 조건문 안에서 isGrounded에 false 값 넣기
if (Input.GetKeyDown(KeyCode.Space) && isGrounded)
{
GetComponent<Rigidbody>().AddForce(Vector3.up * jumpPower, ForceMode.Impulse);
isGrounded = false ; // 점프를 하면 땅에서 떨어짐
}
④ Inspector 창에서 Tag 클릭 후 Add Tag... 클릭
⑤ 플러스 버튼(+) 을 클릭하여 "Ground" 태그 추가
⑥ 땅 오브젝트들을 선택한 후 Inspector 창에서 위의 Tag 버튼을 클릭하여 태그를 "Ground"로 변경
⑦ CompareTag를 이용하여 충돌체의 태그가 "Ground"인지 확인하는 조건문 생성
⑧ 조건문 안에서 isGrounded에 true 값 넣기
void OnCollisionEnter(Collision collision)
{
// 땅 오브젝트가 플레이어의 콜라이더에 닿았을 경우
if (collision.gameObject.CompareTag("Ground"))
{
// 땅에 닿은 것으로 처리
isGrounded = true;
}
}
결과
FixedUpdate와 Update의 차이
FixedUpdate
- Fixed Timestep 의 값에 한 번씩 틱이 돎
- 조건 상관 없이 무조건 실행
- Input 이 이 값 이전에 눌리면 생략되어 반응이 없을 수 있음
Update
- 1 프레임 당 1틱.
- Input 받은 후 Update가 실행되기 때문에 생략되지 않음.
=> 키 입력은 Update에서 받는 게 좋다!
private void Update()
{
// 매 업데이트 마다 direction, rotDirection을 초기화 해줘서
// 그 다음 인풋 적용되도록 한다.
direction = Vector3.zero ;
rotDirection = Vector3.zero ;
// direction 들에 값 넣어주기
if (Input.GetKey(KeyCode.W))
{
direction += charObj.transform.forward;
}
if (Input.GetKey(KeyCode.A))
{
rotDirection += -charObj.transform.right;
}
if (Input.GetKey(KeyCode.S))
{
direction += -charObj.transform.forward;
}
if (Input.GetKey(KeyCode.D))
{
rotDirection += charObj.transform.right;
}
if (Input.GetKeyDown(KeyCode.Space) && isGrounded)
{
GetComponent<Rigidbody>().AddForce(Vector3.up * jumpPower, ForceMode.Impulse);
isGrounded = false ;
}
// 대각선 방향은 값은 루트가 나오기 때문에 정규화
direction.Normalize();
rotDirection.Normalize();
}
회전과 점프는 게임에 거의 필수적인 요소.
손에 익숙해지기 위해 반복학습을 해야겠다 느낌.
'부트캠프' 카테고리의 다른 글
[멋쟁이사자처럼 유니티 TIL] 대리자(delegate)와 이벤트 실습, 공격 모션 구현 (+ (Ctrl + H), 리타겟팅) (1) | 2024.06.12 |
---|---|
[멋쟁이사자처럼 유니티 TIL] node.js을 통한 비동기 서버 구축 구현 (+ 서버 구축 관련 용어 정리, 벡터와 라디안으로 회전 구현, 비동기 프로그래밍) (0) | 2024.06.08 |
[멋쟁이사자처럼 유니티 TIL] 에셋을 통한 애니메이션 구현과 비동기 프로그래밍(코루틴, async, await) (1) | 2024.06.05 |
[멋쟁이사자처럼 유니티 TIL] 에셋을 이용한 보석 먹기 게임 구현 ( + 파일 경로, 링큐 등) (1) | 2024.06.04 |
[c#] 별 찍기 + 피라미드, 역피라미드, 왼쪽/오른쪽 화살표 (0) | 2024.05.29 |