본문 바로가기

Programming/유니티

유니티(Unity) Rigidbody2d의 Addforce와 밀림방지

ㄴ유니티(Unity) 2d 물리 게임 이동충돌
ㄴ유니티(Unity) META-INF/kotlinx_coroutines_core.version
ㄴUndefined symbol : 유니티 Ios 빌드, Pod 설치 및 제거하기
ㄴ유니티(Unity) - 아이폰, 안드로이드 권한 셋팅 화면으로 이동하기
ㄴ유니티 (Unity) - Button의 OnClick Listener 사용법
ㄴ유니티(Unity) 프로젝트 점프게임 만들기 : [7] 플랫폼 생성

Addforce

자연스러운 물리 연출을 위해서 사용되는 함수입니다. 주로 발사체의 연출을 위해 사용하지만 오브젝트의 이동에도 사용이 가능합니다. 

----

----

이동로직

var destPosition;
var dir = destPosition - currentPosition;
dir = dir.normalized;
private void FixedUpdate()
{
    rigi2D.AddForce(dir * moveSpeed);
}

문제점

Addforce를 이용하여 오브젝트를 특정 위치로 이동시킬 때 정확한 위치에 정지하지 않을 수 있습니다. 우선 특정위치 근처에 도달하였는지 확인하는 방법이 필요해 보입니다.

위치확인 방법

Addforce를 이용하여 특정 위치에 오브젝트가 도달하였는지 확인하기 위해서 몇 가지 방법을 사용합니다. 
1. Vector2d.Distance 함수를 이용하여 현재 위치와 목적 위치의 거리를 확인해서 일정 거리 이하가 되면 목적지에 도달한 것으로 확인한다. 
2. 이동하는 방향인 normal 값을 비교하여 방향이 바뀌면 목적지에 도달한 것으로 판단한다.

1번의 경우는 디바이스의 퍼포먼스에 따라서 일정거리값이 도출되지 않을 수 있기 때문에 2번을 사용하는 예를 알아보겠습니다.

normal 값으로 목적지 도달 확인

bool CheckNormalChange(Vector2 _ori, Vector2 _cur)
{
    if (_ori.x < 0 && _cur.x < 0 && _ori.y < 0 && _cur.y < 0){ return false; }
    if (_ori.x < 0 && _cur.x < 0 && _ori.y > 0 && _cur.y > 0) { return false; }
    if (_ori.x > 0 && _cur.x > 0 && _ori.y > 0 && _cur.y > 0) { return false; }
    if (_ori.x > 0 && _cur.x > 0 && _ori.y < 0 && _cur.y < 0) { return false; }

    return true;
}

리턴값이 true가 된다면 목적지를 지나쳐 반대방향으로 이동하게 되는 것이기 때문에 목적지에 도달했다고 볼 수 있습니다.

원하는 위치에 정지시키기

Addforce로 오브젝트를 이동시키는 방법을 알았고 목적위치 근처에 도달했는지 판단하는 방법을 알았습니다. 이제 목적위치에 오브젝트를 멈추는 작업이 필요해 보입니다. velocity = Vector2.zero로 만들면 Addforce로 밀리던 오브젝트를 정지시킬 수 있습니다.

var dir = Vector2.Zero;
var moving = false;
public void SetDestPosition (Vector2 _destPosition)
{
	var destPosition;
	dir = destPosition - currentPosition;
	dir = dir.normalized;
	moving = true;
}

private void FixedUpdate()
{
	if (moving == false) return;

	var _moveDir = destPosition - currentPosition;
	_moveDir = _moveDir.normalized;

	if (CheckNormalChange(dir, _moveDir) == true)
	{
		rigi2D.velocity = Vector2.zero;
        rigi2D.MovePosition(destPosition);
        moveing = false;
	} else {
		rigi2D.AddForce(_moveDir * moveSpeed);
	}
}

Addforce로 이동 중인 오브젝트에 velocity 값을 zero 값으로 만들고 MovePosition 함수를 이용하여 목적 위치에 오브젝트를 위치시킵니다. 이때 계속해서 MovePosition 함수가 실행되면 외력이 작용했을 때 적용되지 않기 때문에 moving이라는 플래그를 두어 리턴 시켜야 합니다.