프로그램시, 접근 범위를 결정하는 접근 제한자에 대해 정리해보려 한다. 


접근 제한자에는 public, protected, internal, private가 있다. 


네 가지의 접근 제한자에 대해 알아보려고 합니다. 아래는 4개의 접근 제한자를 정리해놓은 표입니다.


private


클래스 내부에서만 접근이 가능하다.


public 


모든 곳에서 접근이 가능하다.


internal


같은 어셈블리에서만 public으로 접근이 가능하다. 


protected


클래스 외부에서는 기본적으로 접근할 수 없으나 파생 클래스(자식 클래스)에서는 접근이 가능하다.


protected internal 


같은 어셈블리에서만 protected으로 접근이 가능합니다. 

 

주의할 점은 아무것도 선언하지 않는다면 기본적으로 private로 인식하게 된다.


internal때문에 이것을 검색하게 되었는데...


어셈블리는 즉, 해당 프로젝트 내와 같은 의미라고 할 수 있다.

Posted by sungho88
,

C# 스크립트에서 변수를 여러 개 선언하면,


유니티에서 Inspector내 스크립트에 줄줄이 나온다.

(물론 public으로 선언했을 경우)


그런데 이 변수가 어떤 기능을 하는 것인지 기억이 안나 스크립트에서 코드를 다시 볼때가 있다.


이런 것을 방지하기 위해 유니티에서는 Tooltip이라는 기능을 제공한다.



[Tooltip("이것은 넘버1이다.")]
    public GameObject number01;

이렇게 작성하면,

 

이렇게 마우스를 갖다대면 설명이 나온다.


그래서 스크립트로 돌아가서 확인하지 않아도 되므로 요긴하게 사용될 수 있다.


물론, 원하는 변수에만 작성해서 사용할 수 있다. 

Posted by sungho88
,

초기화를 하지 않았든지 어떤 상황에서는 null이 발생할 가능성이 크다.


그래서 책들을 보면 널 체크를 반드시 해줘야한다는 내용을 종종 본다.


널 체크는 간단하지만 중요하다.


널 체크 방법은 다음과 같다.


Image myImage; 선언을 할테고...


체크할 때,

if (myImage != null)

   XXXXXXXXX


도 물론 가능하지만,


더욱 간단하게 체크할 수도 있다.


if (myImage)

   XXXXXXXXX


이렇게 해도 된다. 


주의할 점은 null이라면, 이 아니라 null이 아니라면 이 조건값이다.


따라서 null일때 뭔가를 해주고 싶다면


부정연산자 !를 붙여서


if (!myImage)

   XXXXXXXXX


로 작성해야 에러가 발생하지 않는다.


Posted by sungho88
,

유니티에서 쿨타임(쿨다운?) 기능을 사용하려고 한다.


RPG 게임에서 어떤 스킬을 사용했을 때, 


사용 후 일정 시간동안 못 쓰게 되고 일정 시간이 지난 후 다시 사용할 수 있게 된다.


[사용 방법]


하나 예제를 만들어보자..


Canvas - UI - Button으로 버튼을 생성한다.


Button을 클릭해보면, Image와 Button 컴포넌트가 기본적으로 만들어진것을 볼 수 있다.


- Image 컴포넌트


Source Image를 통해 버튼의 이미지 모양을 원하는대로 바꿀 수 있다. 

(Sprite 타입 이미지만 사용 가능)


버튼 이미지를 설정 후 Image Type을 Filled로 바꾸면 하위 항목이 다음과 같이 나온다.


여기서 Fill Amount 슬라이더가 생기는데, 


이 슬라이더 값을 0에서 1로 조절하면 버튼 이미지가 이에 따라 채워지는 영역이 변한다. 


이 값을 업데이트 해주면 쿨타임 버튼이 되는 것이다.


참고로,  


Fill Method를 통해 쿨타임의 형태를 바꿀 수 있고,

Fill Origin을 통해 쿨타임의 시작점(원점)을 바꿀 수 있다.


<Fill Method>

  1. Horizontal : 수평으로 쿨타임 적용. 
  2. Vertical : 수직으로 쿨타임 적용.
  3. Radial 90 : 90도로 쿨타임 적용.
  4. Radial 180 : 180도로 쿨타임 적용.
  5. Radial 360 : 360도로 쿨타임 적용.
Fill Origin은 어디서 쿨타임이 시작될 것인지 지정하는 것인데, 위 5가지에 따라 달라진다.


Fill Amount 슬라이더 값을 움직여보면 버튼이 사라지는 것을 볼 수 있다.


이것은 배경은 자동으로 만들어지지 않기 떄문에 사라지는 것처럼 보인다.


즉, 버튼 뒤에 동일한 위치에 배경을 깔아줘야한다.


그리고, Color를 원하는 색상으로 설정해보자. 다음과 같이 된다.




참고로, 빨간 배경을 버튼 위에 놓아야한다.


왜냐하면 Canvas 안에서는 순서대로 겹쳐서 쌓이는 계층구조이므로


빨간 배경이 버튼보다 아래 위치하면 빨간색이 보여지게 된다.


이제 게임 도중에 값을 변화하도록 스크립트를 작성해보자.


Create > C# Script로 스크립트를 하나 생성한다. 이름은 CoolTimeScript.cs로 생성했다.


[CoolTimeScript.cs]


public class CoolTimeScript : MonoBehaviour {
    public Image image;
    public Button button;
    public float coolTime = 10.0f;
    public bool isClicked = false;
    float leftTime = 10.0f;
    float speed = 5.0f;
    
    // Update is called once per frame
    void Update () {

        if(isClicked)
            if (leftTime > 0)
            {
                leftTime -= Time.deltaTime * speed;
                if(leftTime < 0) {
                    leftTime = 0;
                    if(button)
                        button.enabled = true;
                    isClicked = true;   
                }

                float ratio = 1.0f - (leftTime / coolTime);
                if(image)
                    image.fillAmount = ratio;
            }
    }

    public void StartCoolTime() {
        leftTime = coolTime;
        isClicked = true;
        if(button)
        button.enabled = false// 버튼 기능을 해지함.
    }
}



다음과 같이 작성한다.


유니티 On Click에서 버튼을 눌렀을 때 StartCoolTime()을 실행시키도록 하고,


Image와 Button은 버튼에 동일한 위치에 존재하는 컴포넌트를 집어넣어 주면 된다.

speed를 통해 쿨타임 시간을 조절할 수 있다.






Posted by sungho88
,

가장 간단한 방법으로는 


        transform.Rotate();

을 사용하면 된다.
 
이 스크립트를 회전시키고자 하는 게임오브젝트에 컴포넌트로 붙여주면 된다.

코드는 다음과 같다.

public float turnSpeed = 10;

    // Update is called once per frame
    void Update () {
transform.Rotate(Vector3.forward, turnSpeed * Time.deltaTime);
    }





Posted by sungho88
,

유니티 3D와 2D의 차이점이 무엇인지 궁금해서


각각의 프로젝트를 따로따로 생성해본 뒤, 캡쳐를 해서 비교해봤다.


생성 직후,


유니티 3D에는 빛(Directional Light)이 초기에 생성되어 있었지만, 2D에는 카메라 1개만 생성되어 있었다.


또한, 메인카메라(MainCamera) 모드에도 차이가 있었다.


유니티를 2D로 프로젝트 생성시, MainCamera 초기 화면


유니티를 3D로 프로젝트 생성시, MainCamera 초기 화면



Projection


- orthographic : 카메라가 퍼스펙티브에 상관없이 객체를 균일(uniform)하게 렌더링한다.

- perspective  : 카메라는 퍼스펙티브를 그대로 놔둔 채로 객체를 렌더링한다.



2D를 만들 것인데 3D 프로젝트를 만들었다면,,


Clear Flags 를 Solid Color로 바꿔주고, Projection만 바꿔준다면 2D 환경으로 변환할 수 있다. 

Posted by sungho88
,

유니티 화면에서 버튼을 한 번 누를때마다 게임오브젝트를 하나씩 화면서 랜덤한 위치에서 생성하려고 한다.


먼저 게임오브젝트를 동적으로 생성하는 것은 이 블로그를 참조했다.


Instantiate와 Destroy 함수 사용하기


생성하는 것은 Instantiate()함수를 사용한다고 한다. 


그런데 어떻게 화면의 랜덤한 위치에 게임 오브젝트를 생성할까?


먼저, 랜덤 함수를 사용하기 위해 Random.Range(min,max)를 사용한다.


그럼, 화면의 크기를 어떻게 구할까?


만약, 개발 환경이 800 * 1280 해상도라고 


float randomX = Random.Range(0f, 800f); //적이 나타날 X좌표를 랜덤으로 생성해 줍니다.
float randomY = Random.Range(0f, 1280f); //적이 나타날 X좌표를 랜덤으로 생성해 줍니다.


로 한다면.


x축으로 0에서 800 사이의 난수,

y축으로 0에서 1280 사이의 난수가 나오게 된다.


그 밑에 


GameObject enemy = (GameObject)Instantiate(obj, new Vector3(randomX, randomY, 0f),
Quaternion.identity);



위 링크에서 보듯, 


첫 번째 파라미터에 복제(clone)할 프리팹 객체를 obj 위치에 넣고


두 번째 파라미터에 생성될 오브젝트의 위치,


세 번째에 회전인데 없으므로 기본인 Quaternion.identity 을 작성하면 된다.


Posted by sungho88
,

[UGUI 배경]


기존에는 유니티 안에서 GUI 개발 환경이 형편없고, 사용하기 불편해서


NGUI라는 유료 플러그인을 사용하여 GUI를 개발을 했다.


그래서 유니티에서는 NGUI 개발자를 불러들여 유니티 내 GUI 시스템을 대폭 업그레이드 시켰고,


Unity 버전 4.6부터 새로운 GUI를 출시했다.


이로써, 공식 명칭은 아니지만 UGUI라 불리는 GUI 시스템이 유니티 내에서 사용되기 시작했다.


UGUI(Unity Graphical User Interface)


UGUI에 대해 알아보려고 한다.


참고 사이트는 당연히 유니티 공식 홈페이지 - 자습서 내용이다.



캔버스(Canvas)


- Canvas는 Unity에서 모든 UI 객체를 렌더링을 관리하기 위한 루트 컴포넌 트이다.


- 즉, 유니티에서 사용하는 모든 UI 구성 요소들은 모두 캔버스 밑에 위치한다.(캔버스의 자식이다.)


- 캔버스를 생성하는 것을 잊더라도, UI 요소 중에 하나를 생성하면 Canvas는 자동으로 생성된다.


-  한 씬(Scene)에서 캔버스를 여러개 생성할 수 있다.


- 캔버스 영역이 씬 뷰에서 사각형으로 나타나므로 게임 뷰에서 보지 않아도 UI를 쉽게 배치할 수 있다.


- .캔버스(Canvas)에 있는 UI 요소는 계층 구조에 나타나는 것과 동일한 순서이다.

   즉, 겹겹이 쌓이게 되므로, 첫 번째 있는 UI가 두 번째 UI에 가려져 보이지 않게 된다.

   변경을 하고 싶다면 드래그하여 계층 구조에서 위,아래 순서를 변경하면 된다.


- 캔버스에는 기본적으로 4가지의 컴포넌트가 포함되어 있다.


1. Rect Transform

2. Canvas

3. Canvas Scaler

4. Graphic Raycaster


- 캔버스에는 스크린 공간 또는 월드 공간에 렌더링하기 위해 Render Mode가 세 종류 존재한다.


[Render Mode]


1) 스크린 공간(Screen Space - Overlay)


가장 기본이 되는 모드로, 따로 설정하지 않으면 이 모드로 설정된다.

이 렌더 모드에서는 모든 UI 요소가 해당 씬에서 다른 모든 것 위에 렌더링된다. 

이 모드에서 캔버스는 자동으로 스크린을 채우고, 스크린 설정이 변하면 자동으로 크기를 조정한다.

스크린의 크기가 조절되거나 해상도가 변경되면 캔버스는 여기에 맞춰 자동으로 크기를 변경한다.

이 모드에서는 Rect Transform를 통해 직접 편집하는 것은 불가능하다.

캔버스가 Rect Transform을 설정해 자동으로 스크린을 채운다.


Pixel Perfact  

선택하면 UI 엘리먼트는 렌더링될 때 가장 가까운 픽셀로 조정된다.


2) 스크린 공간(Screen Space - Camera)


이 모드는 Screen Space - Overlay와 매우 유사하지만 
이 렌더 모드에서는 캔버스가 씬의 특정 Camera 에서 주어진 거리만큼 앞쪽에 위치한다.
UI 요소는 이 카메라에 의해 렌더링된다. 즉 카메라 설정이 UI의 모습에 영향을 준다. 
카메라가 Perspective 으로 설정되어 있으면 UI 요소는 원근감이 있게 렌더링되며,
원근 왜곡의 정도는 카메라 Field of View 에 의해 조절될 수 있다. 
스크린의 크기가 조절되거나 해상도가 변경되거나 카메라가 변경되면 캔버스 역시 여기에 맞춰 
자동으로 크기를 변경한다.

3)월드 공간(World Space)


이 렌더 모드에서는 캔버스는 씬에 있는 다른 게임오브젝트처럼 동작한다.

캔버스의 크기는 사각 트랜스폼(Rect Transform)을 사용하여 수동으로 설정할 수 있으며,

(위 두 개는 수동 설정 불가)

UI 요소는 3D 배치에 기반하여 씬의 다른 오브젝트의 앞 또는 뒤에 렌더링된다.

이 방식은 월드의 일부를 이루도록 의도된 UI에 유용하다. 

그래서 이 방식을 “서사적 인터페이스”라고도 부르기도 한다.

Posted by sungho88
,
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;

public class Drag : MonoBehaviour, IDragHandler
{

float distance = 10.0f;
public void OnDrag(PointerEventData eventData)
{
Vector3 mousePosition = new Vector3(Input.mousePosition.x,
Input.mousePosition.y, distance);
transform.position = mousePosition;
}

}


1. 드래그를 하기 위해서는 OnMouseDrag() 함수도 있지만, OnDrag() 함수를 사용할 수도 있다.

2. 먼저, OnDrag()를 사용하기 위해서는 


using UnityEngine.EventSystems; 


을 적어줘서 이벤트 시스템을 사용하겠다는 것을 표기한다.


3. MonoBehaviour뒤에 콤마(,)를 쓴 뒤 IDragHandler를 작성한다. 참고로 IDragHandler 는 인터페이스이다.


4. 3번 IDragHandler를 적으면 에러난다. 즉, 인터페이스에 선언된 메소드를 정의해줘야한다.

형태는 다음과 같다. public void OnDrag(PointerEventData eventData)


5. OnDrag()안에 드래그 했을 때, 일어날 동작들을 적으면 된다. 

이 블로그에서는 마우스 드래그하는데로 오브젝트가 딸려오는 것을 구현하려고 한다.


위와 같이 하면 되는데,


마우스는 평면으로 움직이므로 x,y)축만 필요하다.


z축은 위와 같이 10으로 지정해줘도 되고, 그냥 오브젝트의 z축을 그냥 기입해줘도 된다.


그 다음에 transform.position에 mousePosition을 넣음으로써,


드래그할때 mousePosition이 게임오브젝트 위치에 대입되어 마우스 드래그할때 오브젝트가 딸려 움직이게 된다.


이상으로 마우스 드래그를 이용하여 게임오브젝트를 움직이는 방법을 알아보았다.



Posted by sungho88
,

게임 오브젝트를 움직이는 작업을 하다보면, 


화면을 벗어나 우주 공간처럼 끝없이 가게 되는 것을 볼 수 있다.


이때, 화면안에 있도록 제한을 해줘야 하는데 가장 간단하게 구현할 수 있는 것이 바로


Camera.main.WorldToViewportPoint 를 사용하는 것이다.


Transforms position from world space into viewport space.

Parameters:

position:
Vector3 Camera.WorldToViewportPoint(Vector3 position)



바로 카메라(Camera).WorldToViewportPoint(pos)로 써도 되지만, Camera.main을 쓰는 이유는


MainCamera라는 태그(Tag)가 붙은 첫번째 활성화된 카메라를 불러온다는 뜻이다.


즉, 유니티 프로젝트 생성시 만들어지는 main카메라를 사용하겠다는 의미이다.


WorldToViewportPoint(현재 위치)의 경우 position을 월드 공간에서 뷰포트 공간으로 변경시킨다.


카메라의 좌측 하단은 (0,0 , 0.0)이며, 우측 상단은 (1.0 , 1.0)이다. 


또한, z position은 카메라로부터의 거리를 월드 단위로 환산한 값이다.


따라서,


       Vector3 pos = Camera.main.WorldToViewportPoint(transform.position);

            if (pos.x < 0f) pos.x = 0f;
if (pos.x > 1f) pos.x = 1f;
if (pos.y < 0f) pos.y = 0f;
if (pos.y > 1f) pos.y = 1f;

        transform.position = Camera.main.ViewportToWorldPoint(pos);


이렇게 하면, 현재 위치(transform.position)를 pos 변수에 대입하고,


pos.x < 0f 라면 왼쪽 화면 밖으로 나갔다는 의미이므로 아무리 왼쪽으로 이동해도 0.0f

 

pos.x > 1f 라면 오른쪽 화면 밖으로 나갔다는 의미이므로 아무리 오른쪽으로 이동해도 1.0f 


pos.y < 0f 라면 아랫쪽 화면 밖으로 나갔다는 의미이므로 아무리 아래쪽으로 이동해도 0.0f 


pos.y > 0f 라면 윗쪽 화면 밖으로 나갔다는 의미이므로 아무리 윗쪽으로 이동해도 0.0f 


로 조건을 줘서 화면 안에서 못 벗어나게 한다.


그 다음에 다시 뷰포트 공간에서 월드 공간으로 변경시킨 뒤, 현재 위치에 넣으면 된다.


이렇게 한 뒤, 게임을 실행해보면 


드래그를 방향키를 아무리 눌러도 화면을 벗어나지 않고 모서리까지만 가는 것을 볼 수 있다.


ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ


뷰포트 ?

월드 좌표 ??

로컬 좌표 ???

ViewportToWorldPoint ???

WorldToViewportPoint ?????

ScreenToWorldPoint    ???????


카메라 관련 용어 및 개념을 좀 더 익혀야겠다..


Posted by sungho88
,