반응형

C# 문자열

문자열은 일련의 문자로 구성되며, 각 문자는 0부터 시작하는 인덱스 값으로 참조할 수 있다.

예를 들어, "Hello"라는 문자열이 있다면 'H'는 인덱스 0, 'e'는 인덱스 1과 같은 방식이다.

 

또한, C#에서는 IndexOfSubstring이라는 두 가지 유용한 문자열 메소드를 제공한다.

IndexOf 메소드는 특정 문자나 문자열이 처음으로 출현하는 인덱스를 반환한다.

만약 해당 문자나 문자열이 존재하지 않는다면 -1을 반환한다. 아래 예시를 살펴보자.

 

예시:

string str = "Hello World";
int index = str.IndexOf('W'); // index는 6이 됩니다.

Substring 메소드는 문자열의 특정 부분을 추출하는 데 사용된다.

이 메소드는 두 가지 형태가 있다. 하나는 시작 인덱스만 지정하는 것이고,

다른 하나는 시작 인덱스와 길이를 모두 지정하는 것이다.

 

예시:

string str = "Hello World";
string sub = str.Substring(6); // sub는 "World"가 된다.
string sub2 = str.Substring(0, 5); // sub2는 "Hello"가 된다.

이러한 메소드들은 문자열을 다루는 데 있어 매우 중요하므로 잘 기억해두는 것이 좋다.

C# If 문

C#에서 if문은 주어진 조건이 참인 경우에만 코드 블록을 실행한다.
그런데 여러 조건을 확인해야 할 경우에는 if, else if, else 구조를 사용한다.


이 구조에서 if 문 다음에 오는 else if 문은 이전의 ifelse if 문의 조건이 거짓일 때만 확인된다.
그리고 else 문은 앞선 모든 조건이 거짓일 경우에 실행된다.

if (condition1)
{
    // 조건1이 참일 때 실행
}
else if (condition2)
{
    // 조건1이 거짓이고, 조건2가 참일 때 실행
}
else
{
    // 모든 조건이 거짓일 때 실행
}

또한 C#에서는 삼항 연산자를 사용하여 if-else 문을 간단하게 표현할 수 있다.
삼항 연산자는 "조건 ? 값1 : 값2"와 같은 형태로, 조건이 참일 경우 값1을, 거짓일 경우 값2를 반환한다.

var result = (condition) ? "참일 때의 값" : "거짓일 때의 값";

C# Switch문 정리

  • switch 문의 작동 원리: 주어진 조건에 따라 여러 코드 블록 중 하나를 실행.
  • break 키워드: switch 블록에서 더 이상의 코드 실행이나 케이스 테스트를 중단.
  • default 키워드: 모든 케이스와 일치하지 않을 때 실행될 코드를 지정.

예시코드

int day = 4; // 예를 들어, 오늘은 목요일
switch (day)
{
    case 1:
        Console.WriteLine("Monday");
        break;
    case 2:
        Console.WriteLine("Tuesday");
        break;
    case 3:
        Console.WriteLine("Wednesday");
        break;
    case 4:
        Console.WriteLine("Thursday"); // day 4에 해당하므로 "Thursday"가 출력.
        break;
    case 5:
        Console.WriteLine("Friday");
        break;
    case 6:
        Console.WriteLine("Saturday");
        break;
    case 7:
        Console.WriteLine("Sunday");
        break;
    default:
        Console.WriteLine("Looking forward to the Weekend."); // 일치하는 케이스가 없을 때 출력.
        break;
}
반응형
반응형

C# 타입 캐스팅

C#에는 두 가지 유형의 타입 캐스팅이 있다. 암시적 캐스팅과 명시적 캐스팅이다.

 

Implicit Casting(암시적 캐스팅) 

더 작은 크기의 유형을 더 큰 크기의 유형으로 전달할 때 암시적 캐스팅이 자동으로 수행한다.Automatic casting이라고도 한다.

예시:

int myInt = 9;
double myDouble = myInt;       // Automatic casting: int to double

Console.WriteLine(myInt);      // Outputs 9
Console.WriteLine(myDouble);   // Outputs 9

Explicit Casting(명시적 캐스팅)

명시적 캐스팅은 값 앞에 괄호 안에 유형을 배치하여 수동으로 수행한다.Manual casting이라고도 한다.

예시:

double myDouble = 9.78;
int myInt = (int) myDouble;    // Manual casting: double to int

Console.WriteLine(myDouble);   // Outputs 9.78
Console.WriteLine(myInt);      // Outputs 9

Type Conversion Methods(유형 변환 방법)

Convert.ToBoolean, Convert.ToDouble, Convert.ToString, Convert.ToInt32(int)Convert.ToInt64(long)와 같은 내장 메서드를 사용하여 명시적으로 데이터 형식을 변환한다.

예시:

int myInt = 10;
double myDouble = 5.25;
bool myBool = true;

Console.WriteLine(Convert.ToString(myInt));    // convert int to string
Console.WriteLine(Convert.ToDouble(myInt));    // convert int to double
Console.WriteLine(Convert.ToInt32(myDouble));  // convert double to int
Console.WriteLine(Convert.ToString(myBool));   // convert bool to string
  • 변환이 왜 필요한가? : 유형 변환이 필요한 경우는 많지 않다고 한다. 사용자 입력 등에서 작업할 때 사용되기도 한다. 아래 예시를 살펴보자.
Console.WriteLine("Enter your age:");
int age = Convert.ToInt32(Console.ReadLine()); // string으로 입력받은 값을 Int로 변환 후 age에 할당
Console.WriteLine("Your age is: " + age);

매개변수

Parameter(매개변수) & Arguments(인수)

  1. Parameter(매개변수) : 매개변수는 메소드 내에서 변수 역할을 한다. 원하는 만큼 추가 할 수 있고, 쉼표로 구분한다.
  2. Arguments(인수) : 매개변수가 메소드에 전달되면 이를 인수라고 한다.

예시:

static void MyMethod(string fname) // fname == Parameters
{
  Console.WriteLine(fname + " Refsnes");
}

static void Main(string[] args)
{
  MyMethod("Liam"); // Liam and 2 others == Arguments
  MyMethod("Jenny");
  MyMethod("Anja");
}

Multiple Parameters(다중 매개변수)

static void MyMethod(string fname, int age) // 두 개의 매개변수
{
  Console.WriteLine(fname + " is " + age);
}

static void Main(string[] args)
{
  MyMethod("Liam", 5);
  MyMethod("Jenny", 8);
  MyMethod("Anja", 31);
}

Default Parameter Value(기본 매개변수 값)

등호(=)를 사용하여 기본 매개변수 값을 사용한다.

static void MyMethod(string country = "Norway")
{
  Console.WriteLine(country);
}

static void Main(string[] args)
{
  MyMethod("Sweden");
  MyMethod("India");
  MyMethod(); // 매개변수를 지정해주지 않았으므로 Norway가 출력된다.
  MyMethod("USA");
}

// Sweden
// India
// Norway
// USA

Return Values(반환값)

메소드가 값을 반환하도록 하려면 void 대신 기본 데이터 유형(예: int 또는 double)을 사용하고 메소드 내부에서 return 키워드를 사용한다.

static int MyMethod(int x)
{
  return 5 + x;
}

static void Main(string[] args)
{
  Console.WriteLine(MyMethod(3));
}

// Outputs 8 (5 + 3)

반환값을 변수에 저장 하는 것도 가능하다.

static int MyMethod(int x, int y)
{
  return x + y;
}

static void Main(string[] args)
{
  int z = MyMethod(5, 3);
  Console.WriteLine(z);
}

// Outputs 8 (5 + 3)

Named Arguments

key: value 구문을 사용하여 인수를 보내는 것도 가능하다.

static void MyMethod(string child1, string child2, string child3)
{
  Console.WriteLine("The youngest child is: " + child3);
}

static void Main(string[] args)
{
  MyMethod(child3: "John", child1: "Liam", child2: "Liam");
}

// The youngest child is: John

Method Overloading

메소드 오버로딩을 사용하면 여러 메소드가 서로 다른 매개변수를 사용하여 동일한 이름을 가질 수 있다.

static int PlusMethod(int x, int y)
{
  return x + y;
}

static double PlusMethod(double x, double y)
{
  return x + y;
}

static void Main(string[] args)
{
  int myNum1 = PlusMethod(8, 5);
  double myNum2 = PlusMethod(4.3, 6.26);
  Console.WriteLine("Int: " + myNum1);
  Console.WriteLine("Double: " + myNum2);
}
반응형
반응형

플레이어의 체력을 관리하는 스크립트 'PlayerHealthController'

플레이어의 체력과 관련된 기능을 관리하는 PlayerHealthController라는 스크립트에 무적 상태를 구현했습니다.

먼저 float 타입의 변수 invincibleLength와 invincibleCounter를 선언했습니다.

invincibleLength에는 무적 상태가 유지되는 시간을 할당하고,

invincibleCounter에는 무적 상태가 유지된 시간을 관리할 것입니다.

 

자세히 보시면 invincibleLength의 경우 public으로 선언되어 있고

invincibleCounter는 private으로 선언되어 있습니다.

invincibleLength 변수는 인스펙터창에서 값을 설정할 수 있어야 하기 때문에 public으로 선언하였습니다.

DealDamge함수 내에서 무적 상태가 유지되는 시간(invincibleLength)를

무적 상태가 유지되는 시간(invincibleCounter)에 할당했습니다.

저는 유니티 에디터에서 invincibleLength에 1이라는 값을 할당해둔 상태입니다.

즉 무적 상태가 유지되는 시간은 1초입니다.

 

왜 1초인가 하면

프레임마다 호출되는 Update 함수 내에서

invincibleCounter값에서 Time.deltaTime만큼의 시간을 빼주고 있기 때문입니다.

 

Time.deltaTime은 이전 프레임과 현재 프레임 사이의 시간 간격을 나타냅니다.

만약 플레이 환경이 초당 프레임이 60이라면(1초에 60번 화면이 업데이트)

1프레임과 1프레임 사이의 간격은 1초를 60으로 나눈 값이 될 것입니다.

 

즉, invincibleCounter에 할당된 1이라는 값(invincibleLength에 할당된 값)에서

1초를 60으로 나눈 값을 매 프레임마다 빼는 것입니다.

정리해보겠습니다.

 

1. 60FPS = 1초에 화면이 60번 업데이트 된다는 뜻

2. 1프레임 마다 1/60초를 1초에서 뺌.

3. 그럼 2번 과정이 1초에 60번 실행됨. 

4. 1초가 지나면 invincibleCounter의 값은 0에 수렴함.

 

invincibleCounter값이 0보다 크다면 프레임마다 1/60초를 빼줍니다.

invincibleCounter값이 0이하인 경우 1이라는 값(invincibleLength)을 넣어 줌으로써

캐릭터의 체력이 떨어지는 함수인 DealDamage가 실행되지 않습니다.

반응형
반응형

유니티에서 배경을 활용하는 방법은 매우 다양할 것입니다.

저는 오늘 2D플랫포머 게임을 만드는 과정에서

MainCamera 오브젝트와 스크립트를 사용하여,

배경을 재활용하는 방법에 대해 정리해보고자 합니다.

 

만드는 게임의 배경과 오브젝트들

제가 따라 만들고 있는 게임에서 배경은 2가지입니다.

우측 하이어라키창에 Background의 자식 오브젝트인 Far와 Middle입니다.

Far는 좌측 사진에서 빨간 네모 안의 하늘이미지, Middle은 빨간 네모 안의 수풀 이미지입니다.

 

CameraController라는 스크립트를 보면서

카메라와 배경이 플레이어를 따라다니도록 구현하는 코드들을 살펴보겠습니다.

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

public class CameraController : MonoBehaviour
{

    public Transform Player;
    public Transform farBackground, middleBackground;

    public float minHeight, maxHeight;
    public float cameraSpeed;

    private Vector2 lastPos;

    void Start()
    {
        lastPos = transform.position; // 카메라의 초기 위치를 저장합니다.
    }

    void Update()
    {	// 플레이어가 y축으로 움직일 때, 카메라를 범위 내에서 제한합니다.
        float clampedY = Mathf.Clamp(Player.position.y, minHeight, maxHeight); 
        
        // 카메라의 위치를 플레이어와 같은 위치로 맞춥니다.
        transform.position = new Vector3(Player.position.x, clampedY, transform.position.z); 
        
		// 카메라가 움직인 만큼 배경 이미지를 움직입니다.
        Vector2 amountToMove = new Vector2(transform.position.x - lastPos.x, transform.position.y - lastPos.y);
        
		// 먼 배경 이미지를 카메라와 같은 속도로 움직입니다.
        farBackground.position += new Vector3(amountToMove.x, amountToMove.y, 0f); 
        // 가까운 배경 이미지를 카메라와 같은 속도로 움직입니다.
        middleBackground.position += new Vector3(amountToMove.x, amountToMove.y, 0f); 
        
        // 카메라의 현재 위치를 저장합니다.
        lastPos = transform.position; 

    }
}

CameraController스크립트는 main camera 오브젝트에 컴포넌트 형태로 추가했습니다.

하나하나 뜯어서 살펴보겠습니다.

Transform 타입의 변수 3개(Player, farBackground, middleBackground는 public으로 선언되어 있습니다.

awake나 start와 같은 생명주기 함수에서 초기화하지 않고,

인스펙터 창에서 오브젝트를 할당해 초기화를 진행해 주었습니다.

 

Player변수에는 카메라가 따라다닐 Player 오브젝트를 할당했습니다.

farBackground와, middleBackground 변수에는 두 배경을 할당했습니다.

float minHeight변수와 maxHeight변수에는 카메라가 플레이어를 따라

수직이동을 하는 과정에서 한계선 지정을 위해 선언한 것입니다.

예를 들어, 플레이어가 낮은 지형으로 이동할 경우

빨간 박스 안에 땅 바깥의 부분이 게임창에 보일 수 있습니다.

반대로 너무 높이 점프하거나, 높은 지형에서는 하늘 바깥의 검은색 부분이 보일 수도 있습니다.

이를 방지하기 위해 높이의 한계선을 만들어 준 것입니다.

매 프레임마다 실행되는 생명주기 함수인 Update함수의 내부를 살펴보겠습니다.

먼저 float타입의 clampedY입니다.

Mathf.Clamp함수가 사용되었는데요.

Mathf.Clamp함수는 총 3개의 매개변수를 갖습니다.

첫 번째는 반환될 값, 두 번째는 최솟값, 세 번째는 최댓값입니다.

즉, Player 오브젝트의 Y좌표 중에서 minHeight, maxHeight에 속하는 값만 clampedY 변수에 할당됩니다.

 

transfrom.position은 카메라의 위치입니다.

매 프레임마다 카메라의 위치에 Player의 x좌표, clampedY에 할당된 Player의 y좌표가 더해집니다.

 

Vector2 타입의 amounToMove 변수에는

카메라가 얼마나 이동했는지 계산한 값이 할당됩니다.

 

Start함수는 생명주기함수로써 게임이 실행된 후 1번만 실행됩니다.

함수 안에는 latsPos라는 변수 안에 카메라의 위치가 할당된 것을 확인할 수 있습니다.

프레임마다 카메라의 위치를 추적하고, 그 위치에서 초기에 선언한 lastPos를 빼면 이동한 거리가 나옵니다.

카메라가 이동한 거리를 배경의 위치에도 더해주게 되면, 배경도 카메라와 함께 플레이어를 쫓게 됩니다.

마지막으로 lastPos 값에 카메라의 현재 위치를 할당하면서,

프레임 사이에 카메라가 플레이어를 쫓아 얼마큼 이동했는지 알 수 있습니다.

 

이렇게 하면 배경 오브젝트를 수없이 생성하지 않아도,

게임 화면에서는 배경이 무한히 반복되는 것처럼 보이게 할 수 있습니다.

반응형
반응형

출처 : 프로그래머스

정리하자면, 두 정수(a, b)를 입력받고, 그것들을 두 번 붙인다.(ab, ba)

그중에서 더 큰 수를 출력하는 문제다.

입출력 예를 보면 이해하기 쉽다.

 

나의 풀이

using System;

public class Solution {
    public int solution(int a, int b) {
        int answer = 0;
       
        // 두 정수를 문자열로 더한 후 Int형 변수에 할당
        int str1 = Int32.Parse(a.ToString() + b.ToString());
        int str2 = Int32.Parse(b.ToString() + a.ToString());

        return answer;
    }
}

1. 먼저 입력받은 두 정수를 ToString함수를 이용해 각각 더했다. (ab 한 번, ba 한 번)

2. Int32.Parse함수로 덧셈식을 감싸서 String타입의 값을 Int 형으로 변환했다.

3. 변환된 값을 각각 Int형인 str1, str2 변수에 할당했다.

 

조건식

using System;

public class Solution {
    public int solution(int a, int b) {
        int answer = 0;
        // 두 정수를 문자열로 더한 후 Int형 변수에 할당
        int str1 = Int32.Parse(a.ToString() + b.ToString());
        int str2 = Int32.Parse(b.ToString() + a.ToString());
        
        // 조건식
        if(str1 > str2){
            answer = str1;
            }
        else if(str1 < str2){
            answer = str2;
            }
        else{
            answer = str1;
        }
        return answer;
    }
}

1. 첫 번째는 str1이 str2보다 큰 경우 answer 변수에 st1을 할당한다.

2. str1이 str2보다 작다면 answer 변수에 str2를 할당한다.

3. 이도 저도 아닌 경우(둘이 같은 경우)라면 answer 변수에 str1을 할당한다.

반응형
반응형

Player의 Rigidbody2D 컴포넌트 화면

유니티에서는 캐릭터의 기본적인 물리 기능을 구현할 때 Rigidbody라는 컴포넌트를 사용합니다.

컴포넌트라는 것은 유니티의 게임 오브젝트에 다양한 기능을 구현하게 만들어 주는 부품이라고 보시면 됩니다.

 

화면에 파란색 텍스트로 되어있는 Collision Detection이라는 것이 보이시나요?

이 설정값에 따라 오브젝트 간 충돌을 검사하는 방식이 달라집니다.

설정값은 Discrete(이산)과 Continuous(연산)이 있습니다.

 

이산(Discrete)

착지과정에서 땅에 발이 들어간 모습

이산 충돌 검사의 경우 Rigidbody2D가 적용된 오브젝트의 위치를 미리 예측합니다.

때문에 빠르게 움직이거나, 작은 물체 간의 충돌검사에서는 정확하지 않을 수 있습니다.

위 사진은 점프 후 착지 상태를 캡처한 것입니다.

 

연산(Continuous)

정상적으로 착지된 모습

연산 충돌 검사의 경우 이동하면서 생기는 충돌을 비교적 정확하게 검사합니다.

정교한 충돌 감지를 원한다면 Collision Detection 옵션을 Continuous로 설정해 주시면 되겠습니다.

 

 

 

 

반응형
반응형

게임 화면

레이어의 역할

 

유니티에서 Sorting Layer와 Order in Layer는

게임 오브젝트들이 화면상에서 어떻게 그려질지 결정하는 데에 사용됩니다.

위 그림은 2D게임의 한 장면입니다.

이미지 자체가 원근감을 주기도 하지만 레이어가 따로 설정되어 있습니다.

포토샵의 레이어와 비슷한 개념이라고 생각하셔도 좋을 거 같아요.

 

Sorting Layer와 Order in Layer

 

Sorting Layer와 Order in Layer 모두 게임 오브젝트들이 그려지는 순서를 결정하는 데에 사용됩니다.

Sorting Layer 설정창

Sorting Layer의 경우 가장 위에 있는 레이어가 가장 먼저 그려집니다.

사진 상에서 Layer 0이 가장 위에 위치하고 있습니다.

즉, 가장 뒤에 그려진다는 얘기입니다.

 

BackGround 레이어가 "Layer0", Player레이어가 Layer3으로 설정되어 있습니다. 

땅과 벽, 풀 등은 World레이어(Layer1)로 설정되어 있습니다.

아래 사진을 보시면 하늘색 배경이 가장 뒤에, 우거진 수풀이 그다음에,

풀, 벽, 땅 등이 그려지고 마지막에 플레이어가 위치한 모습을 볼 수 있습니다.

수풀 앞에 여우가 그려진 모습

 

그런데 사진을 보다 보니 의문이 하나 생깁니다.

수풀과 배경 모두 BackGround Layer에 포함되어 있습니다.

즉,  Sorting Layer가 같습니다.

그런데 왜 파란색 배경이 뒤에 그려지는 것일까요?

좌측 : 파란배경 오브젝트 / 우측 : 우거진 수풀 오브젝트

동일한 Sorting Layer에서는 Order in Layer의 값이 그려지는 위치를 다르게 합니다.

back 오브젝트가 '파란색 배경', middle 오브젝트가 '우거진 수풀'입니다.

앞서 말한 바와 같이 Sorting Layer값은 BackGround로 동일하지만,

Order in Layer 값이 다릅니다.

back 오브젝트는 -2, middle 오브젝트는 -1입니다.

즉 값이 낮을수록 뒤에 그려집니다.

 

Sorting Layer와 Order in Layer를 따로 사용하는 이유

 

지금처럼 오브젝트가 많지 않은 경우는 Order in Layer만 사용해도 관리가 쉬울 것입니다.

그런데 게임에 사용되는 오브젝트가 수천 개가 넘어간다면 어떻게 될까요?

오브젝트 하나하나 Order in Layer의 값을 조정해 주는 건 어렵고, 비효율적인 일이 될 겁니다.

그래서 오브젝트의 성질에 따라 Sorting Layer로 분류를 해주고,

세부적인 조정은 Order in Layer로 해주는 것입니다.

 

즉, '효율적인 관리'를 위해 Sorting Layer와 Order in Layer를 혼용한다고 생각하면 될 거 같아요.

반응형
반응형

출처 : 프로그래머스(https://school.programmers.co.kr/)

 

문제만 봐서는 잘 이해가 안 됐는데 예를 보니까 이해가 됐습니다.

abcde라는 문자열을 입력했을 때, 문자를 하나씩 떼어내서 출력하는 프로그램을 완성하라는 문제입니다.

 

정답 예제1 (for문 사용)

using System;

public class Example
{
    public static void Main()
    {
        String s;

        Console.Clear();
        s = Console.ReadLine();
        
        for(int i = 0;i < s.Length;i++){
            char r = s[i];
            Console.WriteLine(r);
            }

    }
}

저는 for문을 사용해서 해결했습니다.

먼저 입력되는 문자열을 담아주는 변수 s의 길이만큼 for문을 반복해 줍니다.

그리고 char 타입의 변수 r에 문자열의 첫 번째부터 끝까지 차례대로 할당합니다.

Console.WriteLine함수를 통해 r변수에 담긴 문자를 차례대로 출력합니다.

 

  • 문자열 'abcde'를 입력했을 때 출력 결과 

 

 

 

 

 

 

정답 예제 2(foreach문 사용)

Foreach문법

foreach문은 컬렉션(collection)이나 배열(array) 등의 요소를

하나씩 순회하면서 처리할 때 사용되는 반복문입니다.

foreach문은 반복 대상의 데이터형에 따라 자동으로 반복을 처리하기 때문에,

일반적인 for문보다 코드가 간결해지고 가독성이 좋아집니다.

using System;

public class Example
{
    public static void Main()
    {
        String s;

        Console.Clear();
        s = Console.ReadLine();
        
        foreach(char r in s){
            Console.WriteLine(r);
        }

    }
}

개인적으로는 foreach문으로 문제를 푸는 것이

코드 가독성면에서도 훨씬 깔끔하다는 생각이 들었습니다.

 

  • 문자열 'abcde'를 입력했을 때 출력 결과

반응형
반응형
using System;

public class Example
{
    public static void Main()
    {
        // 특수문자 출력 코드
        Console.WriteLine("!@#$%^&*(\\'\"<>?:;");

    }
}
  • 츨력결과 !@#$%^&*(\'"<>?:;

 

C#에서 특수문자를 출력하는 방법

 

일반적으로 특수문자도 Console.writeLine함수로 출력이 가능합니다.

그러나 '(작은 따옴표), "(큰 따옴표)와 같은 특수문자는

문자열을 둘러싸는 기호로 사용되는데요.

그러므로 출력을 하기 위해서는 '이스케이프 문자(escape character)'를 사용해야 합니다.

 

이스케이프 문자(escape character)

 

이스케이프 문자는 문자열 내에서 특수한 의미를 가지는 문자를 나타내기 위해 사용됩니다.

백슬래시(\)기호와 함께 사용되며, 백슬래시 다음에 오는 문자는 일반 문자로 처리합니다.

 

C#에서 자주 사용되는 이스케이프 문자 모음

 

반응형
반응형

골드메탈 - 뱀서라이크 유니티

Pixel Per Unit

Unity에서 Pixels Per Unit (PPU)란, 1 유닛(Unit)에 포함되는 픽셀(pixel)의 수를 의미합니다.

1 Unit은 위 사진에서 보이는 네모 1칸입니다.

즉, 네모 한 칸 안에 들어가는 픽셀의 수가 PPU인 것이죠.

사진 속 남자 캐릭터의 크기는 18 pixel x 20 pixel입니다.

일반적으로 캐릭터 스프라이트와 PPU를 동일하게 가져간다고 합니다.
만약 PPU 값과 캐릭터 스프라이트의 크기가 다르다면 아래 사진과 같은 문제가 생길 수 있습니다.

캐릭터가 화면에 너무 크게 나타나거나 작게 나타나는 등의 문제입니다.

좌측은 PPU가 18, 우측은 PPU가 100일 경우의 사진입니다.

좌측 : PPU - 18 설정했을 때 / 우측 : PPU - 100 설정했을 때

PPU와 스프라이트의 크기를 일치시켜 주는 이유 중 하나는 '편의성' 때문인 거 같습니다.

PPU 값과 캐릭터 스프라이트의 크기를 일치시켰을 때, 좌표를 1 이동하면 1 유닛만큼 이동합니다.

즉, 게임 오브젝트의 크기와 이동 거리 등을 측정할 때 유용합니다.

 

소형 스프라이트를 사용할 때 유용한 팁

유니티에서는 스프라이트 최적화를 위해

파일을 자체적으로 압축시키는 옵션이 기본으로 되어 있습니다.

 

사이즈가 너무 작은 픽셀 아트의 경우

압축할 때 오히려 색이 변질되거나 선명도가 감소하는 문제가 생긴다고 해요.

그래서 Filter Mode를 Point(no filter), Compression을 None으로 설정해 주면

위와 같은 문제를 예방하는데 도움이 됩니다.

반응형

+ Recent posts