개발/Unity

유니티 간보기 - 골드메탈 2D 게임 따라하며 유니티 기초 익히기

huiyu 2022. 2. 4. 17:20

1. 기초 프로젝트 세팅 & 2D 이미지 설정하기

https://blog.naver.com/gold_metal/221609252536

 

[유니티 강좌] 3D, 2D 프로젝트는 경계가 없다.

보통 유니티를 처음 접하시는 분들께서 3D 프로젝트와 2D 프로젝트는 구분되어지는 거라 생각하실 수 있...

blog.naver.com

위 강좌 따라하기.

리소스는 아래서 받을 수 있음.

https://assetstore.unity.com/packages/2d/characters/simple-2d-platformer-assets-pack-188518

 

Simple 2D Platformer Assets Pack | 2D 캐릭터 | Unity Asset Store

Elevate your workflow with the Simple 2D Platformer Assets Pack asset from Goldmetal. Find this & more 캐릭터 on the Unity Asset Store.

assetstore.unity.com

 

2. 아틀라스 이용해서 Sprite Animation 적용하기

https://blog.naver.com/gold_metal/221613270615

 

[유니티강좌] 아틀라스에 대해서

해당 강좌에서는 이미 제가 Aseprite에서 아틀라스를 만들었지만 직접 아틀라스를 만들고 싶으신 분들을 ...

blog.naver.com

- Animator Controller : 애니메이션을 관리하기 위한 컨트롤러
- Animation Clip : 애니메이션
 -> 스프라이트의 애니메이션을 객체에 드래그하면 Animation Clip이 만들어진다. 이를 AnimatorController로 관리하면 됨.

* Window->Animation을 통해 애니메이션 키 프레임 애니메이션 관리

* Window->Animator를 통해 애니메이션 관리
아래와 같은 화면이 나옴.

 특정 사건이 발생할 때 애니메이션의 흐름을 여기서 결정. (맞았거나, 공격할때, 움직일 때 등등)

위를 정리해놓은 상태. 초기엔 Entry->'Walk' 걷는 상태로 되어 있어 계속 걷는다.

내가 바꾸고 싶은 상태(State)에 마우스 우측->'Set as Layer Default State'를 누르면 초기 상태로 된다.

'Speed'를 통해 애니메이션 속도 조절 가능

3. 캐릭터 이동하기

https://blog.naver.com/gold_metal/221617701946

 

[유니티 강좌] 2D 물리 최대값

이번 시간에서 플레이어의 최대 이동속도를 구현해보았습니다만, 이보다 더 쉽게 컨트롤할 수 있는 방법이 ...

blog.naver.com

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMove : MonoBehaviour
{
    public float maxSpeed;
    Rigidbody2D rigid;

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

    private void FixedUpdate()
    {
        //Move Speed
        float h = Input.GetAxisRaw("Horizontal");
        rigid.AddForce(Vector2.right * h, ForceMode2D.Impulse);

        //Max Speed
        if (rigid.velocity.x > maxSpeed)//Right
        {
            rigid.velocity = new Vector2(maxSpeed, rigid.velocity.y);
        }
        else if (rigid.velocity.x < maxSpeed*(-1)) //Left
        {
            rigid.velocity = new Vector2(maxSpeed*(-1), rigid.velocity.y);
        }
    }

    private void Update()
    {
        //Stop Speed
        if(Input.GetButtonUp("Horizontal"))
        {
            rigid.velocity = new Vector2(rigid.velocity.normalized.x * 0.5f, rigid.velocity.y);
        }
    }
}

RigidBody에 force로 움직임 구현.

RigidBody->Freeze Rotate로 캐릭터 회전 막음

- 좌우 캐릭터 반전 : SpriteRenderer -> Flip<x/y>

//변수선언
SpriteRenderer spriteRenderer;
    
//Awake()
spriteRenderer = GetComponent<SpriteRenderer>();

//Update
//Direction Sprite
if (Input.GetButtonDown("Horizontal"))
{
    spriteRenderer.flipX = Input.GetAxisRaw("Horizontal") == -1;
}

- 걸을 때 애니메이션 설정하기.
  Animator창에서 Idle 마우스 우측-> MakeTransition, Walk 선택하여 연결.
  Idle에서 다음 상태로 Walk를 설정함.

- Walk상태에 'Paramters'의 bool 형태의 'isWalk'변수 추가하기, 파라미터는 특정 상태가 되면 애니메이션이 변환됨을 의미하는 매개변수.

PlayerIdle->Walk 를 연결하는 연결선을 선택, Conditions에 추가한 매개변수를 추가한다.
 isWalk가 true가 되었을 때 'Walk' 애니메이션이 재생됨을 의미.

- 마찬가지로 Walk에서 PlayerIdle상태로 변환되는 라인도 추가해준다.

아래와 같이 코드에 추가하면 된다.

Animator animator;

//Awake()
animator = GetComponent<Animator>(); 

//Update()
//Animation
if(Mathf.Abs(rigid.velocity.x) < 0.4)
{
   animator.SetBool("isWalk", false);
}
else
{
   animator.SetBool("isWalk", true);
}

 

 

4. 캐릭터 점프하기

public float jumpPower;

//Update
//Jump
if (Input.GetButtonDown("Jump"))
{
    rigid.AddForce(Vector2.up * jumpPower, ForceMode2D.Impulse);
}

* 중력값 조절
 Edit->Project Settings -> Physics2D의 중력값(Gravity)을 조절 해도 되고,
캐릭터의 Rigidbody 2D의 Gravity Scale을 조절해도 됨.

- Gravity Scale : Object에 적용되는 중력값

- 마찬가지로 점프 애니메이션 만들어주기.
 1) 스프라이트로 애니메이션 만들기
 2) 애니메이터에서 상태 추가해주기
 

  - 걷다가 뛰는경우, 가만히 있다 뛰는 경우 추가
  - 점프에서 끝날 경우 원래 상태로 돌아가는 경우 추가
  두 경우 isWalk, isJump state를 추가해서 관리.

**점프 후에 Idle상태로 돌리기
 - Ray 기능을 활용해서 땅과 Ray가 충돌했을 경우 Idle로 돌린다.

FixedUpdate()함수에 추가

        //Debugging ray
        Debug.DrawRay(rigid.position, Vector3.down, new Color(0, 1, 0));

        //Ray Collider Check
        RaycastHit2D rayHit = Physics2D.Raycast(rigid.position, Vector3.down, 1, LayerMask.GetMask("Platforms"));
        if(rayHit.collider != null)
        {
            Debug.Log(rayHit.collider.name);
        }

 - Debug.DrawRay() : 디버깅용 레이 확인 가능
 - RaycastHit2D : 실제 ray를 쏴서 출돌 검사.
  마지막 인자 LayerMask.GetMask("마스크이름")을 넘겨주면, 설정한 레이어만 충돌을 검사한다.

 - 오브젝트 선택후 우측, Inspector 위쪽에 Layers로 설정 가능
 - 점프 후 추락시에만 raycast체크하기

//Ray Collider Check
        if(rigid.velocity.y < 0)
        {
            //Debugging ray
            Debug.DrawRay(rigid.position, Vector3.down, new Color(0, 1, 0));
            RaycastHit2D rayHit = Physics2D.Raycast(rigid.position, Vector3.down, 1, LayerMask.GetMask("Platforms"));
            if (rayHit.collider != null)
            {
                if (rayHit.distance < 0.5f)
                {
                    Debug.Log(rayHit.collider.name);
                    animator.SetBool("isJump", false);
                }
            }
        }

 

 - 무한 점프 막기 -> 점프중엔 점프 입력 막기

if (Input.GetButtonDown("Jump") && !animator.GetBool("isJump"))
{
    rigid.AddForce(Vector2.up * jumpPower, ForceMode2D.Impulse);
    animator.SetBool("isJump", true);
}

=> 최종 코드

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMove : MonoBehaviour
{
    public float jumpPower;
    public float maxSpeed;
    Rigidbody2D rigid;
    SpriteRenderer spriteRenderer;
    Animator animator;

    private void Awake()
    {
        rigid = GetComponent<Rigidbody2D>();
        spriteRenderer = GetComponent<SpriteRenderer>();
        animator = GetComponent<Animator>(); 
    }

    private void FixedUpdate()
    {
        //Move Speed
        float h = Input.GetAxisRaw("Horizontal");
        rigid.AddForce(Vector2.right * h, ForceMode2D.Impulse);

        //Max Speed
        if (rigid.velocity.x > maxSpeed)//Right
        {
            rigid.velocity = new Vector2(maxSpeed, rigid.velocity.y);
        }
        else if (rigid.velocity.x < maxSpeed*(-1)) //Left
        {
            rigid.velocity = new Vector2(maxSpeed*(-1), rigid.velocity.y);
        }


        //Ray Collider Check
        if(rigid.velocity.y < 0)
        {
            //Debugging ray
            Debug.DrawRay(rigid.position, Vector3.down, new Color(0, 1, 0));
            RaycastHit2D rayHit = Physics2D.Raycast(rigid.position, Vector3.down, 1, LayerMask.GetMask("Platforms"));
            if (rayHit.collider != null)
            {
                if (rayHit.distance < 0.5f)
                {
                    Debug.Log(rayHit.collider.name);
                    animator.SetBool("isJump", false);
                }
            }
        }
    }

    private void Update()
    {
        //Jump
        if (Input.GetButtonDown("Jump") && !animator.GetBool("isJump"))
        {
            rigid.AddForce(Vector2.up * jumpPower, ForceMode2D.Impulse);
            animator.SetBool("isJump", true);
        }

        //Stop Speed
        if (Input.GetButtonUp("Horizontal"))
        {
            rigid.velocity = new Vector2(rigid.velocity.normalized.x * 0.5f, rigid.velocity.y);
        }

        //Direction Sprite
        if (Input.GetButtonDown("Horizontal"))
        {
            spriteRenderer.flipX = Input.GetAxisRaw("Horizontal") == -1;
        }

        //Animation
        if(Mathf.Abs(rigid.velocity.x) < 0.4)
        {
            animator.SetBool("isWalk", false);
        }
        else
        {
            animator.SetBool("isWalk", true);
        }
    }
}

 

최종 캐릭터 이동 실습

 

728x90
반응형