# C# Unity 게임 개발자 2D

## 스노우 보더

### Sprite Shape

씬에 오브젝트 추가: 2D Object > Sprite Shape 변경된 모양 저장되는 곳: 폴더 > Create > 2D > Sprite Shape Profile

![](https://velog.velcdn.com/images/biomatrix117/post/6eed0b20-6de0-4542-a35b-14455cefc347/image.png)

Sprite Shape Profile의 Sprite 바꿨더니 테두리 바뀜

![](https://velog.velcdn.com/images/biomatrix117/post/342d54c6-7a11-4cae-a511-deb013a914b8/image.png)

Fill - Texture 바꿨더니 안도 채워짐

Edit Spline 누르면 모양 변형시킬 수 있다

### Edge Collider

Edge Collider 붙이면 스프라이트 전체 경계에 딱 맞는 콜라이더가 자동으로 생성 (스프라이트 모양 변경해도 같이 바뀜)

씬에 오브젝트 만들 때 Physics > Dynamic Sprite 하면 콜라이더랑 리지드바디 둘 다 붙어있는 오브젝트 나온다

![](https://velog.velcdn.com/images/biomatrix117/post/5301cc91-e455-461e-bbd1-bd2f139c3318/image.png)

엣지 콜라이더 때문에 살짝 떠서 이동한다

![](https://velog.velcdn.com/images/biomatrix117/post/bf057e9a-6877-47a0-8474-1eae9bac8e70/image.png)

Collider의 Offset을 조절하면 됨

![](https://velog.velcdn.com/images/biomatrix117/post/1fcabef4-f065-4865-9327-efca05b66ed0/image.png)

점 편집 가서 점들 전부 드래그한 후에 Height 조절하면 눈 크기 키울 수 있다

![](https://velog.velcdn.com/images/biomatrix117/post/0c547b91-dce6-4977-95f7-bf5632841f50/image.png)

참고로 Sprite Shape가 매끄러운 곡선인 이유는 Sprite Editor에서 미리 필요한 직선 부분만 잘라놨기 때문.

다른 텍스처로 fill 했는데 안 채워지면 Wrap mode를 Repeat로 바꿔봐라 (눈 스프라이트도 마찬가지)

#### Cinemachine Camera Follow

Cinemachine Pacakage 인스톨해오고 Ball에 Follow 걸면 위치 따라오고 Body를 Framing Transposer로 변경한 후에 Screen X를 바꿔주면 보여주는 화면 오프셋도 변경 가능

### Surface Effector

Surface Effector는 컨베이어 벨트처럼 특정 방향으로 힘을 주는 컴포넌트 이거 말고도 Effectors 2D에 여러 가지 종류 있다

추가 후에 콜라이더에 Used By Effector 체크해줘야한다 추가되는 속도는 Speed에서 조절할 수 있다

![](https://velog.velcdn.com/images/biomatrix117/post/b8bd5a1a-00aa-4355-9e71-e48e0899cbd4/image.jpg)

강의엔 나왔는데 나한테 안 발생한 버그. 플레이어가 벽뚫하기도 한다. 이땐 Rigidbody > Collision Detection > Continous로 바꾼다 Force Scale은 얼마나 중력과 관계없이 힘이 작용하도록 할지 조절하는 값

땅에 붙어있을 때만 Effector가 작용한다

#### 회전 - Addtorque

```cs
rb2d.AddTorque(torqueAmount);
```

Rigidbody에서 Linear Drag: 선형 속도 관성력, Angular Drag: 회전 속도 관성력

#### 네임스페이스 & 씬 전환

클래스 안에 메소드들이 있다 보통 C# 파일 하나에 클래스 하나가 있다 using은 네임스페이스 지정하는거

![](https://velog.velcdn.com/images/biomatrix117/post/c3067408-eadb-4969-b96b-12ce3b0bef31/image.png)

Build Settings에서 필요없는 씬 지우고 Add Open Scenes 해줘야 빌드할 때 유니티가 인식 오른쪽에 보면 인덱스 번호 보이는데 그걸로 씬 제어 가능

VS Code에서 `SceneManager`만 치고 자동완성 하면 네임스페이스 자동으로 추가해준다

#### 딜레이 넣기

딜레이 넣는 방법

* Invoke
* Coroutine

Invoke가 더 간단하니까 여기선 Invoke 써보겠다고 함

```cs
Invoke("NameOfMethod", delay);
```

사용 방법: 딜레이하고 싶은거 메소드로 만든 다음에 Invoke에 이름을 넣는다

#### 파티클 이펙트

Effects > Particle System 만들고 Gizmo에 가서 Selection Outline 끄면 주황색 테두리 사라짐

Particle System은 Emitter와 Particle로 이뤄짐 Inspector에서 모듈들 누르면 상세 조정 가능 각각의 Particle은 게임 오브젝트가 아니다. 그래서 각각의 Transform에 접근할 수 없다.

Start Lifetime: 얼마나 지속될지 Start Speed: 속도 Start Color: 색깔 Start Size: 크기 드롭다운 누르면 'Random Between Two Constants' 등 옵션 있음

Renderer 모듈에서 머테리얼도 바꿀 수 있음 Noise 모듈 쓰면 약간 흔들리는 효과 줄 수 있음

#### 파티클 이펙터 트리거

```cs
ParticleSystem finishEffect;

finishEffect.Play(); // 실행시키기
```

Play on Awake 끄는거 잊지 말기 z좌표 안 되돌려놓으면 안 보인다

파티클이 안 따라오게 하고 싶으면 Simulation Space를 World로 바꾸기

#### 모먼트 튜닝

Cinemachine Virtual Camera에서 Lens Orth Size를 바꾸면 보이는 크기 바뀜 캐릭터가 살짝 떨린다면 rigidbody에서 Interpolate를 Interpolate로 변경

#### FindObjectOfType 사용하기

```cs
surfaceEffector2D = FindObjectOfType<SurfaceEffector2D>();
```

FindObjectOfType은 씬에 딱 하나만 있는 걸 찾을 때 편리 (오브젝트 많으면 그거 다 순회하면서 찾느라 비효율적) 여러 개 있으면 원하는 대로 동작 안 함 (그때는 FindObjectsOfType 써야됨)

> 컴포넌트와 Type의 차이?

컴포넌트도 Type의 일종이다. 클래스를 만들 때 타입도 만들게 된다.

![](https://velog.velcdn.com/images/biomatrix117/post/d9562048-5004-4806-a78b-36f0ef6f2370/image.png)

코드 드래그 > Ctrl+`.` > Extract method

![](https://velog.velcdn.com/images/biomatrix117/post/c7e0e8b3-ae11-4829-b425-144abb8b6599/image.png)

짜잔

![](https://velog.velcdn.com/images/biomatrix117/post/299fba4e-e0b5-41f0-bda0-c8a17a04ad65/image.png)

존재하지 않는 메소드 이름 쓰기 > Ctrl+`.` > Generate method

`throw new NotImplementedException();` 이건 아직 아무것도 안 적었다는거 알려주려고 있는거

#### OnCollisionExit2D 사용하기

```cs
var mainModule = trailEffect.main; // 원본 데이터를 참조하는 핸들 가져오기
mainModule.loop = true; // 핸들로 수정 -> 원본 ParticleSystem에 반영
```

<https://discussions.unity.com/t/why-does-this-code-works-particlesystem-mainmodule-altering/908984/2>

왜 따로 선언했다가 그걸 수정해야하지? 나와 비슷한 의문을 가진 사람이 있었다. 이하는 gpt의 설명.

Unity의 ParticleSystem.MainModule과 같은 구조체는 값 타입 구조체이긴 하지만, 핸들러로 동작하도록 설계되어 있습니다.

Q: 그러면 왜 구조체를 사용하나요? Unity는 성능과 데이터 안정성을 위해 구조체를 사용합니다.

* 구조체는 복사가 기본 동작이라 원래는 값 타입으로 작동합니다.
* 하지만 Unity는 "값 타입" 구조체를 특별히 설계하여, 실제로는 원본 데이터를 안전하게 수정할 수 있도록 만들었습니다.

Q: trailEffect.main.loop = true;는 왜 안 되나요? 이 방식은 불가능한 이유는 trailEffect.main 자체가 구조체이고, 직접 수정할 수 없기 때문입니다. main 자체를 수정하려면 먼저 핸들러를 가져와야 합니다.

<br>

### 퀴즈 마스터

#### UI 캔버스

![](https://velog.velcdn.com/images/biomatrix117/post/5923298b-72e1-447c-9283-6858266f72ff/image.png)

Anchor Preset에서 Shift 누르면 피봇도 바뀌고, Alt 누르면 위치도 바뀐다 하늘색 방향색 있는 것들 클릭하면 늘어나기도 한다 (이전 크기를 기준으로 변형됨)

#### 텍스트 메시 프로

Vertex Color 아래에 있는 Color Gradient 체크하면 gradient 효과 Underlay는 그림자

#### 버튼 레이아웃

Button 컴포넌트에서 Transition > None 바꿔주면 코드로 다룰 때 간단 Source Image를 바꿔버려서 버튼 디자인

버튼 > Image 컴포넌트 > Image Type > Sliced로 바꾸면 테두리 없다고 경고 뜸 해당 스프라이트의 Sprite Editor에서 안 쪽으로 당겨주자

버튼 레이아웃 그룹 만들기 위해 빈 오브젝트 생성 > Vertical Layout Group 컴포넌트 추가 > 버튼들을 자식으로 넣어주기

크기 꽉 차게 하기 위해 Control Child Size 체크

#### 스크립터블 오브젝트

Scriptable Object란?

* 데이터 보관함에 불과하다
* 스크립트 바깥에서 데이터를 보관한다
* 한곳에 데이터를 저장해서 메모리를 줄이는데 도움을 준다
* 게임 오브젝트들에 붙일 필요 없다
* 가볍고 편리하다
* 데이터 일관성을 위한 템플릿으로써 기능한다

```cs
[CreateAssetMenu(menuName = "Quiz Question", fileName = "New Question")]
public class QuestionSO : ScriptableObject
{

}
```

스크립트 만들고 Create > Quiz Question 추가하면 뭔가가 생긴다.

```cs
[TextArea(2, 6)]
    [SerializeField] string question = "Enter new question text here";
```

클래스 안에 이거 넣어주면

![](https://velog.velcdn.com/images/biomatrix117/post/baa8a6f2-51f5-4a45-a5db-3a9dd26c9157/image.png)

등장

#### 게터 메서드

```cs
    [SerializeField] string question = "Enter new question text here";

    public string GetQuestion()
    {
        return question;
    }
```

캡슐화된 데이터 꺼내오는 메서드

#### 타이머 연결하기

SerializeField 걸어놓은 변수들 위에 종류별로 `[Header("Answers")]` 이런거 써 놓으면 Inspector에서 보기 편하다

### 타일바니아

Collider2D.IsTouchingLayers와 LayerMask.GetMaks("layer")로 점프 가능 여부 판단 가능 Cinemachine Virtual Camera > Extensions > Add Extension > CinemachineConfiner를 사용하면 카메라가 특정 영역에서만 움직이게 할 수 있다 Cinemachine State-Driven Camera를 사용하면 걸을 때와 뛸 때의 화면을 다르게 연출할 수 있다 Tilemap에 Bouncing Tilemap 만든 후에 Bounciness가 높은 Physics Material 2D를 연결하면 점프대 만들 수 있다. Friction 0으로 만들면 벽에 달라붙는 현상도 없앨 수 있음

### 레이저 디펜더

코루틴 사용법: 접근자랑 반환 형식 지우고 IEnumerator 써준 후에 yield return new `조건`; 써주고 StartCoroutine(`코루틴이름`); 싱글톤 패턴 쓸 때 이미 1개 있으면 Destroy()해버릴 때 SetActive()까지 해주면 좋다. 희박한 확률이지만 파괴되기 전에 접근할 수도 있기 때문.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://lazyartisan.gitbook.io/note/main-page/courses/c-unity-2d.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
