p330

충돌 메세지를 발생시키는 것은 리지드바디 컴포넌트이다.

따라서 충돌 이벤트 메서드를 사용하려면 서로 충돌중인 게임 오브젝트 중에서 최소 하나의 게임 오브젝트리지드바디 컴포넌트를 가지고 있어야 한다.

 

 

p331

OnCollision계열 : 일반 충돌

일반적인 콜라이더를 가진 두 게임 오브젝트가 충돌할때 자동으로 실행된다.

충돌한 두 콜라이더는 서로를 통과하지 않고 밀어낸다.

Oncollision계열 메서드가 실행될때는 메서드입력으로 충돌관련정보가 Collision타입으로 들어온다.

OnCollisionEnter(Collision collision) : 충돌한 순간
OnCollisionStay(Collision collision) : 충돌하는동안
OnCollisionExit(Collision collision) : 충돌했다가 분리되는 순간

Collision타입충돌관련정보를 담아두는 단순한 정보컨테이너이다.

따라서 입력으로 들어온 collision을 통해 충돌한 상대방 게임 오브젝트, 충돌지점, 충돌표면의 방향을 알 수 있다.

 

 

OnTrigger : 트리거 충돌

충돌한 두게임 오브젝터의 콜라이더 중 최소 하나가 트리거 콜라이더라면 자동으로 실행된다.

이경우 두게임 오브젝트가 충돌했을때 서로 그대로 통과한다.

onTriggerEnter(Collider other) : 충돌한 순간
onTriggerStay(Collider other) : 충돌하는 동안
onTriggerExit(Collider other) : 충돌했다가 분리되는 순간

OnTrigger 계열의 메서드가 실행될 때는 메서드 입력으로 충돌한 상대방 게임 오브젝트의 콜라이더 컴포넌트(Collider 타입)이 들어온다. 여기서 collision이 아닌 collider 타입을 입력받는 이유는 트리거 충돌에는 상세한 충돌 정보가 필요 없기 때문이다.

트리거 충돌은 일반적인 충돌과 달리 서로를 밀어내지 않고 그대로 통과합니다.

따라서 물리적 반발력이나 정확한 충돌 지점, 충격량 등이 존재하지 않으므

충돌한 상대방 게임 오브젝트(의 콜라이더 컴포넌트)를 곧장 받는다.

 

 

 

p535

일반 충돌이 시작되는 순간 실행되는 OnCollisionEnter()메서드와

충돌한 두 콜라이더가 서로 떨어지는 순간 실행되는 OnCollisionEnter()메서드

 

p554 게임오브젝트가 다른 게임 오브젝트를 물리적으로 밀어내면 안되니 추가한 박스 콜라이더2d컴포넌트는 트리거로 설정한다.

'공부' 카테고리의 다른 글

Mathf.Clamp  (0) 2026.02.26
void 함수, return  (0) 2025.12.29
using UnityEngine.SceneManagement;

 게임 재시작은 현재 활성화된 씬을 다시 로드하는 방식으로 구현할 수 있다

 

게임오버상태일때 게임을 재시작하는 기능을 만들자 

 

using TMPro;

// 점수를 출력할 UI 텍스트
public TextMeshProUGUI scoreText;

UI텍스트용 변수의 타입이 Text가 아닌 TextMeshProUGUI라는것에 주의하기.

Text타입은 UGUI의 빌트인 텍스트 컴포넌트 타입,

TextMeshProUGUI타입은 TextMeshProUGUI의 텍스트 컴포넌트 타입.

bool isGameover = false;

if (isGameover && Input.GetMouseButtonDown(0))
{
   SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}

&&는 그리고 라는 뜻이고, 

그럼 if문 조건은 if (isGameover && Input.GetMouseButtonDown(0))이거인데,

 

if (isGameover && Input.GetMouseButtonDown(0))은

if (isGameover == true && Input.GetMouseButtonDown(0) == true) 와 같다

즉, if (isGameover == true && Input.GetMouseButtonDown(0) == true) 이거임.

먼저 if문으로 isGameover가 true인지 확인하여 게임오버상태인지를 확인한다. 동시에 Input~(0)을 검사하여 마우스 왼쪽버튼을 눌렀는지도 확인한다.

 

C#에서는 bool 변수는 그냥 써도 "== true인지 검사한다"는 의미가 된다.

 

 

 

SceneManager.GetActiveScene()은 현재 활성화된 씬의 정보를 Scene타입의 오브젝트로 가져오는 메서드이다.

Scene타입의 오브젝트는 씬의 이름을 변수name으로 제공함.

SceneManager.GetActiveScene().name은 현재씬의이름을 가져온것임

 


 public void AddScore(int newScore) 
 {
     if(isGameover==false)
     {
         score = score + newScore;
         scoreText.text = "Score : " + score;
     }
     
 }

score +=newScore;이 단축형으로 자주쓰임 

 

 public GameObject gameoverUI; // 게임 오버시 활성화 할 UI 게임 오브젝트
 
 // 플레이어 캐릭터가 사망시 게임 오버를 실행하는 메서드
public void OnPlayerDead() 
{
    isGameover = true;
    gameoverUI.SetActive(true);
}

메서드가 실행될때 isGameover가 true되며, gameoverUi에 할당된 Gameover Text게임 오브젝트가 활성화됨

PlayerCtrller스크립트에서 Die()메서드에

//게임매니저의 게임오버처리실행

GameManager.instance.onPlayerDead();

씬에 유일하게 존재하는 GameManager오브젝트로 접근하는데 싱글턴 변수 GameManager.instance를 사용했음에 주목하자

 

 

 private void Update() {
     
     //게임오버가 아니라면
     if (GameManager.instance.isGameover == false)
     {
         // 게임 오브젝트를 왼쪽으로 일정 속도로 평행 이동하는 처리
         //초당 speed의 속도로 왼쪽으로 평행이동
         transform.Translate(Vector3.left * speed * Time.deltaTime);
     }
 }

ScrollingObject스크립트에서 Update()메서드에

     if (!GameManager.instance.isGameove)이렇게 이번에도 GameManager.instance로 씬의 GamaManager오브젝트에 손쉽게 접근했다는사실에주목하기

 

Clamp(클램프)

최소값/최대값을 설정하여 flaot 값이 범이 이외의 값을 넘지 않도록 한다.

변수값을 특정범위에서 벗어나지 못하게 잡아준다.

value가 min보다 작아지면 min값을 반환하고, max보다 커지면 max값을 반환한다.

public static float Clamp(float value, float min, float max);

 

 

 

https://iflife1124.tistory.com/11

https://asix.tistory.com/3

https://m.blog.naver.com/os2dr/221556053756

'공부' 카테고리의 다른 글

OnCollision일반충돌,OnTrigger트리거충돌  (0) 2026.03.02
void 함수, return  (0) 2025.12.29

기본 데이터 형식, 복합 데이터 형식

 

C#은 다양한 종류의 데이터 형식(Data Type)을 제공한다.

데이터 형식(Data Type) == 데이터 타입으로 읽어보기

 

텍스트를 다루는 데이터 형식(Data Type)은 물론, 이미지소리를 다룰 수 있는 데이터 형식(Data Type)도  제공한다.

 

C#이 제공하는 기본 데이터 형식에는 모두 15가지가 있는데, 이들은  크게 숫자형식, 논리형식, 문자열형식, 오브젝트 형식으로 나뉜다. 이중에서 문자열 형식과 오브젝트 형식만 참조 형식에 해당하며, 나머지는 값 형식이다.

 

복합 데이터 형식의 종류에는 구조체, 클래스, 배열 등이 있습니다.

데이터 형식은 기본 데이터 형식복합데이터 형식으로 분류하는 동시에, 값 형식참조 형식으로도 분류할 수 있습니다.

 


변수(Variable)

변수를 코드에서 보면 값을 대입시켜 변화시킬 수 있는 요소이지만,

메모리쪽에서 보면 '데이터를 담는 일정 크기의 공간'이라는 의미를 갖기도 한다.('일정크기'는 데이터 형식에 따라 결정된다.)

그러므로 C#코드를 작성하면서 변수를 만들때는 그 이면에 있는 메모리 세계도 함께 생각해야함.

'이 변수를 위해 메모리에 이만큼의 공간이 마련됐겠구나'정도로 생각하기.

 

코드 위에 뭔가를 '만든다'라는 표현은 잘 쓰지않고, '선언한다(Declare)'라고 쓴다.

'변수를 만든다' 대신에 '변수를 선언한다'라고 쓴다.

변수를 컴파일러한테 선언한다

우리가 변수를 하나 선언하면, 이것은 컴파일러에게 "이 변수에 필요한 메모리 공간을 예약해줘."라고 알린다는 뜻이다.

 

변수는 다음과 같은꼴로 만든다(선언한다).

이렇게 하면 컴파일러는 int형식을 위해 메모리공간을 할당하고, 이 공간을 x라는 식별자가 사용할 수 있도록 준비한다.

선언된 변수 x에는 대입 연산자를 통해 데이터를 입력할 수 있다.

이 코드가 실행되고 나면 x를 위해 할당된 메모리 공간데이터 100이 기록된다.

 

또, 선언과 데이터 할당을 동시에 할 수도 있다.

int x;           //선언

x = 100;      //데이터 할당을 별도로 할 수도 있지만

int x = 100; //선언초기화를 한 번에 할 수도 있다.

 

 

초기화(Initialization)란, 변수에 최초의 데이터를 할당하는 것을 의미한다.


 

 

값 형식, 참조 형식

값 형식 == 값 타입  ,   참조 형식 == 참조 타입  으로 읽어보기

 

값 형식은 변수가 을 담는 데이터 형식을 말하고,

참조 형식은 변수가 값 대신 값이 있는 곳의 위치(참조)를 담는 데이터 형식을 말한다.

이 둘을 이해하려면 C#으로 작성한 프로그램이 사용하는 두가지 메모리 영역에 대해 알고 있어야 함.

이 두가지 메모리 영역중 하나를 스택(Stack), 또 다른 하나를 힙(Heap)이라고 함.

이 두 메모리 영역 중에서 값 형식과 관련있는 것은 스택 메모리 영역, 참조 형식과 관련 있는 것은 힙 메모리 영역이다.

 


힙, 스택

참조 형식의 변수는 힙과 스택을 함께 이용하는데, 힙 영역에서는 데이터를 저장하고 스택 영역에는 데이터가 저장된 힙 메모리의 주소를 저장한다.

이제 왜 ' 참조 형식'이라는 이름이 붙여졌는지 감이 잡히는가?

데이터를 직접 저장하는 대신 실제 데이터가 저장된 메모리의 주소를 '참조'한다고 해서 '참조 형식'인 것이다.

 

 

 

 

 


object형식은 참조 형식이기 때문에 힙에 데이터를 할당한다.int형식이나 double형식은 값형식이기 때문에 스택에 데이터를 할당하고.

 

https://tech-runner.tistory.com/175

 


얕은 복사, 깊은 복사

Struct는 값 형식(Value)이다. 데이터 자체를 직접 저장하며, 변수에 할당될때 값이 복사된다.

이로 인해 각 변수는 독립적인 데이터를 가진다.

Class는 참조 형식(Reference Type)이다. 데이터의 참조(메모리 주소)를 저장하며, 변수에 할당될때 참조가 복사된다.

따라서 여러 변수가 동일한 객체를 참조 할 수 있다.

 

얕은 복사와 깊은 복사의 차이점은?

->얕은 복사는 객체의 '참조 값(주소)'만 복사하는 것이다.

깊은 복사는 객체의 모든 수준의 필드와 하위 객체까지 재귀적으로 복사하는 것이다. 원본객체가 참조하는 모든객체를 새로운 메모리 공간에 복사한다. 즉, 원본 객체와 복사된 객체가 독립적인 객체를 갖게 한다.

 

https://tech-runner.tistory.com/175

참고했습니다

'수업' 카테고리의 다른 글

260114  (0) 2026.01.17
261010  (0) 2026.01.10
260102  (0) 2026.01.05

플레이어 캐릭터의 상태를 나타내는 변수들중 하나

private bool isDead = false; 

 

if(isDead)

{

   //사망시 처리를 더이상 진행하지 않고 종료

    retrun;

}

 

if(Input.GetMouseButton(0)) && jumpCount < 2)

{

 

}

else if

 

~~등등

1.  난잡하게 하지말고, 뭘 테스트 하고 싶고, 어떤 가설을 세웠고 필기하면서 삽질노트 ㄱㄱ

 

2. 책 예제 연습시, 반드시 따라서 해보고  안보고 결과물을 직접 만들어보기

 

3. Mathf.Clamp를 안다뤘어도 함수로 어떻게 값이 변하는지 잘 따라가면 이해할 수 있음

'명심 명심 명심' 카테고리의 다른 글

유니티 할때 이렇게 해라  (0) 2026.01.05

닷넷 생태계

닷넷(.NET)은 소프트웨어 프레임워크로, 응용 프로그램의 개발 속도를 높이는데 도움이 되는 API(Application Programming Interface)  및 서비스 모음이라고 함.

닷넷 프레임 워크(.NET Framework), 닷넷 코어(.NET Core), 닷넷 스탠다드(.NET Standard)처럼 닷넷으로 시작하는 용어들은 모두 닷넷 생태계에 포함된다.

C#은 닷넷 생태계의 모든 영역에서 사용할 수 있는 프로그래밍 언어이다.

 

 

컴파일러

소스코드를 컴파일하여 실행파일로 만든다.프로그램을 실행하기 위해서는 '실행파일'만 있으면 되며, 소스코드는 전혀필요하지않습니다.

 

 

 

 

분류축

1.[언어 제공 여부]  → 기본 타입
2.[메모리 구조]    → 값 / 참조
3.[상속 구조]      → object 최상위

 

 

 

ex)  내가 만든 class Player

C#에서 모든 타입은 값 형식이든, 참조 형식이든, 사용자 정의든, 기본 제공이든 최종적으로 object를 상속한다

 


C#은 기본 데이터 형식을 부품으로 삼아 구성되는 "복합 데이터 형식(Complex Data Type)을 제공합니다.

데이터 형식(Data Type)

"기본 데이터 형식"과 " 복합 데이터 형식"이 있다.(크게 숫자 형식과 논리 형식,문자열 형식, 오브젝트 형식)

 

C#이 제공하는 기본 데이터 형식에는 모두 15가지가 있다.

이 중에서 문자열 형식오브젝트 형식참조 형식에 해당, 나머지는 모두 형식이다.(15가지 기본 자료 형식 중 12가지숫자 데이터 형식(정수계열, 부동소수계열, 소수계열 이렇게 3가지로 나뉜다)으로 제공하고 있다 -->즉 대부분이 형식이겠네?)                 p65  p85오브젝트형식

 

복합 데이터 형식의 종류에는 구조체클래스, 배열 등이 있다. 이미지나 소리 등의 데이터는 바로 이 복합 데이터 형식을 이용하여 나타낼 수 있다.

 

데이터 형식은 "기본 데이터 형식"과 "복합 데이터 형식"으로 분류하는 동시에 "" 형식과 "참조" 형식으로도 분류할 수 있다.

 

 

기본 데이터 형식으로는 int, float,char,bool등등...

복합 데이터 형식으로는 class등등...

 

값 형식(Value Types) 과 참조 형식(Reference Types)

 

값 형식 == 값 타입  ,   참조 형식 == 참조 타입  으로 읽어보기

 

 

값 형식은 변수가 담을 데이터를 말하고, 참조 형식은 변수가 값 대신 값이 있는 곳의 위치(참조)를 담는 데이터 형식을 말한다.

이 둘을 이해하려면 C#으로 작성한 프로그램이 사양하는 두가지 메모리 영역에 대해 알고 있어야 한다고 한다.

두가지 메모리 영역 중 하나는 스택(Stack), 다른 하나는 힙(Heap)이라고 한다.

이 두 메모리 영역 중에서 값 형식과 관련이 있는 것은 스택 메모리 영역, 참조 형식과 관련이 있는 것은 메모리 영역이다.

 

 

 

스택과 값 형식

값 형식의 변수는 모두 이 스택에 저장된다.

다시 말해, 코드 블록 안에서 생성된 모든 값 형식의 변수들은 프로그램 실행이 중괄호 " }"를 만나면 메모리에서 제거된다.

 

힙과 참조 형식

스택은 청소부가 필요 없을정도로 시민의식이 투철한 메모리 구조이다. 자신이 담고 있던 데이터가쓰레기가 되지 않도록 모수 수거해가니깐.

반면에 힙은 저장되어 있는 데이터를 스스로 제거하는 메커니즘을 갖고 있지 않다.

(대신 CLR의 가비지 컬렉터라는 청소부를 따로 고용)

 

프로그래머가 힙에 데이터를 올려놓으면, 코드블록이종료되는지점과는 상관없이 그데이터는 계속 생명을 유지한다. 그리고 이 데이터는 프로그래머가 더이상 사용하지 않는 쓰레기가 됐을때 가비지 컬렉터가 가져다버린다. 그제서야 메모리에서 사라지는것이다.

 

참조 형식의 변수는 힙과 스택을 함께 이용하는데,  영역에는 데이터를 저장하고 스택 영역에는 데이터가 저장되어 있는 힙 메모리의 주소를 저장한다.

데이터를 직접 저장하는 대신 실제 데이터가 저장되어있는 메모리의 주소를 "참조"한다고 해서 "참조 형식"인 것이다.

(왜 "참조 형식"이라고 이름이 붙여지는지 알 수 있음)

 

상수 (Constants), 열거형(Enumerator)

const

 

enum

 

 

 

코딩 기본 규칙

변수는 소문자 단어를 사용한다.

 

 

언매니지드언어/매니지드언어

언매니지드언어로는 C, C++,,,

매니지드언어로는 C#, JAVA, 파이썬,,,

 

정수계열 데이터 형식

데이터 형식 설명 크기(바이트) 담을 수 있는 값의 범위
byte 부호 없는 정수 1(8비트) 0 ~ 255
sbyte   1(8비트) -128 ~ 127
short      
ushort      
int 정수 4(32비트) - 2,147,483,648~
  2,147,483,647
unit unsigined int
부호없는 정수
4(32비트) 0 ~ 4,294,967,295
long 정수 8(64비트) -922,337,203.685.477,508~   922,337,203,685,477,507
ulong      
char 유니코드 문자 2(16비트)  

부동 수소점 형식

데이터 형식 설명 크기(바이트) 범위
float 단일 정밀도 부동 소수점 형식
(7개의 자릿수만)
4(32비트) -3.402823e38~3.4 02823e38
double 복수 정밀도 부동 소수점 형식
(15~16개의 자릿수만 다룰 수 있)
8(64비트) -1.79769313486232e308~
  1.79769313486232e308

 

IEEE754에 따르면 4바이트(32비트)크기의 flaot형식은 수로 표현할때 1비트를 부호전용으로 사용하고,

가수부 23비트를 수를 표현하는데 사용하고, 나머지 지수부 8비트를 소수점의 위치를 나타내기위해 사용한다.

오버플로우(Overflow) , 언더플로우(Underflow)

변수는 데이터를 담는 그릇과 같다. 그릇에 용량에 넘어서는 양의 물을 담으면 넘치는것처럼, 변수에도 데이터 형식의 크기를 넘어서는 값을 담게 되면 넘친다.

 

uint형 변수 a에 umt가 담을 수 있는 최 대값인 4,294,967,295를 넣어놓고 a에 1을 더해보자. 변수 a는 4294967295에 1을 더한 값인 4,294,967,296을 담을 수는 없습니다.

->결과는 오버플로우된 변수 a는 0을 가진다. uint가 가질 수 있는 최저값으로 돌아온 것.

 

각 데이터 형식의 최대값을 넘어가는 데이터를 저장할 때는 오버플로우가 일어나지만,

최저값보다 작은 데이터를 저장하면 언더플로우(Underflow)가 일어난다.

가령 byte 형식 변수에 -1을 담으려는 시도가 일어나면 실제로는 이 변수에 255가 담긴다.

 

 

 

 


모든 변수참조로 동작하는 것은 아니다.

float, int, string 등의 C#내장 변수는 참조로 동작하지 않는다. 이런타입을 값(Value)타입 이라고한다

참조 타입 변수는 값(실체)으로 향하는 참조를 저장하고, 값 타입의 변수는 해당 변수 공간에 값 자체를 저장한다.

 

우리가 사용할 변수 타입들을 구분하면 이렇다

참조 타입 값 타입
clas 타입

유니티의 모든 컴포넌트

우리가 작성할 C#스크립트
(MonoBehaviour를 상속받는 클래스)










C# 내장 변수
-bool
-int
-float
-char
-double
...

struct(구조체) 타입
-Vector3
-Color
...




몇가지 예외가 있지만 class로 만든 대부분의 타입참조로 동작한다. 

유니티의 게임오브젝트, 컴포넌트,C#의 많은 타입이 클래스로 정의되어있다.

C# 내장 변수 타입과 Vector3 같은 struct 타입을 제외하면 우리가 사용할 대부분의 변수는 참조 타입으로 동작한다.


참조 변수는 실체가 아니라 실체로 향하는 참조값을 저장한다.

변수의 참조값으로 실체에 접근하는 참조 타입 덕분에 변수로 씬에 있는 게임 오브젝트와 컴토넌트에 접근하고 이들을 조종할 수 있다.

 

유니티는 수많은 종류의 컴포턴트를 미리 만들어 제공한다. 컴포넌트는 클래스타입이다. 클래스 타입의 변수는 참조 타입으로 동작한다.

결론적으로 씬에 존재하는 모든 '실체'컴포넌트는 코드상에서 참조 타입의 변수로 가리키고 사용할 수 있다.

 

 

 

스태틱(static)

static은 객체마다 따로 존재하는 것이 아니라, 클래스에 단 하나만 존재하며 모든곳에서 공유된다.

그래서 static은 "객체를 만들 필요없이, 모두가 공유해야 할 기능이나 상태"에 사용한다.

 

출처: 레트로의유니티6게임프로그래밍에센스


 

 

출처 : C#교과서, 뇌를자극하는c# 5.0프로그래밍, 레트로의유니티6게임프로그래밍에센스

 

'수업' 카테고리의 다른 글

20260225-1  (0) 2026.02.26
261010  (0) 2026.01.10
260102  (0) 2026.01.05

수업전 햇갈린부분

헷갈렸던 부분은 두 번째 블록이 떨어질 때부터였습니다. 

isDroped = true의 유무와 상관없이 첫 번째 블록은 isFirst == true이기 때문에 Plane과의 물리 충돌 및 OnCollisionEnter 호출은 발생했지만, 
조건문에서 바로 return되어 충돌 처리 로직은 실행되지 않았습니다. 

두 번째 블록이 떨어질 때, 두 번째 블록은 isFirst == false 상태로 Block 태그를 가진 첫 번째 블록과 물리 충돌이 발생했고,
 그 결과 OnCollisionEnter 내부 로직이 실행되어 Debug.Log($"블럭에 닿음 Index : {index}")가 출력되었습니다. 반면, 첫 번째 블록은 isFirst == true 조건으로 인해 CompareTag("Block")를 통한 충돌 대상 판별 로직까지 도달하지 못했습니다. 

세 번째 블록부터는, 두 번째 블록과 세 번째 블록 모두 isFirst == false 상태이므로 양쪽 모두 CompareTag("Block")를 통해 충돌 대상을 판별할 수 있게 되었고, 
이로 인해 점수 증가 로직이 두 번 실행되는 현상이 발생했습니다. 
그래서 이미 한 번 쌓인 블록이 이후 충돌에 반응하지 않도록 하기 위해 " isDroped = true " 를 사용했습니다. 

제가 햇갈린건 
일단 OnCollisionEnter가 호출되려면 두 오브젝토 모두 Collider필요, 최소 하나는 Rigidbody필요, Trigger가 아니여야함(isTrigger==false).
첫번째 블록도 Plane에 닿아 있는 동안의 물리 충돌 상태는 항상 유지된다는 것을 알아야했는데 긴가민가한것 . 
isFirst, isDroped는 충돌을 막는 게 아니라 충돌 처리 로직을 막는다는것.
CompareTag는 충돌 이후 대상 판별용 조건이라는것이고, 충돌이 발생하면 "양쪽 오브젝트에서 각각 실행"된다는 것(한번의 물리충돌 -> 두개의 OnCollisonEnter -> 각각 CompareTag 실행)

 

**   collision.transform.CompareTag("Block") 이 코드의 의미는

                                                     " 지금 나랑 부딪힌 상대 오브젝트의 태그가 Block인가?" 

     즉, CompareTag는 충돌이 나면 부딪힌 두 오브젝트에서 각각 실행된다 **

 

 

디버깅

-현재상황을 인식하기

- Ai는 디버깅을 못하는 경우가 많다.

- 둘이 판별 할 수 있는 무언가가 필요하다. 예를 들면 이름,, 우리 경우엔 이름이 없으므로 index를 만들어서 번호를 매겨주면 판별할수 있겠지?

blockSpawner.cs에서  public int currentIndex = 0;선언,  reateBlock()시 currentIndex += 1;코드 추가.

Block.cs에서

public int index = 0; 

collision.transform.CompareTag("Block")라는 충돌이후 대상  Debug.Log($"블럭에 닿음 Index : {index}");

 

 

'수업' 카테고리의 다른 글

20260225-1  (0) 2026.02.26
260114  (0) 2026.01.17
260102  (0) 2026.01.05

정리필요

 

인스턴스

 

 

 

static 스태틱

-유니티에서 알게 모르게 쓰고있던 Static들

   ->클래스 인스턴스를 생성하지 않고 바로 사용한것이 Static이라 했다.

      GameObjec.Find("Player");

      우리가 자주 썼던 이 함수 또한 원래라면 인스턴스 생성하고 써야 했지만, Find함수는 Static으로 만들어졌기 때문에 그냥 바로       클래스에서 접근이 가능하다.

 

 

 

싱글톤

 

gpt는 도구로 사용하기

ex)방법을 알려줘(방법 서칭용)

->canvasr가뭐지?color가 뭐지?같은 기능을 묻는건 ok

->유니티 리지드바디의 Interpolate와 Collision Detection에 대해 설명해줄래?

 

인스펙터의 rigidbody 기능 알아보기- 어떤 상황에서 어떻게 쓰이는지 학습하기ex)Mass, Linear Damping

숙제

1.간단한 UI 추가해서 블럭이 쌓일때마다 1점씩 추가

2. [선택사항]
시간이 지날수록 또는 떨어트린 블럭의 개수가 많아질수록 난이도 증가
특수 블럭 같은거 : 골든 블럭 ( 점수 2배 ) , 짱큰 블럭  ( 더 큰 크기), 개빠른 블럭 (좌우 움직이는게 엄청 빠른 블럭)

 

 

 

 

 


오프셋

기준 위치는 오브젝트의 원래 위치이다.

 

Offset은 기준 위치에서 얼마나 떨어졌는지를 나타내는 변화량이다.
기준 위치 자체는 포함하지 않는다.

Sin 값(Mathf.Sin)은 -1 ~ 1 사이를 오가는 파형 값이며, 그 자체로는 Offset이 아니다.

Sin 값에 거리(range)를 곱하면 실제 Offset이 만들어진다.

최종 위치는 항상 기준 위치 + Offset으로 계산된다.

즉,

기준 위치 → startX
Offset → x
결과 위치 → startX + x

 

기준 위치까지 포함된 값은 Offset이 아니라 “결과 위치”이다.

이 개념은 위치 이동뿐 아니라회전, 스케일, 카메라 흔들림 등모든 진동 표현의 기본 구조이다

 


Unity Rigidbody의 Collision Detection(충돌 감지)

충돌 감지 방식은 물리 엔진이 얼마나 정밀하게 충돌을 계산할지 결정합니다.

네가지 옵션 Discreate, Continuous, Continous Dynamic, Continuous Speculative이 있음.

 

빠르게 움직이는 발사체(총알, 미사일), 고속이동캐릭터. 얇은 벽이나 바닥이 있는 게임에서 터널링을 방지하려면 Continous Dynamic 이상을 사용해야 합니다. 느리게 움직이거나 큰 객체는 Discreate로 충분합니다

 

Discreate: 기본 설정, 각 물리 프레임마다 한 번만 충돌을 체크합니다. 빠르지만 빠르게 움직이는 객체가 얇은 벽을 통과하는 "터널링" 현상이 발생할 수 있습니다.

 

Continuous: 정적 메시 콜라이더(static mesh collider)에 대해 연속적인 충돌 감지를 수행합니다. 움직이는 객체가 정적인 벽을 뚫고 지나가는 것을 방지합니다.

 

Continuous Dynamic: 다른 동적 객체와 정적 객체 모두에 대해 연속 충돌 감지를 수행합니다.

가장 정밀하지만 성능 비용이 높습니다.

 

Continuous Speculative: 연속 충돌 감지를 사용하되 추측 기반으로 작동해서 Continuous Dynamic 보다 성능이 좋습니다. 

 

참고자료

https://garagefarm.net/ko-blog/collision-detection-in-2d-and-3d-concepts-and-techniques

https://blog.naver.com/PostView.nhn?blogId=jerrypoiu&logNo=221172549241

 

 

 


raycast

Debug.DrawRay(dropBlock.transform.position, dropBlock.transform.up * -checkDistance, Color.red);
if(Physics.Raycast(dropBlock.transform.position, dropBlock.transform.up * -1f, out RaycastHit hit, checkDistance))
{
    Debug.Log("닿음");

    if(hit.collider.CompareTag("Plane"))
    {
        Debug.Log("게임오버");
    }

    if(hit.collider.CompareTag("Block"))
    {
        Debug.Log("블럭에 닿음");
        dropBlock.GetComponent<Rigidbody>().constraints = RigidbodyConstraints.FreezeAll;
        dropBlock.GetComponent<Rigidbody>().isKinematic = true;
    }
}

 

 

hit 6 개를 많이 쓴다(정리하기)

hit.normal

hit.collider ( 예시: hit.collider.CompareTag("Block")처럼~  ) 

 


OnCollisionEnter

private void OnCollisionEnter(Collision collision){}

"물체가 처음으로 다른 물체와 부딪히는 순간 자동으로 실행되는 함수"다

 

* Collision collision: 부딪힌 상대 정보가 들어 있음. 누구랑 부딪혔는지 알려주는상자. 예를 들면 바닥인가? 블럭인가? 어떤 GameObject인가?이런

 

*On: ~했을때 ,  Ondestory나 OnCollisionEnter처럼

*둘 다 collider가 있어야함(둘다 Is Trigger 꺼져있어야함)+ 둘 중 하나 이상 rigidbody가 있어야함(Rigidbody가 없으면 안불린다.).

 

private void OnCollisionEnter(Collision collision){}이런식으로 쓰며, 

OnCollisionEnter함수안에 if문으로 collision.transform.CompareTag("Plane") 이렇게 쓸 수 있음.

* 쓰다가 문득 생각이 난건데, transform.CompareTag도 가능하지만 당연히 GameObject.CompareTag도 가능함

 

 

 

 


isDrop 기본값을 false로 시작하는이유

public bool isDrop = false;

 void Update()
 {
     if (isDrop == true)
     {

     }
     else
     {
         Move();
     }

 }

처음 보면 이 코드가 "false니까 뭔가 예외처리인가?"라고 햇갈릴 수 있다.

하지만 isDrop은 예외처리용 변수가 아니라 "상태(state)"를 나타내는 변수다.

 

왜 기본값을 false로 시작하나?

블록의 흐름을 생각해보면 생성됨, 좌우로 움직임, 떨어짐, 충돌 등  이과정에서 블록은 대부분의 시간동안 '아직 떨어지지않은 상태'이고, Drop()이라는 특정 이벤트가 발생한 뒤에만 상태가 바뀐다.

그래서 대부분의 시간 = false, 특정 이벤트(Drop)에서만 true 이흐름이 자연스럽기 때문에 isDrop의 기본값을 false로 둔다.

 

예외처리랑 햇갈리는 이유

if (isFirst == true)
{
    return;
}

이건 "특정 조건에서는 이 로직을 아예 실행하지 마라"라는 예외(가드) 처리이다.

반면 isDrop은 한번 걸러내고 끝내는 예외X, 계속 유지되는 현재 상태O  라는 점에서 성격이 완전히 다르다.

 

IF문 안이 비어 있는게 낯선 이유

if (isDrop == true)
{

}
else
{
    Move();
}

"이미 떨어진 상태라면 아무것도 하지말고, 아직 떨어지지 않았다면 움직여라."

즉, if(isDrop == true)는  무언가 하라는 조건이 아니라, Move를 하지말아야하는 상태를 표현한것이다.


예외처리

Spawner.cs의 코드

block.isFirst = isFirstBlock;
isFirstBlock = false;

이코드는 "이 블록이 예외 대상인지 아닌지 딱 한번 결정해준다"

 

Block.cs의 코드

 // 대충 처음이면 리턴하고 처음 아니면 아래 코드 진행
 if(isFirst == true)
 {
     return;
 }

 

 if (collision.transform.CompareTag("Plane"))
 {
     Debug.Log("게임오버");
 }

//제일 처음 떨어지는 블록이 plan과 닿았을때는 "게임오버"가 되면 안된다

 if (collision.transform.CompareTag("Block"))
 {
     Debug.Log("블럭끼리 닿음");
     GetComponent<Rigidbody>().constraints = RigidbodyConstraints.FreezeAll;
 }

여기서의 if (isFirst == true) 코드는 " 예외 대상이면 이 함수는 아무 일도 안하고 끝낸다"

 

이 둘은 이렇게 연결되돼 있다.

 

[Spawner]
  └─ 너는 첫 블록이야? (isFirstBlock)
        ↓ 값 전달
[Block]
  └─ 아, 난 첫 블록이구나 (isFirst)
        ↓
  └─ 그럼 충돌 판정 무시

 

결론: Spawner는 ‘예외 대상’을 결정하고, Block은 ‘예외일 때 행동하지 않는다'.

 


간단한 UI추가해서 블럭이 쌓일때마다 1점씩 추가하기(숙제)

 

1.Canvas생성

Hierarchay창에서 빈공간 우클릭 -> UI에서 Canvas 선택 ->그러면 Canvas,EvantSystem이 자동으로 생성됨

 

2. Text생성

생성된 Canvas 오브젝트를 우클릭 -> UI에서 Text-TextMeshPro선택 -> 처음 사용시 "Import TMP Essentials"팝업이 뜨면 Import 클릭

 

3. Text 설정

생성된 Text 오브젝트 선택 -> Inspector에서 Text Input에 "Score:0" 입력

 

4.ScoreManager 오브젝트 생성

Hierarchy 빈 공간 우클릭 -> Create Empty(빈오브젝트 생성) -> 이름을 "ScoreManager"로 변경 -> ScoreManager 스크립트 드래그해서 추가 -> Score Text 필드에 위에서 만든 Text 오브젝트를 드래그

'수업' 카테고리의 다른 글

20260225-1  (0) 2026.02.26
260114  (0) 2026.01.17
261010  (0) 2026.01.10

-결과물을 아니까 그걸 토대로 다시 만들어보면서 필요한 지식들 검색해보고 정리해보기도 하면서 다시 익히는것

 

-남에게 설명하기 위한 목적으로 서술하기

 

-핵심, 기능 위주, 방법 위주로 서술하기

 

-수업때 새로운 개념 배웠을때 정리하기

 

 

 

ex) origin을 어떻게 설정했어야 했을까

ex) if문으로 예외처리하는 것들

ex)어떻게해야할지~ 등의 기법들 생각해보기

ex)충돌체크를 어떤식으로 할까?->레이캐스트에 대한걸 정리

'명심 명심 명심' 카테고리의 다른 글

이렇게 항상 유니티해라  (0) 2026.02.25

+ Recent posts