2024.07.03 - [Coding/Unity] - [내일배움캠프 55일차 TIL] 2D 하루 낮밤과 다음 날 구현하기 [내일배움캠프 55일차 TIL] 2D 하루 낮밤과 다음 날 구현하기[ URP 설정 ]2D에서 빛을 이용해 낮과 밤을 만들고 싶다면 URP 설정이 되어있어야 한다.URP는 Universal Render Pipeline으로 빌트 인(Built-In) 보다 향상된 그래픽 품질을 제공하는 파이프 라인이다. 유니티siknyang.tistory.com저번에 24시간 내내 시간이 흘러가고, 시간에 맞춰 빛 색이 변화하는 기능을 구현했다. 이번에는 침대에서 잠을 자면 다음 날 오전 6시로 넘어가는 기능을 추가했다. [ 수면 시스템 구현] 전체 코드using System.Collections;usin..
Coding/Unity
[ URP 설정 ]2D에서 빛을 이용해 낮과 밤을 만들고 싶다면 URP 설정이 되어있어야 한다.URP는 Universal Render Pipeline으로 빌트 인(Built-In) 보다 향상된 그래픽 품질을 제공하는 파이프 라인이다. 유니티 버전 2022.3.17f1빌트 인으로 시작했더라도 패키지 매니저에서 URP를 설치하면 사용할 수 있다. URP를 검색해서 Install을 누르면 자동으로 설치된다. 이후 렌더링 토글에 생성 가능한 URP 파일들이 생기는데, URP Asset (with Universal Renderer)을 누르면 프로젝트 탭에 두 파일이 생성된다. 프로젝트 세팅에서 Graphics의 Scriptable Render Pipeline Settings에 아까 생성되었던 파일 중 _Asset..
[ 트러블 슈팅 ]적이 죽고 리스폰되지 않음적을 구현할 때 오브젝트 풀을 이용해서 생성, 제거를 반복하지 않고 계속해서 가져다 쓰는 기능을 구현했다. 하지만 맨 처음 풀 사이즈만큼 적들이 생성되고 죽고 나면 다시 리스폰되지 않는 현상이 발생했다. private IEnumerator DestroyAfterDelay(float delay) { yield return new WaitForSeconds(delay); Destroy(gameObject); // 오브젝트 파괴 }그 이유는 적이 죽고 오브젝트를 씬에서 삭제하는 코루틴에서 적 오브젝트 자체를 파괴해버려서 다시 큐에 들어가지 못했기 때문에 생성되지 않았다. private IEnumerator DestroyAfterDe..
[ 오브젝트 풀에서 큐의 동작 원리 ]오브젝트 풀에서 자주 사용되는 것이 선입선출 구조인 큐(Queue)이다. 큐에 오브젝트를 넣을 때는 Enqueue 메서드, 뺄 때는 Dequeue 메서드를 사용하라고 해서 사용하곤 있지만, 오브젝트 풀에서 정확히 어떤 원리로 동작하고 있는지 이해를 해야 적절한 시점에서 해당 메서드들을 사용할 수 있다. 큐와 오브젝트예를 들어 설명하자면 큐는 관리자, 오브젝트는 일꾼이다. 일꾼들이 작업할 순서를 정해주는 것이 큐의 역할이다.활성화는 작업 중인 것이고, 비활성화는 작업을 하고 있지 않은 상태이다.모집 인원에 맞춰 이제 막 고용된 일꾼들은 일을 하고 있지 않는다. Enqueue()맨 처음 일꾼들이 일을 하러 와서 관리자에게 출석 확인을 한다. 작업 명단을 작성해서 관리자가..
[ 플레이어 데이터 ]데이터가 저장되어 있는 변수를 바로 사용하는 것이 아니라, 직렬화하려는 데이터들만 따로 별도의 class나 struct로 만든다. public class Character : MonoBehaviour{ public UserData data; private void Start() { data.nickname = "식냥"; data.lv = 7; data.hp = 100; } private void Update() { // JSON 직렬화 if (Input.GetKeyUp(KeyCode.Q)) { var jsonData = JsonUtility.ToJson(data); ..
2024.05.10 - [Coding/Unity] - [내일배움캠프 19일차 TIL] New Input System, 이벤트 처리 [내일배움캠프 19일차 TIL] New Input System, 이벤트 처리사용자가 플레이어를 움직이기 위해서 키보드 방향키를 눌렀다. 그러면 플레이어는 이동에 대한 입력을 받은 것이다. 우리는 입력이 들어오면 이동과 관련된 모든 메서드들이 실행되기를 원한siknyang.tistory.com지금까지는 계속 Player Input component로 이벤트를 호출하는 방식을 사용했다. 2024.06.12 - [Coding/Unity] - [내일배움캠프 40일차 TIL] Input System 다이렉트, 임베디드, 액션 에셋, C# 제너레이트, Action Properties [..
[ 파티클 시스템(Particle System) ]반짝이는 효과나 마법진 같은 이펙트를 제작하는 데 활용되는 컴포넌트이다.이펙트에 사용되는 오브젝트 하나하나를 파티클이라고 부르며, 파티클 시스템은 이런 수천 개의 파티클의 동작과 생애를 체계적으로 관리한다.파티클 시스템의 주요 컴포넌트는 emitter(발사체), particles(파티클), animator(애니메이터), renderer(렌더러) 등이 있다.시간에 따른 파티클의 행동을 시뮬레이션하면서 각 파티클의 위치, 속도, 수명, 색상, 크기 등의 정보를 저장한다.파티클 시스템은 최대 파티클 수 제한, 적용 범위 제한 등과 같은 기능으로 성능 최적화를 한다. 주요 모듈Main 모듈가장 기본적인 값인 파티클의 속도, 크기, 회전, 최대 개수를 정할 수 있..
[ InputSystem ]기존에는 인풋 액션 창에서 키를 직접 설정하고 인풋 시스템 컴포넌트를 추가해서 사용했다. 하지만 코드 작성으로 인풋 시스템을 사용할 수도 있다.캐릭터가 A키와 D키를 통해 좌우로 움직이는 로직을 코드를 사용해서 구현해보자. 우선 기본적으로 스크립트에서 인풋 시스템을 사용하려면 UnityEngine.InputSystem 네임스페이스가 있어야 한다.using UnityEngine.InputSystem; 다이렉트다이렉트 방식은 코드로 모든 입력을 받아오는 로직을 작성한다.public float dir;Keyboard keyboard;void Start(){ keyboard = Keyboard.current; // 현재 연결된 기기 받아옴}void Update(){ if(keyboar..
[ 아이템 데이터 NullReferenceException 에러 ]트러블 슈팅클릭한 오브젝트, 놓인 오브젝트, 들고 있는 오브젝트 비교해서 모두 동일하면 해당 오브젝트를 보이게 하는 코드가 있다. 기존에는 테스트를 위해 전역 변수로 직접 인스펙터 창에서 오브젝트를 할당해서 사용했는데, 팀원들과 작업물을 합치면서 플레이어가 실제로 장착하고 있는 아이템의 정보를 가져오는 코드로 수정했다. 하지만 플레이어가 항상 아이템을 장착하고 있는 것이 아니기 때문에, 아이템을 장착하고 있지 않을 때 클릭을 하면 NullReferenceException 에러가 뜬다. GameObject curItem = CharacterManager.Instance.Player.equipItem.ItemPrefab;if (curItem ..
[ 오브젝트 컴포넌트에 플레이어 위치 자동 할당 ]트러블 슈팅건물 에셋을 가져왔는데, 기존에 있던 임시 플레이어를 삭제하고 새로운 플레이어를 생성했더니 기존에 할당되어 있던 플레이어 오브젝트가 모두 None이 되면서 문이 열리지 않게 되었다. 문 외에도 서랍장, 창문 등 열리고 닫히는 오브젝트와의 상호작용 자체가 되지 않았다. 모든 것을 할당하기에는 오브젝트가 몇 백개라서 현실적으로 일일이 할당하기란 불가능했다. 오브젝트가 프리팹이라서 프로젝트에서 프리팹을 수정하면 되지 않을까했는데, 스크립트가 있는 오브젝트가 자식 오브젝트라서 플레이어를 할당할 수 없었다. 그리고 오브젝트 수도 엄청 많아서 이것도 현실적으로 불가능했다. 그래서 각 오브젝트에 있는 스크립트를 수정하는 방향으로 해결했다. 문을 여닫고 싶은..
[ 패시브 아이템 사용 불가 버그 ]트러블 슈팅컨디션과 관련된 아이템은 정상적으로 사용되고 UI에도 적용이 됐지만, 패시브와 관련된 아이템은 사용부터 되지 않는 버그가 있었다. 사용하기 버튼을 누르면 NullReferenceException: Object reference not set to an instance of an object 에러가 떴다. 원인을 확인하기 위해서 에러가 발생하는 코드에서 디버깅을 했다. 디버깅을 했을 때 UIInventory 스크립트의 OnUseButton 메서드에서 passive에 null 값이 있어서 에러가 발생했다. 해당 스크립트에서 정의된 passive 변수에서도 null이 떴다. 원인은 PlayerPassive 스크립트와 UIInventory 스크립트와의 연결이 잘 되..
[ 인벤토리 아이템 NullReferenceExeption 에러 ]트러블 슈팅인벤토리에 들어온 아이템을 클릭하면 오브젝트를 찾을 수 없다는 NullReferenceException: Object reference not set to an instance of an object 에러가 뜬다. 에러가 뜬 줄에서 디버깅을 했더니 selectedItem이 null이었다.selectedItem에서는 slots[index].item이 null이었다.slots[index].item이 있는 if문을 확인해보니 == 연산자를 사용해서 값이 null인지 확인하는 조건이 되게 해야하는데, = 연산자를 사용해서 null이 할당되어 있었다. == 연산자로 수정했더니 정상적으로 작동되었다. [ 인벤토리 창의 아이템 능력치 표시 ..
[ 스크립터블 오브젝트 ]스크립터블 오브젝트(ScriptableObject)는 유니티에서 데이터를 저장하고 관리하는 일종의 컨테이너이다. 오브젝트에 대한 데이터 및 설정을 스크립터블 오브젝트에 저장하고, 이를 다른 오브젝트에 적용해서 재사용할 수 있다. 인스펙터 창에서 직접 수정하고 관리할 수 있다. using UnityEngine;[CreateAssetMenu(fileName = "Stat", menuName = "Monster/Defalut")]public class StatSO : ScriptableObject{ public string name; public int level; public float attackDemage;}예를 들어 몬스터에 대한 이름, 레벨, 공격력에 대한 데..
[ 애니메이션 적용 ]트러블 슈팅애니메이션을 적용했을 때 스프라이트가 바뀌면서 캐릭터가 깜빡거리는 현상이 발생했다.또한 CameraController가 오브젝트의 위치를 참조하지 못하면서 카메라 화면도 이동하지 않게 됐다. 캐릭터 오브젝트를 할당하지 않았던 간단한 문제였다. 이후 정상적으로 깜빡임 현상 없이 카메라 화면도 잘 움직였다. 너무 기본적인 거라 당연히 했을 거라고 생각하고 까먹을 때가 있는데, 뭔가 잘 안 된다면 일단 컴포넌트에 오브젝트를 할당했는지 체크해 보자. [ 이름 입력 ]StartScene을 생성해서 이름을 입력하고 Join 버튼을 누르면 MainScene으로 이동한다. 단, 이름은 2~10글자여야 한다. 트러블 슈팅public class JoinButton : MonoBehaviou..
[ 카메라 추적 ]구현 코드카메라가 캐릭터의 움직임을 따라가고 함께 이동하기 때문에, TopDownMovement 클래스에서 캐릭터 이동 메서드에 카메라 이동 코드를 구현하면 되지 않을까 하고 생각했다.하지만 메서드를 구분해 놓는 것이 찾기도 쉽고 구현도 편할 것 같아서 CameraController 클래스를 새롭게 생성했다. //최종 코드public class CameraController : MonoBehaviour{ private Camera camera; public Transform chracterPos; public Vector3 offset = new Vector3(0, 0, -10); private void Awake() { camera = Camer..
사용자가 플레이어를 움직이기 위해서 키보드 방향키를 눌렀다. 그러면 플레이어는 이동에 대한 입력을 받은 것이다. 우리는 입력이 들어오면 이동과 관련된 모든 메서드들이 실행되기를 원한다. 이는 이벤트 핸들링을 통해 해결할 수 있다. 잠깐! 근데 그냥 입력된 이동을 처리하는 메서드에서 관련된 메서드를 바로 호출하면 되는 것 아닌가요🤔?이 의문을 해결하기 위해서는 New Input System을 알아야 한다. [ New Input System ]기존에 사용되던 InputManager에서 모든 기능들이 하나의 클래스에 존재하여 발생하는 문제점을 보완한 것이다. 기능별로 클래스를 나눠서 구현하는 것은 객체 지향 프로그래밍에서 매우 중요한 요소이기 때문에, New Input System을 이용하면 수월하게 로직을..
[ 쿼터니언 ]쿼터니언은 3차원 회전을 표현할 때 사용되고, 유니티에서는 오브젝트의 회전을 처리한다. 유니티 인스펙터 창의 회전은 3차원 벡터로 표현되고, 이를 오일러 각이라고 한다. 오일러 각은 피치(Pitch)는 x축, 요(Yaw)는 y축, 롤(Roll)은 z축을 기준으로 회전한다. 이때 하나의 축에서 과한 회전이 일어나 다른 회전축과 평행하게 됐을 때 짐벌락(Gimbal Lock)이 발생한다. 두 개의 회전축이 겹쳐지면서 기존의 축이 방향을 잃어버리는 것이다. 쿼터니언을 이용하면 이러한 짐벌락 문제를 피할 수 있다. 쿼터니언은 수학적으로 (x, y, z, w) 형태의 4가지 숫자로 구성되어 있고, 이를 직접 조정할 수는 없다. 대신 Quaternion.Euler, Quaternion.LookRota..
[ 게임 엔진 ]게임 엔진이란 게임 개발에 필요한 여러 기능들을 제공하는 프로그램이다. 그래픽, 사운드, 애니메이션 등과 같은 다양한 요소들을 관리하고 통합한다. [ 스크립트 ]컴포넌트는 Monobehavior를 상속받고 있는 것들이다.Monobehaviour를 상속 받는 클래스는 유니티 이벤트 함수를 활용할 수 있고, 게임 오브젝트에 있는 이벤트 함수들은 특정 순서에 따라 호출되는 라이프 사이클을 가지고 있다. [ PPU ]Pixels Per Unit의 약자로, 스프라이트 픽셀 수 / 해당 스프라이트의 값이 게임 세계에서 차지하는 공간이다. 따라서 PPU 값이 클수록 스프라이트의 크기는 작아진다. 예를 들어 100 PPU는 1단위의 공간에 100개의 픽셀이 배치됨을 의미한다. 500 PPU는 1단위의 ..
3주 차 프로젝트에서는 게임을 제작했다. [ 기본 씬 구성 ] 카메라 화면 크기 조절 메인 씬 하이어아키에서 메인 카메라를 클릭하고 사이즈를 25로 맞춘다. 카메라에 보이는 화면이 넓어졌고, 더 많은 오브젝트를 생성할 수 있다. 오브젝트에 이미지 적용 오브젝트에 이미지를 적용하는 법은 간단하다. 오브젝트를 클릭하고 스프라이트에 이미지를 드래그 앤 드롭하면 자동으로 적용된다. 위치만 설정해 주면 되고, 크기는 이미지 크기에 맞춰서 자동으로 조절된다. 새로운 씬 생성 씬 폴더 우클릭으로 Create > Scene을 클릭하면 새로운 씬이 생성된다. 게임 시작 전 인트로 씬을 만들기 위해 StartScene으로 이름을 변경한다. MainScene과 동일하게 메인 카메라의 사이즈를 25로 맞춘다. using Un..
2주 차 프로젝트에서는 게임을 제작했다. [ 기본 씬 구성 ] Square, Circle, Text 오브젝트를 이용해서 게임 기본 씬을 구성한다. 풍선 애니메이션 색이 번갈아가면서 나타나게 하기 위해서 Balloon_Idle 애니메이션을 생성하고 Balloon 오브젝트에 드래그 앤 드롭한다. 애니메이션 창을 열어 왼쪽 상단의 녹화 버튼을 누르면, 오브젝트에 변화가 생길 때마다 변동 사항이 기록이 된다. 프레임 0에서는 맨 처음 상태가 기록이 되었고, 프레임 20에서는 연보라색으로 색상을 바꿔주었다. 프레임 40에서는 다시 흰색으로 변경하고 녹화를 종료하면, 두 가지 색상이 번갈아가면서 나타나게 된다. 왼쪽 상단의 토글을 눌러 Create New Clip으로 Balloon_Die 애니메이션을 생성한다. 녹..
[ UI ] 텍스트 UI는 User Interface의 약자로, 카메라와 상관없이 게임 화면에 계속해서 보이는 정보이다. UI는 하이어아키 빈 공간 우클릭 해서 만들 수 있다. UI > Legacy > Text를 통해 텍스트를 생성한다. 하이어아키에서 캔버스와 그 안에 텍스트가 있는 것을 볼 수 있다. 캔버스는 카메라 화면과 상관없이, 게임 화면 위에 바로 보이는 공간이다. 텍스트의 인스펙터에는 위치, 폰트 스타일, 폰트 크기, 정렬, 색상 등을 조정할 수 있다. UI에 보이게 하고 싶은 텍스트들을 복제해서 서식에 맞게 수정했다. 씬에서는 텍스트를 볼 수 있지만, 메인 카메라에서는 텍스트가 보이지 않는다. 하지만 게임 화면에서는 카메라 화면 위에 UI가 덧씌워져 텍스트가 적용된 모습을 볼 수 있다. [ ..
[ 오브젝트 물리 적용 ]중력빗물을 표현하기 위한 원 오브젝트를 생성한다. 하지만 프로젝트를 실행하면 원은 그 자리에 가만히 있고 움직이지 않는다. 따라서 오브젝트에 물리 작용을 줘야 하는데, 그중 아래로 떨어뜨리기 위해서 중력을 사용해야 한다. Rain 오브젝트에서 Add Component를 클릭하고 Rigidbody 2D를 클릭한다. Rigidbody 2D는 2차원 프로젝트에서 오브젝트에 중력을 부여하는 요소이다. 프로젝트를 실행하면 빗물이 아래로 떨어지는 것을 확인할 수 있다.하지만 빗물이 바닥을 뚫고 계속해서 아래로 떨어지는 문제가 생긴다. 이를 해결하기 위해서 빗물과 바닥이 부딪혔을 때, 빗물이 멈추고 파괴되도록 해야한다. 충돌Rain 오브젝트에 충돌을 적용시키기 위해 Add Component에..
유니티를 설치하고, 오브젝트 만들기부터 코드를 적용시켜 실행하기까지 게임 개발의 기초적인 부분을 학습했다. 프로젝트 명은 로, 하늘에서 떨어지는 빗물을 받아 점수를 모으는 게임을 만드는 것이다. 게임을 만들기 위해서는 게임이 실행될 환경이 구축되어야 한다. 2D 탬플릿의 새로운 프로젝트를 생성하고, 작업하기 쉬운 레이아웃으로 변경한 뒤 본격적인 제작에 들어갔다. ▼ 레이아웃 변경을 통한 작업 환경 구축 더보기 [ 오브젝트 ] 추가 구성 요소인 오브젝트를 추가하는 방법은 Hierarchy 창에서 우클릭 후, 2D Object > Sprites > 모양 선택을 하면 된다. 배경 화면을 만들기 위해서 네모 오브젝트를 추가했다. 추가된 오브젝트는 Inspector 창에서 다양한 속성을 부여할 수 있다. Tran..