안녕하세요! 여러분들과 함께 게임 개발을 공부하는 베르입니다!

이번 영상에서는 개발할 때 활용할 수 있는 정규화라는 개념에 대해서 알아봅시다!

 

타임라인

0:00 인트로

0:10 정규화란?

0:47 벡터의 정규화

3:21 좌표의 정규화

5:12 아웃트로

인트로

안녕하세요. 여러분들과 함께 게임 개발을 공부하는 베르입니다.

이번 시간에는 게임 개발에서 사용할 수 있는 정규화라는 개념에 대해서 알아보도록 하겠습니다.

정규화란?

먼저 정규화라는 용어에 대해서 알아보겠습니다.

위키백과를 참고해보면 정규화는 어떤 대상을 일정한 규칙이나 기준에 따르는 정규적인 상태로 바꾸거나 비정상적인 대상을 정상적으로 돌리는 과정을 뜻한다고 합니다.

영어로는 Nomalization이라고 합니다.

이 정규화라는 개념은 여러 분야에서 각 분야에 맞게 사용되고 있습니다.

가장 대표적인 것은 데이터베이스 분야의 정규화로 데이터베이스를 설계할 때 여러 테이블에서 중복되는 데이터를 최소화시키는 프로세스를 가리킵니다.

게임이나 프로그램을 개발할 때도 여러 곳에서 이러한 정규화를 적용할 수 있습니다.

벡터의 정규화

앞에서 정규화를 영어로 하면 Noralization이라고 했을 때 짐작하신 분도 있었겠지만 역시 가장 먼저 이야기 해볼 것은 바로 벡터의 정규화 입니다.

벡터에 대해서는 [좌표와 속도를 다루는 도구 - 벡터] 영상에서 한 번 다룬 적이 있습니다.

벡터에 대한 자세한 내용은 해당 영상에서 확인할 수 있습니다.

벡터의 정규화는 어떤 한 벡터를 벡터의 길이로 나누어서 그 벡터의 길이를 1로 만드는 것입니다.

이렇게 길이가 1이 된 벡터를 단위 벡터라고 부르죠.

이런 식으로 정규화를 통해서 길이를 1이 된 벡터는 캐릭터의 이동과 방향에 주로 사용됩니다.

보통 키보드로 조작하는 방식의 게임은 W키와 S키를 이용해서 앞/뒤로 움직이고 A키와 D키를 이용해서 좌/우로 움직입니다.

그리고 W키를 누르면 수직 입력 값을 1로 받고 S키를 누르면 수직 입력 값을 -1로 받게 됩니다.

물론 손을 떼면 0이고 W키와 S키를 동시에 누르면 값이 상쇄되어서 0이 됩니다.

A키와 D키 역시 마찬가지로 수평 입력 값에 대해 동일하게 동작합니다.

그리고 W키와 S키로 동작하는 수직 입력과 A키와 D키로 동작하는 수평 입력을 묶어서 2차원 벡터로 이동 입력을 표현하게 됩니다.

여기서 이동 입력 키를 하나만 눌렀을 때의 입력 벡터의 길이는 언제나 1이라는 것을 알 수 있습니다.

이처럼 플레이어가 이동하고자 하는 입력 방향 벡터의 길이가 언제나 1이 되어야 캐릭터를 이동시킬 때, 입력 받은 방향에 캐릭터의 이동 속도를 곱하는 방식으로 쉽게 구현할 수 있게 됩니다.

그런데 캐릭터를 대각선 방향으로 이동시키기 위해서 W키와 A키, W키와 D키, A키와 S키, D키와 S키 같은 조합으로 동시에 누르게 되면 문제가 발생합니다.

만약 오른쪽 정면을 향해 이동하기 위해 W키와 D키를 동시에 눌렀다면, 정면 방향 벡터인 (0,1)과 오른쪽 방향 벡터인 (1,0)이 합쳐져서 (1,1)이 됩니다.

벡터 (1,1)의 길이는 밑변과 높이가 각각 1인 삼각형의 빗변의 길이로 나타내집니다.

이 길이는 루트 2로 약 1.414가 됩니다.

그래서 입력된 대각선 이동 벡터에 곧바로 이동 속도를 곱해서 캐릭터를 이동시키면 앞, 뒤, 왼쪽, 오른쪽 각 단일 방향으로 움직일 때보다 약 1.4배의 속도로 더 빠르게 움직일 수 있게 되는 겁니다.

이런 문제를 막기 위해서 이동 벡터의 길이가 1보다 길어지면 정규화를 통해서 이동 벡터의 길이를 1로 맞춰주는 방식을 자주 사용하게 됩니다.

이런 캐릭터의 이동 문제 외에도 속력과 방향을 정의되는 벡터에서 순수하게 방향만을 남겨서 사용하고자 하는 경우에는 이러한 벡터의 정규화 개념을 사용하게 됩니다.

좌표의 정규화

두 번째로 다뤄볼 정규화는 좌표의 정규화입니다.

게임을 개발하면서 우리는 여러가지 종류의 공간을 다루게 됩니다.

대표적으로는 게임을 플레이하면서 돌아다니게 되는 월드 공간과 UI가 그려지는 UI 공간이 있습니다.

이 두 공간의 좌표를 오가는 기능으로는 월드 공간에 존재하는 오브젝트를 UI 공간에서 나타내기 위한 기능으로 지도 기능이 있습니다.

플레이어나 오브젝트들이 움직이는 월드 공간의 크기는 기획에 따라 달라지기 마련이고 UI 공간은 디스플레이의 해상도에 따라 달라집니다.

간단하게 예를 들어서 3800x3800의 넓이를 가지는 월드 공간에서 움직이는 오브젝트를 UI 공간에서 800x800의 지도 UI에서 표시하고 싶다고 가정해봅시다.

오브젝트가 (2000, 1500)의 위치에 있을 때 지도 UI에 자신의 좌표를 그대로 보내버리면 800x800인 지도의 한참 바깥에 위치를 표시하게 됩니다.

그렇기 때문에 월드 공간에 존재하는 오브젝트의 위치는 좌표를 정규화시켜서 지도에 전달해야 합니다.

오브젝트 좌표의 X값과 Y값을 각각 월드 공간에 속하는 맵의 가로 폭과 세로 폭으로 나눠줍니다.

그러면 오브젝트의 좌표는 (0.52631, 0.39473)으로 변환되면서 좌표의 모든 값이 0에서 1사이 값의 형태를 가지게 됩니다.

이렇게 정규화된 좌표 값을 지도 UI에 넘겨주면 지도 UI에서는 이 값에 지도의 너비와 높이를 곱해줍니다.

그러면 오브젝트의 지도 위에서 좌표 값이 (421.05, 315.78)이 되면서 월드 상의 위치와 지도 상의 위치가 거의 흡사하게 표시되는 것을 볼 수 있습니다.

이런 식으로 서로 다른 공간에 있는 오브젝트의 위치를 표현할 때 좌표 값을 정규화해서 넘겨주는 것으로 동일한 위치에 표시할 수 있게 되는 것입니다.

이러한 좌표의 정규화 개념은 월드 공간과 UI 공간을 넘어서, 현실 공간에서 센서같은 장비로 계측된 위치를 월드 공간으로 옮기는 방식으로도 적용할 수 있습니다.

아웃트로

이번 영상에서는 정규화라는 개념과 게임 개발에서 사용되는 아주 간단한 예시만을 알아보았습니다.

이 외에도 정규화라는 개념은 게임 개발의 여러 분야에서 유용하게 사용할 수 있습니다.

이상 베르의 게임 개발 유튜브였습니다. 감사합니다.

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

'게임 제작 > 게임 수학' 카테고리의 다른 글

[Math] 비트 연산  (0) 2021.06.22

스크립트

인트로

안녕하세요. 여러분들과 함께 게임 개발을 하는 베르입니다.

이번에는 문돌이가 다루는 한없이 가벼운 게임 수학이라는 주제로 돌아왔습니다.

게임을 만들면서 사용되는 수학이나 계산 등에 관련된 것을 알아보도록 할 겁니다.

베르의 한없이 가벼운 게임 수학 그 첫 번째 주제는 비트 연산입니다.

캐릭터 상태 예시

보통 게임에서 캐릭터는 여러 가지의 상태를 가질 수 있습니다.

간단하게 RPG 캐릭터를 예시로 들어보겠습니다.

보통의 열거형으로 구현한다면 가장 기본 상태인 정상 상태와 기절 상태, 중독 상태, 화상 상태 등등 여러가지 상태를 이렇게 만들 수 있습니다.

하지만 이렇게 기본 열거형에 순서대로 상태를 정의하는 방법은 캐릭터가 한 번에 하나의 상태만 가질 수 있게 만듭니다.

0이 정상이면 1은 기절, 2는 중독, 3은 화상, 이렇게 값이 정의됩니다.

이 방법에서는 상태가 바뀌면 다른 상태로 전환될 뿐이지 여러 개의 상태가 중복으로 적용되지 못하는 것을 볼 수 있습니다.

이진법

그럼 여기에 비트 연산을 사용하면 어떻게 되느냐.

비트 연산에 대해서 이해하려면 우선 2진법에 대한 이해가 필요합니다.

2진법은 컴퓨터 내부에서 사용되는 수 체계로 0과 1이라는 두 개의 숫자만으로 수를 나타내는 방법입니다.

0과 1만으로 수를 표현하면 0은 0이고 1은 1이지만 2부터는 자릿수가 올라가면서 10이 됩니다.

그리고 3은 11, 4는 100이 되죠.

한마디로 제일 오른쪽 첫 자리에서의 1은 1, 둘째 자리의 1은 2, 셋째 자리의 1은 4, 넷째 자리의 1은 8, 이렇게 2의 n승으로 자릿수가 올라갈 때마다 커지는 방식입니다.

컴퓨터에서 2진수의 한 자리를 1bit라고 부릅니다.

그리고 이 비트 8개가 모이면 1바이트라고 부르는 단위가 됩니다.

그리고 이 바이트 4개가 모이면 보통의 컴퓨터에서 int 변수 하나를 저장하는 크기가 되죠.

보통의 열거형은 int 타입으로 다뤄지기 때문에 4바이트의 크기를 차지합니다.

4바이트를 다시 비트로 환산하면 32개의 비트가 됩니다.

비트는 2의 n승으로 표현된다고 했으니 2의 32승, 즉 42억이 넘는 수가 표현이 가능한 겁니다.

이 숫자를 모두 캐릭터의 상태 열거형에 사용하면 최대 42억 개의 캐릭터 상태를 표현할 수 있습니다.

이진법을 이용한 중첩 상태 표현

하지만 앞에서도 이야기했듯이 그렇게 상태를 표현하면 한 번에 하나의 상태만 표현할 수 있고 다른 상태가 중첩되는 것을 전혀 표현할 수 없죠.

그래서 이 중첩된 상태를 표현하기 위해서 비트 하나에 상태 하나를 매핑해주는 겁니다.

모든 비트의 값이 0이면 아무런 상태도 적용되지 않은 정상이고, 첫째 자리가 1이면 기절 상태, 둘째 자리가 1이면 중독, 셋째 자리가 1이면 화상인 것입니다.

각 자리는 독립적으로 1이 될 수도 있고 0이 될 수도 있기 때문에 기절 상태이면서 화상에 걸릴 수도 있고, 화상에 걸린 상태에서 중독될 수도 있습니다.

거기에 더해서 모든 상태에 동시에 걸릴 수도 있죠.

이렇게 비트로 표현하는 상태의 단점은 열거형의 기본 타입이 int로 32비트라서 최대 32개의 상태까지만 표현할 수 있다는 점이지만 어지간한 게임에서는 32개의 상태면 필요로 하는 상태를 거의 다 표현할 수 있을 겁니다.

만약 32개의 상태가 부족한 경우에는 enum의 타입을 long으로 바꿔주면 64비트로 확장되어서 64개의 상태를 표현할 수 있게 됩니다.

그럼 여기까지 이진법의 비트 단위를 이용해서 어떻게 중첩된 캐릭터 상태를 표현할 수 있는지 알아보았습니다.

잘못된 상태 계상 방법

그렇다면 이제 이 비트 단위로 각 상태가 지정된 열거형 변수에 개발자가 원하는 상태를 적용하려면 어떻게 해야할까요?

이렇게 각 비트마다 상태 의미가 매핑되어서 각 상태들이 복잡하게 섞인 상태라면 내가 원하는 상태에 걸려있는지 어떻게 판단해야 할까요?

그리고 상태를 제거하고자 할 때는 또 어떻게 해야할까요?

그냥 상태를 추가할 때는 원하는 자리에 상태 값을 더하고 상태를 제거할 때는 원하는 자리에 상태 값을 빼주면 될까요?

이제부터 이 비트들에 대한 연산 방법을 알아보겠습니다.

값을 눈에 보기 쉽게 하기 위해서 잠시 윈도우 계산기를 찾아서 실행해줍니다.

그리고 계산기의 모드를 프로그래머로 바꾸면 비트 계산이 가능해집니다.

현재 상태가 0001이면 캐릭터는 기절 상태입니다.

거기에 중독 상태를 추가하기 위해서 0010을 더해주면 0011이 되서 기절 상태와 중독 상태가 중복됩니다.

그럼 0011처럼 이미 중독이 걸린 상태에 중독 공격을 한 번 더 당하면 어떻게 될까요?

더하기 계산으로는 두 번째 자리에 값을 더해주기 때문에 자릿수가 올라가서 0101이 되버립니다.

중독 상태가 갑자기 화상 상태로 바뀌어버리는 거죠.

명백한 버그입니다.

반대로 상태를 제거하기 위해서 값을 빼는 것도 마찬가지 입니다.

0101 상태로 중독 값이 없는 상태에서 중독을 제거하려고 0010을 빼면 0011이 되서 갑자기 화상 상태가 사라지고 중독 상태가 걸립니다.

그리고 0001 처럼 그 위에 값이 없는 상태에서 0010을 빼버리면 더 큰 문제가 발생할 수 있습니다.

위 값이 전혀 없는 상태에서 0001에서 0010을 빼면 가장 윗 자리수 앞에 1이 있는 것으로 간주해서 빼는 계산을 해버리기 때문에 그 위의 모든 자릿수들이 1로 바뀌어 버립니다.

그리고 지금 예시에서야 0101과 같이 눈으로 볼 수 있게 이야기를 하고 있지만 실제 값은 5일 겁니다.

이 5라는 값에서 기절과 화상이 걸린 상태라는 것을 어떻게 판단해야 할까요?

AND 연산과 OR 연산

이런 문제 없이 원하는 자리에 값을 넣고 빼기 위해서는 비트들끼리 연산하는 방법에 대해서 알아야 합니다.

컴퓨터 관련 공부를 해보셨거나, 마인크래프트에서 손에 레드스톤 가루를 좀 묻혀보신 분들이라면 AND 게이트와 OR 게이트에 대해서 알고 계실 겁니다.

그래도 모르시는 분들을 위해서 조금만 설명하도록 하죠.

AND 연산은 각 자릿수 끼리 계산을 해서 둘 중 하나라도 0이면 0이되고 두 수가 모두 1이면 각 자리가 1이 되는 방식의 계산입니다.

여기 이렇게 0011과 0101, 두 이진수를 AND 연산으로 처리하면 제일 앞자리는 0과 0이니 0, 두 번째 자리는 0과 1이니 0, 세 번째 자리는 1과 0이니 역시 0, 마지막 자리는 1과 1이니 1이 나와서 0001이 됩니다.

그리고 OR 연산은 각 자릿수 끼리 계산해서 둘 중 하나라도 1이면 그 자리의 수가 1이 되는 방식의 계산입니다.

다시 0011과 0101, 두 이진수를 OR 연산으로 처리하면 제일 앞자리는 0과 0이니 0, 두 번째 자리는 0과 1이니 1, 세 번째 자리는 1과 0이니 역시 1, 마지막 자리는 1과 1이니 1이 나와서 0111이 됩니다.

비트 연산을 이용한 상태 계산

그럼 이제 이 AND 계산과 OR 계산을 이용해서 앞에서 말한 문제를 해결해봅시다.

우선 상태를 추가하는 방법입니다.

상태를 추가하기 위해서는 OR 계산을 사용하면 됩니다.

0001에서 중독상태를 추가하기 위해서는 0010을 OR 연산해주면 0001과 0010에서 1인 자리들이 합쳐져서 0011이 되면서 중독 상태가 추가됩니다.

그리고 0011처럼 이미 중독된 상태에서 0010을 OR 연산해도 값이 증가하면서 엉뚱한 상태가 추가되지 않는 것도 알 수 있습니다.

코드에서는 이렇게 구현됩니다.

아무런 상태 이상도 걸리지 않은 Normal을 0으로 두고 각 상태를 2의 n승 값을 가지게 만들어줍니다.

기절은 1, 중독은 2, 화상은 4. 이렇게 말이죠.

숫자 앞에 0x를 붙이면 숫자를 16진수로 쓸 수 있는데 16진수를 사용하면 2의 n승을 표현하기 쉬워지기 때문에 비트 연산을 할 때 사용하면 좋습니다.

이렇게 비트 단위로 값을 설정한 다음 수직선 기호( | )를 사용하면 OR 통해서 상태를 추가할 수 있습니다.

그 다음 상태를 제거하는 방법은 AND 연산을 사용하면 됩니다.

0011처럼 중독과 기절이 동시에 걸려있는 상태에서 중독 상태를 제거하기 위해서는 1101처럼 빼고자 하는 자릿수만 0이고 나머지는 모두 1인 값과 AND 연산을 해주면 됩니다.

그러면 두 자리가 모두 1이 되는 자릿수만 그대로 남고 0인 자리들은 0이 됩니다.

거기서 중독 상태 자리는 계산되는 값이 0이기 때문에 무조건 0이 되어서 제거됩니다.

코드에서는 이렇게 구현됩니다.

우선 열거형에 해당 상태 자릿수만 0이고 나머지는 모두 1이 되는 반대 상태를 정의해주는 것이 작업에 도움이 됩니다.

NotStun이라는 이름으로 값을 정의해줍니다.

16진수로 반대가 되는 값을 넣어주면 되는데 값이 헷갈릴 수 있으니 계산기를 켜고 해당 비트를 0으로 만들어서 값을 만든 다음 확인하고 입력해줍니다.

정의가 끝난 다음에는 현재 상태와 Not 상태값을 & 기호를 사용해서 AND 연산해주면 원하는 상태만 제거할 수 있게 됩니다.

그 다음으로 지금 캐릭터가 어떤 상태에 걸렸는지 확인하는 방법입니다.

상태 확인 역시 AND 연산을 사용하면 되는데 Not 상태값 대신 확인하고자 하는 상태값을 현재 상태와 AND 연산을 해주면 됩니다.

그러면 그 상태에 걸려있으면 그 상태값이 나오고 그렇지 않으면 0이 나옵니다.

이렇게하면 어떤 상태에 걸려있는지 확인할 수 있습니다.

마지막으로 비트 연산의 응용법을 하나 알아보겠습니다.

일반 열거형을 사용하면 그 값이 int가 되어서 총 32개의 비트를 사용한다는 것과 어떤 자리가 어떤 상태를 나타내는지 각 비트에 상태를 매핑해서 사용한다는 것을 앞에서 말씀드렸었습니다.

이때 상태를 무작위로 매핑하는 것이 아니라 상위의 16개 비트에는 플레이어에게 이로운 효과를 매핑하고 하위의 16개 비트에는 플레이어에게 해로운 효과를 매핑하는 겁니다.

그러면 게임에서 자주 보던 것처럼 플레이어에게 적용되고 있는 모든 해로운 디버프를 한 번에 제거할 수도 있고 반대로 이로운 버프들을 모두 제거할 수도 있게 됩니다.

아웃트로

이번 영상에서는 이진법과 비트 연산을 이용해서 캐릭터의 상태를 표현하는 방법을 알아보았습니다.

이상 베르의 게임 개발 유튜브였습니다. 감사합니다.

타임라인

0:00 인트로

0:20 캐릭터 상태 예시

0:57 이진법

1:38 이진법을 이용한 중첩 상태 표현

3:20 잘못된 상태 계산 방법

5:19 AND 연산과 OR 연산

6:13 비트 연산을 사용한 상태 계산

9:39 아웃트로

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

'게임 제작 > 게임 수학' 카테고리의 다른 글

[Math] 정규화 (1) - 벡터와 좌표의 정규화  (1) 2021.10.04

+ Recent posts