본문 바로가기
게임 개발/게임 이론+수학

[게임수학 | 유니티] 캐릭터 점프 구현하기

by 불타는홍당무 2017. 3. 22.


캐릭터의 점프 시 속도와 시간의 상관관계


캐릭터가 점프하면 빠른 속도로 높이가 상승하지만 시간이 지나면서 중력가속도에 의해 점점 그 속도가 감소한다. 결국 음수값이 되고 그 값은 캐릭터가 바닥에 착지할 때까지 점점 더 음수의 값으로 증가한다. 이 물리법칙을 1차함수로 정리하면 다음과 같다.


y= -ax + b (a: 중력가속도 b: 초기 점프속도. x: 점프시간, y: 점프속도)



우리가 궁극적으로 알아야 할 것은 점프하는 동안의 캐릭터의 높이이다. 그렇다면 높이는 어떻게 구할 수 있을까? 높이는 위의 1차함수에서 빗금으로 표시된 영역의 시간당 누적값으로 표시된다. 왜냐하면 속도x시간=거리이고 여기서 높이는 거리와 같기 때문이다.


1차함수를 적분하여 2차함수로 만들면 y = (-a/2)*x*x + b*x이 되고 여기서 y값이 곧 캐릭터의 높이가 된다.



유니티로 캐릭터의 점프 구현하기



게임오브젝트 생성 후 아래 스크립트를 추가하면 된다. 소스 설명은 주석을 참고한다. 

중력가속도(_gravity)나 점프력(_jumpPower)을 조절하여 원하는 느낌의 점프 모션을 구현할 수 있도록 한다.


using UnityEngine;

public class JumpCtrl : MonoBehaviour
{
    private Transform _transform;
    private bool _isJumping;
    private float _posY;        //오브젝트의 초기 높이
    private float _gravity;     //중력가속도
    private float _jumpPower;   //점프력
    private float _jumpTime;    //점프 이후 경과시간

    void Start()
    {
        _transform = transform;
        _isJumping = false;
        _posY = transform.position.y;
        _gravity = 9.8f;
        _jumpPower = 15.0f;
        _jumpTime = 0.0f;
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space) && !_isJumping)
        {
            _isJumping = true;
            _posY = _transform.position.y;
        }

        if (_isJumping)
        {
            Jump();
        }
    }

    void Jump()
    {
        //y=-a*x+b에서 (a: 중력가속도, b: 초기 점프속도)
        //적분하여 y = (-a/2)*x*x + (b*x) 공식을 얻는다.(x: 점프시간, y: 오브젝트의 높이)
        //변화된 높이 height를 기존 높이 _posY에 더한다.
        float height = (_jumpTime * _jumpTime * (-_gravity) / 2) + (_jumpTime * _jumpPower);
        _transform.position = new Vector3(_transform.position.x, _posY + height, _transform.position.z);
        //점프시간을 증가시킨다.
        _jumpTime += Time.deltaTime;

        //처음의 높이 보다 더 내려 갔을때 => 점프전 상태로 복귀한다.
        if (height < 0.0f)
        {
            _isJumping = false;
            _jumpTime = 0.0f;
            _transform.position = new Vector3(_transform.position.x, _posY, _transform.position.z);
        }
    }
}