새로운 팀프로젝트가 시작되는 날이다.
우리 팀은 Alt F4라는 게임을 모작한다.
일단 방해물이 주된 컨텐츠이기때문에 방해물들을 먼저 제작한 후 다른 구현을 하기로 했다.
나는 진자 운동을 하는 공과 튀어오르는 생선 구현을 맡았다.
진자 운동 공 구현
빈 오브젝트 자식으로 막대기, 막대기의 자식으로 구를 넣은 후
빈 오브젝트에 rotation.z를 변경하는 스크립트를 넣어줬다.
진자 운동 구현
첫 번째로 시도했던 방법
https://srdeveloper.tistory.com/41
이 블로그의 코드를 참고했다.
moveTime += Time.deltaTime * speed;
transform.rotation = Quaternion.Lerp(
Quaternion.Euler(transform.forward * angle), // Vector3.forward
Quaternion.Euler(-transform.forward * angle), // Vector3.back
(Mathf.Sin(moveTime) + 1) * 0.5f);
Quaternion.Lerp를 사용해 transform.rotation.z의 값을
(0,0,1) * angle부터 (0,0,-1) * angle까지 왔다갔다 하면서 부드럽게 증감소 시키는 코드이다.
Mathf.Sin(moveTime) + 1 * 0.5f는
Quaternion.Lerp()의 t(마지막인자)는 0 ~ 1 값을 넣어줘야 하는데 Mathf.Sin()의 값은 -1 ~ 1 이기때문에 보정을 위한 코드다.
단순히 Mathf.Sin(moveTime)을 사용하면 진자운동 시작 위치에 잠깐 멈춰있는다.
이렇게 했을 경우 잘 돌아가지만, 오브젝트의 방향을 바꿨을 때도 같은 방향으로 진자운동을 한다.
다시 말해서 오브젝트의 transform.rotation.x 값과 transform.rotation.y값은 항상 0으로 고정되어 다른 방향의 진자 공 오브젝트가 여러개 있을 때도 다 같은 방향으로 움직이는 상황이 벌어진다.
이를 해결하기 위해 아래 방법을 사용했다.
두 번째로 시도했던 방법
moveTime += Time.deltaTime * speed;
Quaternion currentRotation = transform.rotation;
float targetZRotation = Mathf.Sin(moveTime) * angle;
Quaternion targetRotation = Quaternion.Euler(currentRotation.eulerAngles.x, currentRotation.eulerAngles.y, targetZRotation);
transform.rotation = Quaternion.Lerp(currentRotation, targetRotation, 0.5f);
원래의 Rotation값을 저장해 놓고 z축의 값만 바뀌도록 구현했다.
Quaternion.Lerp의 마지막인자(t)의 값(0.5f)은 선형 보간의 가중치(weight)또는 보간 정도이고
0은 시작 값(currentRotation), 1은 목표 값(targetRotation)이고 0.5이면 그 중간의 값이다.
따라서 현재 회전값과 목표 회전값의 중간 지점으로 게임 오브젝트의 회전을 어느 한 쪽에 치우치지 않고 부드럽게 변경한다.
+
float t = Mathf.PingPong(Time.deltaTime * speed, 1.0f);
구현하다가 발견한 PingPong 함수. 정말 핑퐁하는 것 처럼 움직인다.
튀어오르는 생선 구현
튀어올라서 플레이어를 공격하는 생선을 구현할 것이다.
생선은 ObjectPool를 이용할 예정이다.
ObjectPool을 이용하게 되면 SetActive(true)가 되었을 때 튀어오르게 하기 위해
OnEnable()을 이용했다.
private void OnEnable()
{
_rigidbody = GetComponent<Rigidbody>();
float randomX = Random.Range(-1.0f, 1.0f);
float randomZ = Random.Range(-1.0f, 1.0f);
_rigidbody.AddForce(randomX * _jumpForce, 1.0f * _jumpForce, randomZ * _jumpForce);
StartCoroutine(Flap());
}
또 팔닥거리는 움직임을 주기 위해 Coroutine을 이용했다.
0.6초에 한 번 AddForce와 AddTorque를 이용해 팔닥거리는 움직임을 주려했다.
IEnumerator Flap()
{
yield return new WaitForSeconds(3f);
while (true)
{
_rigidbody.AddForce(Vector3.up * _flapForce);
_rigidbody.AddTorque(Vector3.forward * Random.Range(-1.0f, 1.0f) * 100f);
yield return new WaitForSeconds(_flapTime);
}
}
Coroutine은 SetActive(false)를 해도 계속 돈다고 한다.
따라서 OnDisable()이 되었을 때 Coroutine을 종료해 주었다.
private void OnDisable()
{
StopCoroutine(Flap());
}
'내일배움캠프(Unity)' 카테고리의 다른 글
숙련 주차 팀프로젝트 3 - 방해물 넉백, ragdoll (0) | 2024.01.04 |
---|---|
숙련 주차 팀프로젝트 2 - Object Pool, 플레이어 튕겨내기, lagdoll (1) | 2024.01.03 |
TIL (0) | 2023.12.28 |
TIL (0) | 2023.12.27 |
클린 코드 4 (0) | 2023.12.26 |