728x90

이글은 인프런 [따라하면서 배우는 고박사의 유니티 기초] 강의를 수강하고 정리한 글이다. 

 

[지금 무료] 따라하면서 배우는 고박사의 유니티 기초 | 고박사 - 인프런

고박사 | 유니티로 게임을 개발하고 싶은 초보자를 대상으로 하며, 유니티 설치부터 2D/3D 게임 개발에 필요한 기초 지식까지 자세하게 설명합니다. (강의에 사용되는 모든 리소스는 영상 상단의

www.inflearn.com


강의를 시작하기에 앞서서 플레이어의 이동, 점프등 구현을 위해 2D 오브젝트를 생성하여 원하는 위치에 배치한다. 

  • 유니티 패키지 파일: 원하는 파일들을 하나로 묶어 다른 프로젝트로 전달할 때 사용
  • 패키지 파일 생성하기 : Project View에서 원하는 파일들을 선택한 후 마우스 오른쪽을 클릭 → Export Package로 저장
  • 패키지 파일 사용하기 : 파일을 적용하고 싶은 프로젝트의 Project View로 패키지 파일을 드래그앤 드롭으로 가져온다.

player 오브젝트는 중력을 받을 수 있도록 rigidbody2d들을 적용시키고 freeze rotation z를 선택하게 되면 이동할 때 z축으로 회전하지 않게 된다. 그리고 충돌 처리를 위해 Capsule Collider 2D를 추가한다.

Rigidbody2D 컴포넌트의 Constraints

  • Freeze Position: 물리에 의한 이동 중지
  • Freeze Rotation: 물리에 의한 회전 중지

 

 

 

플레이어 오브젝트 이동(Rigidbody2D)

플레이어 이동을 구현해보도록 movement2D 스크립트를 작성한다. 

using UnityEngine;

public class Movement2D : MonoBehaviour
{
    [SerializeField]
    private float speed = 5.0f; //이동 속도
    private Rigidbody2D rigid2D;


    private void Awake()
    {
        rigid2D = GetComponent<Rigidbody2D>();
    }


    public void Move(float x)
    {
        //x축 이동은 x*speed로, y축 이동은 기존의 속력 값(현재는 중력)
        rigid2D.velocity = new Vector2(x * speed, rigid2D.velocity.y);
    }
}

velocity 변수를 설정한다. 

 

그리고 PlayerController 스크립트를 작성하여 플레이어 좌우 방향키값을 입력하게 되면 movement2D에 함수의 키값을 적용에 오브젝트가 이동한다.

using UnityEngine;

public class PlayerController : MonoBehaviour
{
    private Movement2D movement2D;

    private void Awake()
    {
        movement2D = GetComponent<Movement2D>();
    }

    private void Update()
    {
        //left or a = -1 / right or d = 1
        float x = Input.GetAxisRaw("Horizontal");
        //좌우 이동 방향 제어
        movement2D.Move(x);
    }
}


플레이어 오브젝트 점프

플레이어 이동을 위한 Move 함수와 마찬가지로 Jump 함수를 추가한다.

Jump함수가 호출되면 y축 +방향으로 속력이 설정된다. 이때 점프의 정도는 jumpforce 변가 결정한다.

Jump함수는 PlayerController안에서 스페이스 바를 눌렀을 때 실행되도록 한다. 

using UnityEngine;

public class Movement2D : MonoBehaviour
{
    [SerializeField]
    private float speed = 5.0f; //이동 속도
    [SerializeField]
    private float jumpForce = 8.0f; //점프 힘(클수록 높게 점프)
    private Rigidbody2D rigid2D;


    private void Awake()
    {
        rigid2D = GetComponent<Rigidbody2D>();
    }


    public void Move(float x)
    {
        //x축 이동은 x*speed로, y축 이동은 기존의 속력 값(현재는 중력)
        rigid2D.velocity = new Vector2(x * speed, rigid2D.velocity.y);
    }
    public void Jump()
    {
        //jumpForce의 크기만큼 윗쪽 방향으로 속력 설정
        rigid2D.velocity = Vector2.up * jumpForce;
    }
}

위에 코드에서는 아무런 제약없이 무한히 점프할 수 있다.

using UnityEngine;

public class PlayerController : MonoBehaviour
{
    private Movement2D movement2D;

    private void Awake()
    {
        movement2D = GetComponent<Movement2D>();
    }

    private void Update()
    {
        //left or a = -1 / right or d = 1
        float x = Input.GetAxisRaw("Horizontal");
        //좌우 이동 방향 제어
        movement2D.Move(x);

        //플레이어 점프(스페이스 키를 누르면 점프)
        if (Input.GetKeyDown(KeyCode.Space))
        {
            movement2D.Jump();
        }
    }
}

 

 

낮은 점프, 높은 점프

 

using UnityEngine;

public class Movement2D : MonoBehaviour
{
    [SerializeField]
    private float speed = 5.0f; //이동 속도
    [SerializeField]
    private float jumpForce = 8.0f; //점프 힘(클수록 높게 점프)
    private Rigidbody2D rigid2D;
    [SerializeField]
    public bool isLongJump = false; // 낮은/높은 점프 체크


    private void Awake()
    {
        rigid2D = GetComponent<Rigidbody2D>();
    }

    private void FixedUpdate()
    {
        //낮은 점프, 높은 점프 구현 위한 중력 계수 조절 Jump Up일 때만 적용)
        //중력 계수가 낮은 if문은 높은 점프가 되고, 중력 계수가 높은 else문은 낮은 점프가 됨.
        if (isLongJump && rigid2D.velocity.y > 0)
        {
            rigid2D.gravityScale = 1.0f;
        }
        else
        {
            rigid2D.gravityScale = 2.5f;
        }
    }


    public void Move(float x)
    {
        //x축 이동은 x*speed로, y축 이동은 기존의 속력 값(현재는 중력)
        rigid2D.velocity = new Vector2(x * speed, rigid2D.velocity.y);
    }
    public void Jump()
    {
        //jumpForce의 크기만큼 윗쪽 방향으로 속력 설정
        rigid2D.velocity = Vector2.up * jumpForce;
    }
}

 

jump키를 눌렀는지 판단하는 isLongJump변수가 PlayerController에서 GetKey로 설정된다.

using UnityEngine;

public class PlayerController : MonoBehaviour
{
    private Movement2D movement2D;

    private void Awake()
    {
        movement2D = GetComponent<Movement2D>();
    }

    private void Update()
    {
        //left or a = -1 / right or d = 1
        float x = Input.GetAxisRaw("Horizontal");
        //좌우 이동 방향 제어
        movement2D.Move(x);

        //플레이어 점프(스페이스 키를 누르면 점프)
        if (Input.GetKeyDown(KeyCode.Space))
        {
            movement2D.Jump();
        }
        //스페이스 키를 누르고 있으면 isLongJump=true
        if(Input.GetKeyUp(KeyCode.Space))
        {
            movement2D.isLongJump = true;
        }
        //스페이스 키를 떼면 isLongJump=false
        else if (Input.GetKeyUp(KeyCode.Space))
        {
            movement2D.isLongJump = false;
        }
    }
}

스페이스바를 길게 누르냐 짧게 누르냐에 따라 점프의 높이가 달라진다. 길게 눌렀을 때랑 크게 다른 점은 없지만 이중점프가 가능했다..

 

 

 

바닥 판정 및 점프 제어

바닥에 닿아 있을 때만 플레이어가 뛸 수 있도록 설정하는 코드를 작성해보겠다. 

플레이어의 발 위치를 알아야 하며, 코드에서 내가 설정한 collider과 맞게 설정해주어야한다. 

 

충돌이 일어나면 isGrounded 변수가 참이 된다.

using System;
using UnityEngine;

public class Movement2D : MonoBehaviour
{
    [SerializeField]
    private float speed = 5.0f; //이동 속도
    [SerializeField]
    private float jumpForce = 8.0f; //점프 힘(클수록 높게 점프)
    private Rigidbody2D rigid2D;
    [SerializeField]
    public bool isLongJump = false; // 낮은/높은 점프 체크

    [SerializeField]
    private LayerMask groundLayer; //바닥 체크를 위한 충돌 레이어
    private CapsuleCollider2D capsuleCollider2D; //오브젝트의 충돌 범위 컴포넌트
    private bool isGrounded; //바닥 체크 (바닥에 닿아있을 때 true)
    private Vector3 footPosition; //발의 위치


    private void Awake()
    {
        rigid2D = GetComponent<Rigidbody2D>();
        capsuleCollider2D = GetComponent<CapsuleCollider2D>();
    }

    private void FixedUpdate()
    {
        //플레이어 오브젝트의 Collider2D min, center, max 위치 정보
        Bounds bounds = capsuleCollider2D.bounds;
        //플레이어의 발 위치 설정
        footPosition = new Vector2(bounds.center.x, bounds.min.y);
        //플레이어의 발 위치에 원을 생성하고, 원이 바닥과 닿아있으면 isGrounded = true
        isGrounded = Physics2D.OverlapCircle(footPosition, 0.1f, groundLayer);

        //낮은 점프, 높은 점프 구현 위한 중력 계수 조절 Jump Up일 때만 적용)
        //중력 계수가 낮은 if문은 높은 점프가 되고, 중력 계수가 높은 else문은 낮은 점프가 됨.
        if (isLongJump && rigid2D.velocity.y > 0)
        {
            rigid2D.gravityScale = 1.0f;
        }
        else
        {
            rigid2D.gravityScale = 2.5f;
        }
    }

    private void OnDrawGizmos()
    {
        Gizmos.color = Color.blue;
        Gizmos.DrawSphere(footPosition, 0.1f);
    }


    public void Move(float x)
    {
        //x축 이동은 x*speed로, y축 이동은 기존의 속력 값(현재는 중력)
        rigid2D.velocity = new Vector2(x * speed, rigid2D.velocity.y);
    }

    public void Jump()
    {
        if(isGrounded == true)
        {
            //jumpForce의 크기만큼 윗쪽 방향으로 속력 설정
            rigid2D.velocity = Vector2.up * jumpForce;
        }
    }
}

땅으로 사용되는 모든 오브젝트의 layer 값을 Ground로 바꿔주고, 플레이어 오브젝트에도 Ground Layer 변수를 Ground로 설정한다.  Movement2D에  게임을 실행하면, 땅에 닿아야지 점프가 되는 것을 확인할 수 있다.

 

최대 점프 횟수 설정

점프하는 횟수 조절을 할 수 있도록 하여 2단,3단 점프가 가능하게끔 코드를 짠다. 

using UnityEngine;

public class Movement2D : MonoBehaviour
{
    [SerializeField]
    private float   speed = 5.0f; //이동 속도
    [SerializeField]
    private float   jumpForce = 8.0f; //점프 힘(클수록 높게 점프)
    private         Rigidbody2D rigid2D;
    [SerializeField]
    public bool     isLongJump = false; // 낮은/높은 점프 체크

    [SerializeField]
    private LayerMask           groundLayer; //바닥 체크를 위한 충돌 레이어
    private CapsuleCollider2D   capsuleCollider2D; //오브젝트의 충돌 범위 컴포넌트
    private bool                isGrounded; //바닥 체크 (바닥에 닿아있을 때 true)
    private Vector3             footPosition; //발의 위치

    [SerializeField]
    private int       maxJumpCount = 2; //땅을 밟기 전까지 할 수 있는 최대 점프 횟수
    private int       currentJumpCount = 0; //현재 가능한 점프 횟수


    private void Awake()
    {
        rigid2D =           GetComponent<Rigidbody2D>();
        capsuleCollider2D = GetComponent<CapsuleCollider2D>();
    }

    private void FixedUpdate()
    {
        //플레이어 오브젝트의 Collider2D min, center, max 위치 정보
        Bounds bounds = capsuleCollider2D.bounds;
        //플레이어의 발 위치 설정
        footPosition = new Vector2(bounds.center.x, bounds.min.y);
        //플레이어의 발 위치에 원을 생성하고, 원이 바닥과 닿아있으면 isGrounded = true
        isGrounded = Physics2D.OverlapCircle(footPosition, 0.1f, groundLayer);


        //플레이어의 발이 땅에 닿아 있고, y축 속도가 0이하이면 점프 횟수 초기화
        //velocity.y <= 0을 추가하지 않으면 점프키를 누르는 순간에도 초기화가 되어
        //최대 점프 횟수를 2로 설정하면 3번까지 점프가 가능하게 된다.
        if(isGrounded == true && rigid2D.velocity.y <=0)
        {
            currentJumpCount = maxJumpCount;
        }

        //낮은 점프, 높은 점프 구현 위한 중력 계수 조절 Jump Up일 때만 적용)
        //중력 계수가 낮은 if문은 높은 점프가 되고, 중력 계수가 높은 else문은 낮은 점프가 됨.
        if (isLongJump && rigid2D.velocity.y > 0)
        {
            rigid2D.gravityScale = 1.0f;
        }
        else
        {
            rigid2D.gravityScale = 2.5f;
        }
    }

    private void OnDrawGizmos()
    {
        Gizmos.color = Color.blue;
        Gizmos.DrawSphere(footPosition, 0.1f);
    }


    public void Move(float x)
    {
        //x축 이동은 x*speed로, y축 이동은 기존의 속력 값(현재는 중력)
        rigid2D.velocity = new Vector2(x * speed, rigid2D.velocity.y);
    }

    public void Jump()
    {
        //if(isGrounded == true)
        if (currentJumpCount > 0)
        {
            //jumpForce의 크기만큼 윗쪽 방향으로 속력 설정
            rigid2D.velocity = Vector2.up * jumpForce;
            //점프 횟수 1 감소
            currentJumpCount--;
        }
    }
}

위에 코드에서 maxJumpCount 변수의 값으로 2번이라 했기 때문에 최대 점프 값이 2번임을 알 수 있다.


오브젝트 마찰력 설정

위에 게임들을 실행하였을 때 마찰력에 의해 벽면에 플레이어가 붙어 버린다. 이것을 조작하려면 프로젝트 뷰에서 physics Meterial 2D를 설정하면 된다.

+ Recent posts