유니티에서 물리적인 힘을 적용하여 캐릭터 점프를 구현한다.
물리적인 힘은 Rigidbody를 통해 구현된다.
물리적인 충돌 및 게임 오브젝트 간의 충돌 감지는 Collider를 통해 구현된다.
1. 준비
대상 오브젝트에 Rigidbody와 Collider 컴포넌트를 추가한다. CharaterControl 클래스를 만들고 점프를 구현할 대상 오브젝트에 등록한다.
Plane을 추가하고 Scale *10으로 하여, 지면을 구현한다. 트랜스폼의 Scale 값은 (10, 0, 10)이다. 지면을 생성하지 않으면, 게임 오브젝트가 추락하게 된다. Plane은 대상 오브젝트보다 아래(Y축)에 위치하도록 한다. 트랜스폼의 Position 값은 (0, -1.0, 0)이다. 물리 충돌을 구현하기 위해서는 Plane도 Collider 컴포넌트가 추가된 상태여야 한다.
2. 점프 구현
Space 키를 누르면 대상에 힘을 가하도록 구현한다.
아래의 두 개의 코드는 동일한 역할을 한다. GetButtonDown()은 매개변수를 string 타입, GetKeyDown()은 매개변수를 Keycode 타입을 사용한다.
Edit → Project Settings → InputManager 에서 확인 및 수정할 수 있다.
1. Input.GetButtonDown("Jump")
2. Input.GetKeyDown(KeyCode.Space)
시작하게 되면, 게임 오브젝트에 추가한 Rigidbody 컴포넌트의 인스턴스를 얻는다.
에디터 뷰에서 수정이 가능하도록 실수형 변수 force를 public으로 생성한다.
사용자로부터 키 입력을 받으면, 대상 오브젝트에 Y축 방향으로 힘을 가하도록 구현한다.
Vector3(0, 1.0f, 0) * 100만큼 힘을 가한다.
public class CharacterControl : MonoBehaviour
{
// 물리
Rigidbody rigidbody;
public float force = 100.0f;
void Start()
{
// 힘을 가하기 위해 게임 오브젝트에 추가된 Rigidbody 컴포넌트의 인스턴스를 얻는다.
rigidbody = GetComponent<Rigidbody>();
}
void FixedUpdate()
{
if (Input.GetButtonDown("Jump"))
{
rigidbody.AddForce(new Vector3(0, 1.0f, 0) * force);
}
}
}
3. AddForce()
오브젝트에 힘을 가할 때에는 Rigidbody의 AddForce()를 사용한다.
Rigidbody.Addforce(force)
Rigidbody.Addforce(force, ForceMode)
Addforce()를 이용할 때 몇 가지 포스 모드를 사용해 대상 오브젝트에 물리적인 힘을 가할 수 있다.
AddForce의 기본 모드는 ForceMode.Force이다. Addforce()의 첫 번째 매개변수는 Force 값이다. 두 번째 매개변수로, 포스 모드를 설정할 수 있다. 두 번째 매개변수를 입력하지 않으면, ForceMode.Force이다.
FroceMode.Force는 현실세계의 물리 법칙을 적용할때에 주로 사용된다. ForceMode는 enum 클래스이며 Forcemode.Type을 대입한다.
ForceMode는 다음과 같다.
- Force : 질량을 사용, 연속적인 힘을 가하는 경우
- Acceleration : 질량을 무시, 가속력을 가하는 경우
- Impulse : 질량을 사용, 짧은 순간 힘을 가하는 경우
- VelocityChange : 질량을 무시, 속도 변화를 짧은 순간에 적용하는 경우
순간적인 힘을 가하여, 게임 오브젝트를 +Y축으로 이동시킨다. 매개변수로 ForceMode.Impulse를 입력한다.
public class CharacterControl : MonoBehaviour
{
// 물리
Rigidbody rigidbody;
public float force = 10.0f;
void Start()
{
// 힘을 가하기 위해 게임 오브젝트에 추가된 Rigidbody 컴포넌트의 인스턴스를 얻는다.
rigidbody = GetComponent<Rigidbody>();
}
void FixedUpdate()
{
rigidbody.velocity = new Vector3(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"), 0)
* moveSpeed * Time.fixedDeltaTime;
if(Input.GetKeyDown(KeyCode.Space))
{
rigidbody.AddForce(Vector3.Up * force, ForceMode.Impulse);
}
}
}
각 모드는 계산 공식이 다르다. Force와 Impulse를 예로 들어 점프를 구현하면, 질량 1인 오브젝트에 Impulse는 10의 힘을 가하면, 대상 오브젝트는 튀어 오른다. Force는 더 많은 힘을 가해야 대상 오브젝트를 위로 이동시킬 수 있다. 실제 이러한 차이는 대상 오브젝트에 물리를 가하는 계산 공식이 다르기 때문이다. 실제 현실과 같은 게임 월드를 구현하거나, 가상의 세계를 프로젝트에 맞게 구현하기도 한다. 각각의 프로젝트는 힘을 가하는 방식이 다를 수밖에 없다.
각 모드의 계산 공식은,
- Force : mass * distance / time^2
- Acceleration : distance / time ^2
- Impulse : mass* distance / time^2
- VelocityChange : distance / time
Forcemode 사용은 AddForce()에 포스 모드를 추가하면 된다.
AddForce()의 첫번째 매개변수(Parameter)는 힘의 크기(Vector3)이며, 두 번째 매개변수가 포스 모드이다.
Rigidbody.AddForce(Vector3, ForceMode.Mode )
여기에 추가적으로 다음의 표를 확인하면 도움이 될 것이다.
Impulse와 Force는 가하는 힘의 크기에 Mass를 사용한다. Mass가 커질수록 대상 오브젝트에 가하기 위해, 필요한 힘의 크기가 더 많이 요구된다. Impulse와 VelocityChange는 순간적으로 1 frame에 힘을 가한다. Force와 Acceleration은 1초 동안 지속적으로 가한다. 이러한 차이점은 각 포스 모드에 따라, 다른 결과를 도출한다.
참조
https://docs.unity3d.com/ScriptReference/ForceMode.html
https://answers.unity.com/questions/696068/difference-between-forcemodeforceaccelerationimpul.html
'유니티 > 기초' 카테고리의 다른 글
유니티 게임 오브젝트( Game Object ) (0) | 2020.11.02 |
---|---|
유니티 씬(Scene)과 씬 전환 (Scene Transition) (0) | 2020.11.01 |
유니티 캐릭터 마우스 이동[기초 4] (0) | 2020.09.07 |
유니티 카메라 이동 및 회전 [기초 5] (1) | 2020.05.05 |
유니티 캐릭터 이동 및 회전 [ 기초 3] (1) | 2020.05.04 |