티스토리 뷰

[유니티]캔버스에 이미지 추가 및 소스 활용법, 스프라이트 설정 방법

rucya 2016. 10. 12. 11:34

[유니티]캔버스에 이미지 추가 및 소스 활용법, 스프라이트 설정 방법

 


유니티(Unity 3D)에서 캔버스(Canvas)를 사용해 이미지를 추가하고, 필요에 따라 이미지를 변경하는 방법에 대한 설명입니다.

 

유니티에서 이미지를 추가하는 방법은 크게 2가지(또 다른 방법이 있는지는 잘 모르겠지만..) 방법이 있습니다.

 

1. 3D 오브젝트를 추가하고 이미지를 입히는 방법

2. 캔버스를 추가하고 이미지를 추가하는 방법

 

◎ 3D 오브젝트를 추가하고 이미지를 입히는 방법

유니티에서 3D 오브젝트를 추가하고 3D 오브젝트에 이미지를 입히는 방법은 고정된 메뉴나 아이콘보다는 움직이는 캐릭터에 많이 사용하는 방법입니다.

캐릭터와 함께 움직이는 게이지(예를 들면 HP 등)를 만들 때는 이 방법이 효율적입니다.

하지만 고정된 위치에 나오는 게임 메뉴나 아이콘 등은 캔버스를 활용하는 방법이 더 효율적입니다.

 

◎ 캔버스를 추가하고 이미지를 추가하는 방법

유니티에서 캔버스를 이용해 이미지를 추가하는 방법은 위의 설명처럼 고정된 메뉴나 아이콘 등을 배치할 때 매우 효율적입니다.

화면의 위치나 크기 등을 작업하기에 편리합니다.

 

캔버스를 이용해 이미지를 표현하는 방법은 3D 오브젝트를 사용하는 방법과 달리 몇 가지 주의해야 할 사항이 있고, 사용 방법도 조금 차이가 있습니다.

유니티에는 많이 기능이 있는데 제가 아직 모르는 기능도 많기 때문에 제가 알고 있는 선에서 정리를 해 보도록 하겠습니다.

 

캔버스를 이용해 이미지를 추가하기 위해서는 캔버스를 먼저 추가해야 합니다.

캔버스를 추가하지 않고 이미지나 버튼, 텍스트 등을 추가하면 유니티가 자동적으로 캔버스를 추가하며, 이벤트 시스템(EventSystem)도 자동으로 추가됩니다.

 

 

 

위의 그림처럼 추가된 캔버스를 선택한 상태에서 유니티 메뉴의 Component -> UI 메뉴 하위에 있는 텍스트나 이미지 버튼 등을 추가하면 됩니다.

캔버스에서 사용되는 이미지는 스프라이트(Sprite)로 변경해서 사용하게 되는데요.

우선 추가할 이미지를 작업해서 Resources 폴더에 저장합니다.

반드시 Resources 폴더에 저장해야 하는 것은 아니지만 추후 소스를 작성해 상황에 따라 이미지를 변경하고자 한다면 Resources 폴더나 Resources 폴더의 하위 폴더에 저장해 두어야만 합니다.

Resources 폴더에 대한 설명은 아래의 소스 설명에서 자세하게 설명하겠습니다.

 

 

위 그림처럼 Resources 폴더에 저장된 이미지를 선택 후 Inspector 창에서 Texture Type 을 Sprite (2D and UI) 로 변경한 다음 우측 하단의 Apply 버튼을 클릭합니다.

그러면 선택된 이미지는 일반 이미지 형태가 아닌 Sprite 형태가 되며, 캔버스의 이미지로 활용이 가능합니다.

참고로 Inspector 창의 Max Size는 큰 이미지의 경우 사이즈에 맞게 변경해 주는 것이 좋습니다.

유니티는 모든 이미지를 2의 배수에 해당하는 크기로 압축해서 사용을 하는데 사용하고자 하는 사이즈(가로나 세로 사이즈)가 2500인데 2048로 설정할 경우 2500 사이즈의 이미지를 2048로 압축해서 저장하기 때문에 화질이 떨어지는 문제가 발생할 수 있습니다.

그러므로 사용하는 이미지의 가로나 세로 사이즈 중 큰 사이즈의 바로 윗 단계로 설정해 주는 것이 좋습니다.

위에서 언급한 2500의 경우 2048 보다는 4096 으로 설정해 주는 것이 좋습니다.

예를 들어 이미지의 크기가 300 * 200 이라면 300보다 큰 숫자중 2의 배수에 해당하는 512로 설정해 주는 것이 좋습니다.

 

유니티에서는 사용자가 어떤 오브젝트를 터치했는지를 알아낼 때 Raycast 기능을 사용하는데요.

캔버스를 사용할 경우는 주의해야 할 사항이 있습니다.

캔버스를 사용하지 않을 경우에는 Raycast 기능을 활용해 사용자가 터치한 오브젝트를 알아내는데 문제가 발생하지 않지만,

캔버스를 사용할 경우 캔버스의 이미지나 버튼에도 클릭처리가 일어나고, 아울러 Raycast에서도 중복으로 터치한 것으로 결과가 나타납니다.

만약 캔버스의 버튼을 누른 경우에는 버튼에 대한 처리만 하고자 한다면 상당한 문제가 발생하지요.

 

그렇다보니 저의 경우에 이전 게임까지는 캔버스를 사용하지 않아 문제가 없었지만...

캔버스도 사용하면서 Raycast 기능을 같이 사용하려니 중복으로 터치가 일어나는 문제가 발생하더군요.

그래서 저는 방법을 바꿔서 사용하고 있습니다.

모든 터치는 Raycast를 사용하는 것이 아니라 캔버스를 사용하는 것으로요.

화면에 보이는 이미지나 버튼은 해당 오브젝트에 소스를 연결시켜서 터치에 대한 처리를 하면 됩니다.

하지만 이 경우 이미지나 버튼이 없는 위치는 어떻게 할 것인가에 대한 문제가 발생합니다.

그래서 캔버스의 가장 뒷쪽에 투명 이미지를 두고 이 이미지에서 Raycast에 해당하는 기능을 처리하는 것입니다.

 


 

참고로 제가 주로 사용하던 Raycast 기능은 다음과 같이 사용이 가능합니다.

 

Vector3 mouseDownPos;

RaycastHit hit;
Ray ray;

 

if (Input.GetButtonDown("Fire1"))
{

 mouseDownPos = Input.mousePosition;

 ray = Camera.main.ScreenPointToRay(mouseDownPos);

 

 if (Physics.Raycast(ray, out hit, Mathf.Infinity))

 {

  switch (hit.collider.gameObject.name)

  {

  case "ButtonMainStart":

  //처리 내용 중간 생략

  break;

  case "ButtonTabGuns":

  //처리 내용 중간 생략

  break;

  }

 }

}

 

 

캔버스에서 버튼에 대한 이벤트 처리를 할 때는 위의 그림 중 하단의 OnClick()을 활용할 수 있습니다.

하지만 저는 OnClick() 기능의 사용 대신 다른 방법을 사용하고 있습니다.

 

제가 활용 방법을 잘 몰라서 그러는지는 모르겠지만 OnClick() 기능을 활용할 경우 해당 오브젝트의 이름에 따른 처리에 문제가 있더군요.

예를 들어 버튼이 10개가 있고, 이 버튼의 이름이 각각 Button00 ~ Button09라고 할 경우 이름의 마지막 2글자의 숫자값에 따라 처리를 하고자 할 경우 약간의 문제가 있어서 제 나름대로의 다른 방법을 찾아 사용하고 있습니다.

 

제가 사용하는 방법의 소스를 보면 다음과 같습니다.

 

using UnityEngine;
using System.Collections;
using UnityEngine.UI;

public class CsButtonPetInformationPetList : MonoBehaviour {

 // Use this for initialization
 void Start ()
    {
        GetComponent<Button>().onClick.AddListener(ButtonPetInformationPetListClick);
    }
 
 // Update is called once per frame
 void Update ()
    {
 
 }

    int GetNo()
    {  
        return int.Parse(gameObject.name.Substring(gameObject.name.Length - 3, 3));
    }

    void ButtonPetInformationPetListClick()
    {
        GameObject.Find("GameManager").SendMessage("ButtonPetInformationPetListClick", GetNo());
    }

    void ButtonPetInformationPetListSet()
    {  
        int no = GetNo();       
        string strText;
        RectTransform rt = GetComponent<RectTransform>();
        Sprite newSprite;
       
        if(no <= CsManager.petHaveCount - 1)
        {
            rt.transform.localPosition = new Vector3((no % 5) * 250 - 500, (-(no / 5) * 220) - 110, 0);
           
            strText = string.Format("Common/Monster/Monster{0:000}", CsManager.mPet[CsManager.mPetList.no[no]].no);
            newSprite = Resources.Load<Sprite>(strText);
            GetComponent<Image>().overrideSprite = newSprite;

        }
        else
        {  
            Destroy(gameObject);
        }
    }
}

 

캔버스를 사용하기 위해서는 using UnityEngine.UI; 문장을 추가해 주어야 합니다.

void Start () 함수에는 이 버튼을 클릭했을 경우에 대한 이벤트 리스너를 추가해 줍니다.

이런 명령을 잘 모르신다면 위의 소스처럼만 사용하면 사용이 가능합니다.

GetComponent<Button>().onClick.AddListener(ButtonPetInformationPetListClick);

위의 문장은 버튼의 터치에 대한 이벤트 리스너를 작성한 내용입니다.

마지막의 ButtonPetInformationPetListClick는 버튼을 클릭했을 때 처리해야 되는 내용이 들어있는 함수로 위의 소스처럼 작성해 주시면 됩니다.

 

int GetNo() 함수는 오브젝트의 이름 중 마지막 3글자에 해당하는 숫자를 반환하는 함수로 버튼 클릭 시 사용하게 됩니다.

 

그리고 아래쪽의 void ButtonPetInformationPetListSet() 함수는 다른 소스 파일에서 GameObject.Find 기능을 활용해 사용할 소스를 작성해 둔 것입니다.

아래쪽의 ButtonPetInformationPetListSet() 함수 내용 중 Sprite 에 대한 내용이 나오는데요.

Sprite 기능은 캔버스에 추가한 이미지나 버튼의 이미지 파일을 변경할 때 사용하는 소스입니다.

사용 방법은 참고하시면 충분히 이해가 될 것으로 보이는데요.

strText 의 내용 중 경로를 보시면 Common/Monster 라고 된 부분이 있습니다.

이 경로는 더 정확히 얘기하면

프로젝트 경로/Assets/Resources/Common/Monster 입니다.

저의 경우 D 드라이브에 몬스터에이지(MonsterAge) 라는 폴더에 게임을 제작하고 있기 때문에 Monster000 파일의 경우 전체 경로는

D:\Unity\Project\MonsterAge\Assets\Resources\Common\Monster\Monster000.PNG 입니다.

이처럼 폴더를 사용해 이미지 파일들을 구분할 경우에는 경로명에 Resources 하위 폴더명을 적어주시면 됩니다.

 

※ 모두들 잘 아시겠지만 폴더명에는 한글이 들어가면 안된다는 점 주의하세요.

 

위의 소스 중 ButtonPetInformationPetListClick에 대한 함수 처리 내용은 GameManager라는 오브젝트에 연결되어 있는 소스 중 ButtonPetInformationPetListClick 함수를 처리하라는 뜻입니다.

ButtonPetInformationPetListClick 함수를 처리할 때 인수로 GetNo()의 값을 넘겨주는 방식입니다.

 

** 제가 유니티를 공부한지 얼마 안된 상태라서 아직 모르는게 많다보니 설명 중 부족한 부분이나 틀린 부분이 있더라도 양해 부탁드립니다. ^^

 

 


 

아래 내용은 제가 유니티 공부를 처음 시작해서 한달만에 개발한 게임을 소개 해 드립니다.

유니티 책 2권 구입해서 예제만 따라 해 보다가 책의 소스 내용을 응용해서 이런 게임도 가능하지 않을까 하는 생각을 가지

고 만들기 시작한 게임이랍니다.

 

유니티 공부를 시작한 지 1주일 정도 된 시점에서 유니티의 기본적인 명령들은 조금 파악이 된 상태였고 그 때부터 게임 기

획을 시작하면서 한달만에 완성한 게임인데요.

 

유니티로 처음 만든 게임이라서 그런지 애정이 많이 가는 게임이랍니다.

엄밀히 말하면 유니티 공부를 1주, 게임 개발 겸 유니티 공부 3주, 총 4주만에 개발한 게임이랍니다.

 

게임을 간단히 소개하겠습니다.

 

ㅇ 게임명 : 키스볼(추후 키스볼의 스테이지를 재정리해서 키스볼2를 새롭게 출시함)

 

ㅇ 게임경로 : https://play.google.com/store/apps/details?id=com.kaisersoze.kissballs2

 

※ 게임 검색 : 구글플레이에서 "키스볼2"로 검색(안드로이드 버전만 출시함)

 

ㅇ 게임방법

 

1. 파란볼과 빨간볼이 만나면 성공하는 게임

2. 화면 아무곳이나 클릭하면 볼이 무제한으로 생성되도록 구현되어 있음

3. 화면에 다양한 장애물이 있으며 장애물은 색 및 모양으로 구분됨

4. 볼들은 색으로 구분되며, 무게 및 다른 물체에 부딪혔을 때 튕기는 반사력에 차이가 있음

 

ㅇ 기타

- 구글 리더보드를 이용해서 성공한 스테이지의 갯수를 비교할 수 있음

- 동영상 녹화기능도 추가했었으나 게임에 방해가 되는 것 같아서 현재 버전에서는 제거함

- 5분 이상 게임을 지속한 상태에서 성공 또는 실패 시 애드몹(구글 광고) 광고가 노출됨(수익은 거의 없음 ㅠㅠ)

 

아래에 게임 동영상을 올려드리니 동영상 감상하시고 재미있겠다 싶으시면 설치해서 재미있게 즐겨보시기 바랍니다.
그외에도 자이로센서 데이터를 이용해 우주선을 격파하는 게임(알파포스 AR) 및 마방진 등 몇 개의 게임을 더 개발했답니다

.

(알파포스AR, 마방진 프리미엄, 러버볼 등)

 



댓글