이미지 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에 놓습니다. 자동으로 애니메이션 컴포넌트가 추가됩니다.

 

+ Recent posts