Vector3.Lerp( (Vector3)현재 위치, (Vector3)타겟 위치, 속도 );
: 타겟 위치에 가까워질수록 속도가 느려짐
MoveTowards ( (Vector3)현재 위치, (Vector3)타겟 위치, 속도 );
: 일정한 속도로 움직임.
플레이어가 오브젝트의 아래를 지나갈 경우 떨어지고, 플레이어가 오브젝트의 범위에서 벗어나면 제자리로 돌아가는 것을 구현하였다.
매우 간단할 줄 알았던 기능이었는데 은근 시간이 많이 걸렸다.
Vector3값은 float이라 그런지 == 를 사용할 수 없었다. Unity라 혹시 가능할까 했는데 내가 방법을 못찾은 건지 모르겠지만
소수점 아래까지 모두 같을 순 없었다.
구글링을 한 결과 맨 위에 써 놓은 것처럼 특정 좌표로 이동시켜주는 함수를 찾을 수 있었다.
처음에는 Update()에 두었지만 매 프레임마다 Vector3.Lerp()가 실행되는 것이 문제로 보였고 코루틴을 사용하였다.
OnTriggerExit2D 이벤트 함수가 실행될 때, 즉 플레이어가 가시상자 오브젝트의 범위를 벗어났을 때
제 자리로 돌아갈 수 있는 코드를 코루틴으로 하였고 while문을 통해 제 자리로 돌아갈 수 있는 충분한 시간을 부여하였다.
문제는 만약 각기 높이가 다른 가시상자라면 도달하는 시간이 모두 다르기 때문에 시간을 부여하는 것보다 제 자리로 찾아가면 코루틴을
종료시키는 것이 더 좋은 방법이다. 더 방법을 찾아봐야 겠다.
* 주의 ) 제 자리로 돌아가는 코루틴이 종료하기 전에 플레이어가 다시 가시상자 오브젝트의 범위에 들어올 수 있으므로
Trigger 이벤트 함수들 시작할 때 AllStopCoroutine()을 해주어야 한다.
***************************************************************************************************************************************************
float.Epsilon과 Vector3.sqrMagnitude를 통해 본래 있던 위치와 거의 근접한 경우 while문을 벗어나게 할 수 있게 되었다.
void OnTriggerEnter2D(Collider2D col) { if(col.transform.tag == playerTag) { rb2D.gravityScale = 1f; rb2D.AddForce(Vector3.down * 3f * Time.deltaTime, ForceMode2D.Impulse); } } void OnCollisionEnter2D(Collision2D col) { if(col.transform.tag == "GroundUnit") { StartCoroutine(backOrigin()); } } IEnumerator backOrigin() { rb2D.gravityScale = 1f; float sqrRemaingDistance = (transform.position - originPos).sqrMagnitude; while(sqrRemaingDistance > float.Epsilon + 0.1f) { Vector3 newPosition = Vector3.MoveTowards(rb2D.position, originPos, rBackSpeed * Time.deltaTime); rb2D.MovePosition(newPosition); sqrRemaingDistance = (transform.position - originPos).sqrMagnitude; yield return null; } rb2D.gravityScale = 0f; rb2D.velocity = Vector3.zero; }
코루틴의 while문 안을 보면 남아 있는 거리가 float.Epsilon(거의 0에 근접한 수)보다 큰 경우 while문이 지속된다.
부동 소수점으로 오차가 존재하기 때문에, == 가 불가능하고 따라서 오차가 거의 없는 경우, 즉 본래 있던 위치와 현재 위치의 차이가 거의 0에
수렴할 때까지 본래 자리로 돌아가도록 하였다.
0.1f를 더해준 까닭은 0.1f를 붙여주지 않으면 while문 조건이 만족되지 않기 때문이었다. Debug.Log를 찍으면 while문을 나오는게 맞는 것 같은데,
나오질 않아 0.1f를 더해주니 그제서야 while문을 나온다. 이것이 옳은 방법인진 모르겠으나 위치를 계속 확인해보니
0.01~0.10 정도의 오차로 거의 동일하였다.
cf) Rigidbody2D.MovePosition(Vector3) 은 Vector3의 위치로 이동시켜주는 함수이다.
Vector3.sqrManitude는 Vector3의 제곱 값이다.
'Unity 공부시작 > Unity2D 게임 및 기능구현' 카테고리의 다른 글
유니티2D :: 랜덤 스킬 배정받기 < Action 이용 > (0) | 2019.01.22 |
---|---|
유니티2D :: 애니메이션의 전환이 느린 경우 (0) | 2019.01.18 |
유니티2D :: 대화 이벤트 구현 연습 (2) | 2019.01.18 |
유니티2D :: 캐릭터 이동, 점프 및 애니메이션 구현 (0) | 2019.01.17 |
Unity2D 기능 구현 :: 날아오는 화살 막아내기 (0) | 2019.01.07 |