이미지 UI 만들기

하이라키 + 를 누르고 UI>Image를 클릭한다. Canvas를 부모로 Image가 생기고 EventSystem까지 생겼다. ㅠㅠ

Canvas 표시 설정

하이라키의 Canvas를 더블클릭해서 포커스해보면 게임화면 보다 훨씬 큰 크기입니다. 

현재 Canvas의 Renderer Mode는 Screen Overlay라 결국 최종 출력위에 오버레이 되는 거라 출력은 게임화면 사이즈를 무시하고 현재 이 상태가 오버레이되지만 게임화면과 좀더 직관적인 편집을 위해 모드를 Screen Space - Camera로 변경합니다. 나중에 다시 변경해도 문제없습니다. Renderer Camera를 하이라키의 Main Camera를 끌어다 놓거나 ◉검색브라우저를 눌러 찾아도 됩니다.

이제 하이라키의 Canvas를 더블클릭해서 포커스를 주면 게임화면과 같이 보이게 되나 이미지가 보이지 않습니다. 문제는 Order in Layer입니다. 이걸 10으로 변경해서 가장 위로 위치 시킵니다. 

Overlay Mode에서는 무조건 게임씬 맨 위로 오버레이되기 때문에 이런 문제가 없습니다. 여기서 다루지 않은 World Space모드는 Cavas위치를 게임내 3D 월드공간 특정 위치에 배치됩니다. 따라서 자유도는 있지만 게임출력화면에 딱 붙어 있지 않으므로 잘 조절해야 합니다.

 

현재 이미지는 Cavas 좌하에 위치하고 있습니다. 중앙으로 옮겨보겠습니다. 하이라키의 Image를 클릭한후 손으로 옮겨도 되겠지만 좀더 편한 방법이 있습니다. 인스펙터뷰의 Transform아래 좌표그림을 눌러봅니다. Anchor 프리셋이 나타납니다. 잘 읽어보면 Alt를 누를 경우 set position을 바꿀수 있습니다. Alt를 누르면 화면이 바뀌고 가운데를 누르면 위치가 가운데로 변경됩니다.

Image가 선택되어져 있는 상태에서 프로젝트뷰 Images폴더에서 GameStart이미지를 Image컴포넌트의 Source Image에 끌어다 가져다 놓으면 표시가 바뀝니다.

그런데 사이즈가 좀 작고 글씨가 뭉쳐보이지요 같은 Image컴포넌트 내 PreserveApect를 체크하고 Set Native Size를 클릭하면 보기좋게 바뀝니다.

버튼 UI 추가하기

게임이 끝난 후 재시작하기 위한 RESTART버튼을 추가합니다. 버튼도 UI오브젝트이기에 Cavas안에 배치합니다.

계층 뷰의 Canvas를 선택하고 +>UI>Legacy>Button을 선택합니다. 이름을 RestartButton으로 변경합니다.

Images폴더내 Button스프라이트를 끌어다 Image컴포넌트의 Source Image로 끌어다 주고 Preserve Aspect 체크 Set Native Size를 클릭후 화면에 맞게 적당히 사이즈를 조절해줍니다.

하이라키의 RestartButton을 펼쳐보면 Text가 숨어 있습니다. RestartText로 이름을 변경해주고 인스펙터뷰의 Text컴포넌트에서 RESTART로 Text내용을 바꿔주고 사이즈도 적당히 바꿔줍니다.

하이라키뷰에서 RestartButton를 선택후 Ctrl-D를 눌러 복사한후 이름을 NextButton으로 변경한후 펼치후 Text를 인스펙터뷰에서 NEXT로 바꿉니다. RestartButton을 선택후 위치도 적당히 아래로 내려줍니다. (위치는 Text가 아닌 Button을 해야 함께 움직입니다.)

하이라키에서 Canvas선택후 +를 눌러 UI>패널을 만듭니다. 버튼2개를 감쌀 정도로 사이즈를 바꿔줍니다.

 

이후 버튼 2개를 패널의 자식으로 만듭니다. 패널을 선택하고 칼라의 알파를 0으로 변경합니다.

골인 지점에 도착했을때와 게임오버시의 충돌처리를 작성합니다.

gameState라는 게임 상태를 나타내는 정적변수를 선언해서

player가 죽었을때는 "gameover", Goal에 도착했을대는 "gameclear"상태가 되어

각 이벤트호출시 gameState가 "playing"상태가 아니면 처리하지 않게해서 플레이어를 멈추게 합니다.

보통의 게임오브젝트(인스턴스)는 씬이 바뀔경우 없어지게 되는데 gameState는 정적변수라 씬이 바뀌어도 게임 전체에 계속 남아 있을 수 있다.

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

public class PlayerController : MonoBehaviour{
	~생략~
    public static string gameState = "playing"; //게임중
		~생략~
    void Start(){
		~생략~
        gameState = "playing";
    }

    // Update is called once per frame
    void Update(){
        if(gameState != "playing") {
            return;
        }
		~생략~
    }
    private void FixedUpdate() {
        if(gameState != "playing") {
            return;
        }
       		~생략~
    }
    public void Jump() {
       		~생략~
    }
    private void OnTriggerEnter2D(Collider2D collision) {
       		~생략~
    }
    public void Goal() {
        		~생략~
        gameState = "gameClear";
        GameStop(); //게임중지;
    }
    public void GameOver() {
       		~생략~
        gameState = "gameOver";
        GameStop();   //게임중지
        GetComponent<CapsuleCollider2D>().enabled = false;  //플레이어 판정 비활성화
        rbody.AddForce(new Vector2(0, 5), ForceMode2D.Impulse);  //한번 튕겨줍니다.
    }
    void GameStop() {
        Rigidbody2D rbody = GetComponent<Rigidbody2D>();
        rbody.velocity = Vector2.zero;
    }
}

PlayerController.cs
0.00MB

이제 애니메이션 전화을 위한 PlayerController 스크립트를 수정합니다.

이번에 제일 중요한 부분은 충돌 판정입니다. Goal과 Dead존에 들어가면 알맞은 함수를 실행합니다.

  private void OnTriggerEnter2D(Collider2D collision) {
        if (collision.gameObject.tag == "Goal") {
            Goal();
        } else if(collision.gameObject.tag =="Dead") {
            GameOver();
        }
    }

FixedUpdate()에서는 이동중이면 PlayerMove, 정지시 PlayerStop, 하늘에 떠 있다면 PlayerJump 애니메이션을 실행합니다.

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

public class PlayerController : MonoBehaviour{
		// 생략
		//애니메이션처리
    Animator animator;  //애니메이터 컨트롤러 참조
    public string stopAnim = "PlayerStop";
    public string moveAnim = "PlayerMove";
    public string jumpAnim = "PlayerJump";
    public string goalAnim = "PlayerGoal";
    public string deadAnim = "PlayerOver";
    string nowAnim = "";
    string oldAnim = "";
    void Start(){
        rbody = GetComponent<Rigidbody2D>();
        animator = GetComponent<Animator>();
        nowAnim = stopAnim;
        oldAnim = stopAnim;
    }

    // Update is called once per frame
    void Update(){
 		// 생략 
    }
    private void FixedUpdate() {
     	//생략
        if(onGround) {
            if(axisH == 0) {
                nowAnim = stopAnim;
            } else {
                nowAnim = moveAnim;
            }
        } else {
            nowAnim = jumpAnim;
        }
        if(nowAnim != oldAnim) {
            oldAnim = nowAnim;
            animator.Play(nowAnim);
        }
    }
    public void Jump() {
        goJump = true;
    }
    private void OnTriggerEnter2D(Collider2D collision) {
        if (collision.gameObject.tag == "Goal") {
            Goal();
        } else if(collision.gameObject.tag =="Dead") {
            GameOver();
        }
    }
    public void Goal() {
        animator.Play(goalAnim);
    }
    public void GameOver() {
        animator.Play(deadAnim);
    }
}

PlayerController.cs
0.00MB

 

점프 애니메이션을 이전 처럼 여러장의 스프라이트로 자동으로 만들어도 되지만 이번에는 수동으로 만들어 보겠습니다.

하이라키에서 player를 선택하고 Ctrl+6를 클릭해서 애니메이션 창을 엽니다. 메뉴 Windows>Animation>Animation을 클릭해서도 열수 있습니다.

현재는 PlayerMove하나만 있습니다. PlayerMove>Create New Clip을 선택한후 PlayerJump로 바꿉니다.

Add Property를 클릭해 Sprite Renderer>Sprice옆 +를 클릭합니다.

기본적으로 player_stop이 1초간 적용되어 있는데 Assets>Player폴더내 Player_Jump1,2로 변경해보겠습니다.

Player_Jump1을 0프레임에 끌어다 놓습니다. Player_Jum2를 0.2초 1초 2군데 끌어다 놓습니다.

 

대기, 클리어, 게임오버 애니메이션 만들기

New Animation Clip을 PlayerStop이라는 이름으로 만들고 Player폴더에서 Player_Stop 스프라이트를 끌어다 0프레임에 놓으면 자동으로  Sprite프라퍼티가 추가되면서 다이아몬드가 생깁니다.

PlayerGoal이라는 이름으로 새로운 Clip을 만들고 Player_Clear라는 스프라이트를 0프레임과 60프레임에 끌어다 놓습니다. Add Property>Sprite Color를 추가하고 60프레임의 Color.a를 0으로 변경합니다.

지금까지 Move, Jump, Stop, Clear, Over 애니메이션클립을 만들었습니다. 이들이 상황에 맞게 전화되도록 해보겠습니다.

Animations 폴더의 Player Anim을 열어봅니다. 그동안 만들었더 애니메이션들이 모여있습니다.

현재  제일 먼저 시작되는 Entry에서 PlayerMove가 디폴트로 설정되여 있는데 PlayerStop으로 바꿔보겠습니다. PlayerStop위를 우클릭하고 Set as Layer Default State를 선택합니다. PlayerStop이 디폴트가 됩니다.

이제 플레이 해보면 PlayerStop이 디폴트이므로 아무런 동작도 안하고 움직여도 애니메이션이 없습니다.

애니메이션은 유니티의 메카님 기능을 활용합니다. 여러장의 스프라이트를 순차적으로 플레이해서 애니메이션을 보여줍니다.

 

이동 애니메이션 만들기

프로젝트뷰 player폴더내 player_run1부터 run7까지를 모드 선택후 Pivot이 Bottom인지 확인후 , 씬뷰로 드래그&드롭 합니다. 저장할건지 물어보면 PlayerAnim으로 저장합니다.

하이라키에 보면 player_run1이 생겼는데 레이어오더 문제로 보이지 않습니다. Order를 3으로 변경합니다.

저장후 폴더에는 삼각형과 사각형모양의 아이콘이 2개 생깁니다. 이름을 아래와 같이 변경하고 Animations폴더를 만들어 이동 시킵니다. 삼각형은 이동동작을 표현하난 애니메이션클립이고 사각형은 여러가지 애니메이션을 조건에 맞게 플레이 해주는 애니메이터(컨트롤러)입니다. 새로만들어진 player_run1의 인스펙터뷰를 보면 Animator컴포넌트가 추가되어 있고 Controller는 PlayerAnim가 연결되어 있습니다.

Player Move를 선택하고  Samples가 12로 되어 있습니다. 7을 입력하고 엔터하면 조금 느리게 재생됩니다. 플레이가 재생이 안되면 하이라키의 player_run1을 클릭하면 잘 움직입니다.

이제 하이라키의 player_run1을 지웁니다. 씬뷰에서 방금 만든 캐릭터를 지워도 됩니다.

이제 프로젝트뷰 Animations폴더내 PlayAnim을 끌어다 하이라키의 player에 놓습니다. 자동으로 애니메이션 컴포넌트가 추가됩니다.

 

플레이어 캐릭터가 점프를 할 수 있는데 벽이나 블록에 닿으면 붙어서 떨어지지 않습니다. 이는 캐릭터의 마찰력 때문입니다.  마찰을 0으로 바꾸어 보겠습니다.

 프로젝트뷰의 +를 눌러 2D> physics Material 2D를 클릭합니다. 이름을 PM2D라고 변경합니다.

Fricsion을 0으로 바꿉니다.

이 매터리얼을 Player에 적용합니다. 

Player게임오브젝트의 인스펙터뷰> Rigidbody2D > Material 검색브라우저를 눌러 방금만든 PM2D를 적용시킵니다. 파일을 끌어다 여기다 놔도 됩니다.

 

Vector2 jumpPw = new Vector2(0, jump);  // 점프벡터 생성
rbody.AddForce(jumpPw, ForceMode2D.Impulse); //순간적인 힘 가하기
goJump = false; // 점프플래그 끄기

플레이어 Tag지정하기

플레이어를 선택하고 Tag를 player를 선택합니다. player Tag는 기본적으로 있습니다.

 

점프 구현하기

스페이스바를 눌렀을때 캐릭터를 점프하게 만들어 보겠습니다.

Update()함수에 스페이스키를 체크되면 Jump()함수를 호출하는 코드가 추가되었습니다. 

Jump() 함수는 goJump 플래그를 true로 할 뿐입니다.

public void Jump() {
    goJump = true;
}

실제 점프 동작은 FixedUpdate()에서 if(onGround && goJump) 때 이루어 집니다. 

Vector2 jumpPw = new Vector2(0, jump);  // 점프벡터 생성
rbody.AddForce(jumpPw, ForceMode2D.Impulse); //순간적인 힘 가하기
goJump = false; // 점프플래그 끄기

플레이 해보면 스페이스바를 눌러도 캐릭터가 점프를 안하는데 LayerMask 변수인 groundLayer를 인스펙터뷰 playerController 스크립트 창에서 ground로 설정해야 합니다.

public LayerMask groundLayer; //착지할 수 있는 레이어
bool onGround = false;  //지면에 서 있는 플래그

Linecast가 캐릭터위치에서 0.1f 아래로 광선을 쏴서 goundLayer가 감지될경우만 onGround를 true시킵니다.

onGround = Physics2D.Linecast(transform.position, 
					transform.position - (transform.up * 0.1f), groundLayer);

Linecast(시작점, 종료점, 마스크)

 

아래는 playerController.cs 전체코드입니다.

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

public class PlayerController : MonoBehaviour{
    // Start is called before the first frame update
    Rigidbody2D rbody;  // Rigidbody 참조
    float axisH = 0.0f; //입력
    public float speed = 3.0f;  //이동속도

    public float jump = 9.0f; //점프력
    public LayerMask groundLayer; //착지할 수 있는 레이어
    bool goJump = false; //점프개시 플래그
    bool onGround = false;  //지면에 서 있는 플래그
    void Start(){
        rbody = GetComponent<Rigidbody2D>();
    }

    // Update is called once per frame
    void Update(){
        axisH = Input.GetAxisRaw("Horizontal");
        if(axisH > 0.0f) {
            transform.localScale = new Vector2(1, 1);
        } else if (axisH <0.0f) {
            transform.localScale = new Vector2(-1, 1);
        }
        if (Input.GetButtonDown("Jump")) {
            Jump();
        }
    }
    private void FixedUpdate() {
        //착지판정
        onGround = Physics2D.Linecast(transform.position, transform.position - (transform.up * 0.1f), groundLayer);
        if(onGround || axisH !=0) {  //점프상태일 때는 전진 안함.
            rbody.velocity = new Vector2(speed * axisH, rbody.velocity.y);
        }
        if(onGround && goJump) {
            Vector2 jumpPw = new Vector2(0, jump);  // 점프벡터 생성
            rbody.AddForce(jumpPw, ForceMode2D.Impulse); //순간적인 힘 가하기
            goJump = false; // 점프플래그 끄기
        }
    }
    public void Jump() {
        goJump = true;
    }
}

 

이번에 만들 게임요소를 정리해 보겠습니다.

  • 규칙 : 오른쪽 끝의 골인 지점에 도착하면 게임 클리어
  • 적과 장애물 : 함정에 떨어지면 게임 오버
  • 간섭과 변화 : 점프로 함정 뛰어넘기
  • 보상 : 함정을 피해서 목표 지점에  도착

 

4.1 사이드뷰게임

사이드뷰는 게임 속 세상을 옆에서 바라본 시점의 게임 시스템입니다. 이동은 좌우나 점프를 위해 상하로 움직일 수 있습니다. 

 

사용할 게임 오브젝트와 스크립트 생각해보기

  • 플레이어 캐릭터 : 좌우이동과 점프를 할 수 있습니다. 이동이나 점프를 묘사할 애니메이션을 적용합니다.
  • 지면과 블록 :  플레이어가 올라가서 이동할 수 있는 지면과 점프해 올라갈 수 있는 발판이 되는 블록입니다.
  • 골인 지점과 게임 오버 : 게임 스테이지의 오른쪽 끝에 게임 오브젝트를 배치해 이곳에 접촉하면 스테이지 클리어되도록 목표지점을 만듭니다. 지면 아래로 떨어지면 게임 오버되는 처리도 추가합니다.
  • 상태 표시와 재시작 : 게임으 시작및 게임오버 클리어했을 때의 화면을 표시하고 다시 처음부터 시작할 수 있게 합니다. 

4.2 샘플 게임 실행해보기  

Jewlry Hunter폴더내의 프로젝트를 플레이 해보시면 됩니다.

4.3 게임 스테이지 만들기

지면 블록 만들기

이전에 연습했던 프로젝트를 사용합니다.

프로젝트뷰의 Block들을 끌어다 씬뷰에 배치합니다.

위와 같이 보이지 않을겁니다. 왜냐하면 Order in Layer가 밑에 있기 때문에 가려져서 그렇습니다.

하이라키에서 방금 끌어온 block들을 선택해고 인스펙터뷰의 Additional Settings의 Order in Layer를 2로 하면 위와 같이 블록들이 보입니다.

레이어로 게임 오브젝트를 그룹으로 분류하기 (레이어)

유니티는 게임오브젝트를 이름으로 식별할 수 있지만 "레이어"를 사용해 그룹으로 묶을 수도 있습니다. 바닥과 블록을 Ground라는 이름으로 그룹화해 플레이어 캐릭터가 레이어에 접촉할 때만 점프할 수 있도록 합니다.

인스펙터뷰의 레이어 Item을 눌러 Add Layer로 Ground 레이어를 추가합니다.  보통 0~5까지는 유니티가 사용중이므로 레이어6에 새로 만듭니다.

레이어 추가 메뉴는 게임오브젝트 메뉴와 독립적이라 돌아갈 수 없고 다시 하이라키의 게임오브젝트를 선택해야 합니다.

한꺼번에 레이어를 바꾸기 위해 하이라키에서 ground 와 블록3가지를 선택하고 인스펙트뷰에서 레이어를 6으로 바꿔줍니다.

씬뷰에 goal팻말을 배치하고 인스펙터뷰에서 Order in Layer를 2로 바꿔줍니다.

골인 지점 도달 판별하기

목표에 도달한것을 판별하기 위해 goal에 Box Collider2D 컴포넌트를 추가하고 Is Trigger를 체크합니다. Is Trigger는 물리적인 충돌없이 충돌 이벤트만 만듭니다.

 

게임오브젝트를 구별하는 방법(태그)

골인 지점에 도달했는지 판별하는 방법중 태그(Tag)도 있습니다. 

하이라키에서 goal을 선택후 인스펙트뷰에서 Tag를 눌러 Add Tag에서 Goal을 만들고 저장합니다. 이후 Goal에서 지정합니다.

게임오브젝트 재사용하기

유니티에서 프리팹은 재사용가능한 "클래스"같은 개념입니다. 하이라키의 ground,block1,2,3,goal등을 끌어다 프로젝트뷰에 끌어다 놓으면 자동으로 프리팹이 만들어 집니다. 하이라키의  ground,block1,2,3,goal등은 이미 파란색으로 바뀌었는데 이건 프리팹의 인스턴스라는 이야기 입니다. 프리팹을 사용하고 싶으면 아이콘을 끌어다 하이라키나 씬뷰에 놓으면 인스턴스가 만들어집니다.

프로젝트뷰의 프리팹은 런타임시 존재하지 않습니다. 씬뷰에서 인스턴스화 되었을때 비로서 런타임에서 존재하고 접근할 수 있습니다. 이점이 중요합니다. 클래스나 타입도 변수화 하지 않으면 아무것도 아닌것 처럼요.

프리팹을 변경하면 기본에 만들었던 모든 인스턴스에 영향을 미칩니다. 반대로 인스턴스를 변경해면 유니티에서 프리팹을 변경할건지 물어보는 개념도 있습니다. 이걸 오버라이드라고 합니다.

프리팹을 정리하기 위해 프로젝트뷰 Assets 폴더안에 Prefabs폴더를 만들고 만들어진 프리팹들을 끌어다 놓습니다.

 

프리팹을 배치해 지면 만들기

프리팹 폴더안의 프리팹들을 이용해 다음과 같이 지면과 블록을 더 배치 합니다. (이미지 폴더가 아닙니다.)

백그라운드는 back_title에서 back으로 바꾸었습니다. 길게보이는 그라운드는 확대한게 아니라 같은 그라운드를 2개 연결한것입니다.

 

게임 오브젝트 정렬하기

옮길 오브젝트를 살짝 클릭해서 선택해줍니다. 마우스클릭하지 않고 키보드 V를 눌러 맞추고 싶은 중앙이나 모서리를 클릭하면서 맞출곳에 가져가면 자석같이 붙습니다. 화면을 좀 크게하시는게 잘되고 한번에 안되면 옮긴후 다시 시도 하면 됩니다.

 

보이지 않는 충돌 판정 만들기

하이라키의 +를 눌러 Create Empty를 클릭합니다. 이름을 Wall로 합니다. Box Collider 2D를 2개 추가합니다.

Edit  Collider를 눌러 충돌영역의 위치를 화면 양옆으로 이동시킵니다. BoxCollider2D를 2개 추가했기 때문에 영역이 2개 입니다. 

플레이해보면 캐릭터가 왼쪽벽에 부딪쳐 가지 못합니다. 

 

게임오버 판별하기

현재는 구덩이쪽으로 가면 캐릭터가 빠져 계속 떨어지기 때문에 게임진행이 더 이상 불가능 합니다.

DeadZone이라는 빈게임오브젝트를 만들고 BoxCollider2D컴포넌트를 추가하고 Is Trigger를 체크합니다.  Edit Collider를 누루고 다음과 같이 화면 아래 배치합니다. 

Dead라는 Tag를 만들어 지정해 줍니다.

 

 

 

 

 

스크립트로 게임 오브젝트 조작하기

Rigidbody2D나 Box Collider등과 같은 컴포넌트들을 게임오브젝트에 추가했던것 처럼 스크립트를 컴포넌트처럼 추가할 수 있습니다.

 

스크립트 파일 만들기

게임오브젝트에서 Add Component에서 스크립트를 추가할 수도 있고 프로젝트뷰에서 스크립트를 만들어 나중에 추가할 수도 있습니다. 프로젝트뷰에서 Scripts폴더를 만든후 폴더안에서 우클릭후 Create>Script를 클릭후 이름을 PlayerController로 바꿔줍니다.

키 입력으로 게임 오브젝트를 조작하는 스크립트

Rigidbody2D rbody;  // Rigidbody2D의 참조입니다.

게임오브젝트 생성시 불리워지는 Start() 함수에서 rbody변수에 Rigidbody2D 참조를 연결합니다.

매 프레임 불리워지는 Update()에서 키보드입력을 받습니다. axisH = Input.GetAxisRaw("Horizontal");

일정한 간격으로 호출되는 FixedUpdate()에서 Rigidbody 2D컴포넌트를 사용중이므로  Rigidbody를 물리를 이용 객체의 위치를 변경시킵니다. rbody.velocity = new Vector2 (axisH * 3.0f, rbody.velocity.y);

Rigidbody를 사용하지 않을경우 Transform컴포넌트를 이용 객체를 이동시키나 Rigidbody를 사용시는 되도록 Rigidbody를 사용해야 합니다. 이는 Rigidbody가 Trnasform컴포넌트 보다 나중에 실행되어지기 때문입니다.

저장후 Pplayer_stop에 적용시켜줍니다. 플레이후 AD키를 누르면 좌우로 움직입니다.

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

public class PlayerController : MonoBehaviour
{
    // Start is called before the first frame update
    Rigidbody2D rbody;
    float axisH = 0.0f;
    void Start()
    {
        rbody = GetComponent<Rigidbody2D>();
    }

    // Update is called once per frame
    void Update()
    {
        axisH = Input.GetAxisRaw("Horizontal");
    }
    private void FixedUpdate() {
        rbody.velocity = new Vector2 (axisH * 3.0f, rbody.velocity.y);
    }
}

변수부분에 public float speed = 3.0f; 를 추가하고 상수 3.0f대신 speed를 사용합니다.

캐릭터가 좌우로 움직일 경우 진행 방향을 바라보기 위해 transform.localScale을 이용합니다. 물리상 - Scale은 말이 안되지만 유니티에서는 반전을 뜻합니다.  (-1,1)은 x축만 반전 시키겠다는 의미입니다.

if(axisH > 0.0f) { //오른쪽 처리
    transform.localScale = new Vector2(1, 1);
} else if (axisH <0.0f) {  //왼쪽 처리
    transform.localScale = new Vector2(-1, 1);
}

저장하고 실행해보면  캐릭터가 진행방향에 따라 반전하는걸 알수 있습니다. 

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

public class PlayerController : MonoBehaviour{
    // Start is called before the first frame update
    Rigidbody2D rbody;
    float axisH = 0.0f;
    public float speed = 3.0f;
    void Start(){
        rbody = GetComponent<Rigidbody2D>();
    }

    // Update is called once per frame
    void Update(){
        axisH = Input.GetAxisRaw("Horizontal");
        if(axisH > 0.0f) {
            transform.localScale = new Vector2(1, 1);
        } else if (axisH <0.0f) {
            transform.localScale = new Vector2(-1, 1);
        }
    }
    private void FixedUpdate() {
        rbody.velocity = new Vector2 (speed * axisH, rbody.velocity.y);
    }
}

실행해보면 좌우방향에 따라 캐릭터가 반전한다.

2.1 새프로젝트 만들기

2D 프로젝트 만들기

유니티 허브에서 우상 New project를 클릭후  2D템플릿을 선택후 이름을 UniSideGame으로 하겠습니다.

샘플 게임과 샘플 에셋 다운로드

아래 사이트에서 예제를 다운 받아  풀어보니까너무 커서 컴퓨터 멈출정도로 느리네요 ㅠㅠ  너무 커서 그냥 풀지 마시고 아래에서 그때  그때 필요한 파일을 올려드릴께요

https://bit.ly/unity2d_jpub

 

unity2d_jpub.zip

 

drive.google.com

 

2.2 게임화면 만들기

이미지 에셋을 프로젝트에 등록하기

압축파일을 풀어서 Playes, Images 폴더 통채로 Assets폴더로 복사합니다. 

Images.zip
2.11MB
Player.zip
0.36MB

이미지 에셋으로 게임화면 만들기

하이라키에 다음과 같이 Images/back, ground, Player폴더의 player_stop이미지를 끌어다 놓는다. 플레이해 보면 예상과 다르게 배경만 보인다. player_stop의 이름은 player로 바꿉니다.

트랜스폼

트랜스폼:  위치, 화면 크기를 조절하는 컴포넌트 입니다. 

스프라이트랜더러

스프라이트랜더러 :  이미지를 표시하는 컴포넌트입니다. 다음과 같은 값을 가지고 있습니다.

Sprite : 표시할 이미지에셋을 나타냅니다.

Color : 색감변경

Flip : 상하좌우로 반전시킬수 있습니다.

Sorting Layer: 게임오브젝트를 레이어라는 그룹으로 묶고 표시의 우성순위를 그룹별로 지정할 수 있습니다.

Order in Layer : Sorting Layer로 나눈 레이어 중 게임 오브젝트가 씬에 표시되는 순서를 정합니다. 값이 클수록 앞에 표시됩니다.

 

게임 오브젝트의 이미지 변경하기

스프라이트렌더러에는 이미지의 파일명이 표시된  Sprite라는 항목이 있습니다. Sprite를 클릭하면 프로젝트뷰에서 해당 이미지 에셋이 강조돼 어느 에셋이 사용되는지 확인할 수 있습니다.

이미지를 선택한후 Delete키를 클릭해 제거해 보면 씬뷰에서보이지 않게 되지만 하이라키뷰에서는 게임오브젝트가 남아 있습니다.

다시 이미지를 설정해 봅시다. 이미지가 제거 되었으니 계층뷰에서 게임오브젝트를 선택합니다. 프로젝트 뷰의 이미지를 선택해 Sprite의 오른쪽 텍스트박스에 드래그앤드롭합니다.

 

표시우선순위를 알아보기

지면이나 캐릭터 등은 항상 배경보다 앞에 표시돼야 해 표시 우선순위를 의도적으로 변경해야 합니다. 우선순위를 높이려면 Sprite Renderer 컴포넌트의 Additional Settings에서 Order in Layer의 값을 크게 합니다. 여기서는 배경 0, 플레이어는 3, 지면은 2로 설정했습니다. 드디어 보이네요

게임 오브젝트 재배치하기

title_back: (4,0,0), ground:(-5,-2,0), player_stop:(-5,0,0)

 

게임 오브젝트에 중력(Rigidbody 2D)추가하기

 하이라키에서 player_stop을 선택하고 오른쪽 인스펙터부에서 Rigidbody 2D 컴포넌트를 추가합니다.

플레이해보면 플레이어가 아래로 떨어집니다.

 

충돌판정, ground에 Box Collider 2D 추가하기

하이라키에서 ground를 선택하고 Box Collider 2D를 선택 추가합니다. 

플레이 해보면 아직도 플레이어가 떨어집니다. 이제 플레이어에도 Box Collider 2D를 추가해보면  다음과 같이 사각형이 생기는데 Edit Collider를 누르면 사각형 색과 모양이 다음과 같이 바끼고 크기를 조정할 수 있습니다. Capsule Collider 2D를 선택하면 좀더 타이트하게 설정도 가능합니다. 가벼운 처리를 위해서는 Circle Collider 2D가 있습니다. 대량의 적 캐릭터의 충돌 판정에 적합합니다.

 

플레이 해보면 캐릭터가 그라운드 위에서 멈춥니다.

 

+ Recent posts