Unity 개인 공부

Unity 개인 공부(2025-01-18)

kimjunki-8 2025. 1. 18. 23:32
제네릭
아까 List에 대해 조금 더 자세히 알아보겠습니다.
List<int> nums = new List<int>();
nums.Add(2);
nums.Add(5);​
여기서 제네릭이란 개념이 나옵니다.
제네릭이란?
제네릭(Generic)은 C#과 같은 프로그래밍 언어에서 데이터 타입을 일반화하여 코드의 재사용성과 타입 안전성을 높이는 기능입니다. 제네릭을 사용하면 클래스, 메서드, 인터페이스 등을 선언할 때 데이터 타입을 고정하지 않고, 나중에 사용할 때 특정 데이터 타입을 지정할 수 있습니다. 

자 그런데 여기선 짧게 가겠습니다 왜냐? 제네릭은 고급 개념이므로...
일단 설명을 하면,

1. List<int>의 의미
List<T>는 제네릭 컬렉션(Generic Collection)입니다.
여기서 <T>는 리스트가 저장할 데이터 타입을 지정하는 제네릭 타입 매개변수입니다.
List<int>는 int형 데이터를 저장할 수 있는 리스트를 생성하겠다는 의미입니다.
즉, 제네릭(Generic)을 사용해서 저장할 데이터의 타입을 미리 지정해주는 것입니다.
예: List<string>은 문자열 저장.
예: List<double>은 실수 저장.
System.Collections.Generic 네임스페이스에 포함되어 있습니다.

2. new List<int>()의 의미
new 키워드: 새로운 객체를 힙 메모리에 할당합니다.
List<int>() 생성자 호출: 리스트 객체를 초기화합니다. 생성된 리스트는 초기에는 아무 요소도 포함하지 않습니다.

3. 전체 선언
List<int> nums: 정수형 리스트를 참조할 변수를 선언합니다.
= new List<int>();: 새로운 List<int> 객체를 생성하고, 이를 nums라는 변수에 할당합니다.

특징 및 주요 기능
크기 자동 조정
List는 배열과 달리 크기를 미리 지정하지 않아도 됩니다.
요소를 추가하면 리스트의 크기가 자동으로 증가하고, 제거하면 줄어듭니다.

요소 추가 및 삭제
Add(): 리스트 끝에 요소를 추가합니다.
예: nums.Add(2);
Remove(): 특정 값을 리스트에서 제거합니다.
예: nums.Remove(5);
RemoveAt(): 특정 인덱스의 요소를 제거합니다.
예: nums.RemoveAt(0);

요소 접근
리스트의 요소는 인덱스(index)로 접근할 수 있습니다.
예: int firstElement = nums[0];

반복 처리
리스트는 반복문을 사용하여 요소를 쉽게 순회할 수 있습니다.
foreach (int num in nums)
{
    Console.WriteLine(num);
}

정렬 및 검색
Sort(): 리스트의 요소를 정렬합니다.
예: nums.Sort();
Contains(): 특정 값이 리스트에 포함되어 있는지 확인합니다.
예: bool exists = nums.Contains(5);

메모리 구조
스택: nums라는 변수는 스택에 저장되며, 힙 메모리에서 생성된 List<int> 객체를 참조합니다.
힙: new List<int>()에 의해 할당된 리스트 객체는 힙 메모리에 저장됩니다. 리스트가 커질수록 동적으로 메모리가 할당됩니다.


즉, 이 코드는 "비어 있는 정수형 리스트(List)를 생성해서 변수 nums에 넣는다"는 뜻입니다.

참고로, ()는 생성자(Constructor)를 호출하는 기호입니다. 비어 있는 ()는 매개변수가 없는 기본 생성자를 호출할 때 사용하며, 생성자에 값을 전달해야 할 때는 () 안에 값을 넣습니다. 생성자 외에도 {}로 초기화를 할 수 있는 경우가 있습니다. (컬렉션 초기화 같은 경우)

()는 생성자(Constructor)를 호출하기 위한 기호입니다.
생성자는 객체를 초기화할 때 사용하는 특별한 메서드입니다.
List<int> 클래스에는 기본 생성자(Default Constructor)가 제공되는데, 이 생성자는 아무것도 받지 않고 빈 리스트를 만들어줍니다.

비어 있는 이유
기본 생성자는 매개변수가 필요 없기 때문에 ()를 비워둬도 되며,
여기서 new List<int>()는 List를 초기화하면서 아무 값도 전달하지 않는 생성자를 호출한 것입니다.

그러면 생성자는 또 뭔데?

생성자
생성자란?
생성자(Constructor)는 어떤 물건(객체)을 처음 만들 때 사용되는 특별한 "설명서" 같은 것입니다.
이 설명서를 따라 물건을 만들고, 필요한 재료나 설정을 할 수 있습니다.
2. 간단한 예: 쿠키 만들기
우리가 "쿠키"를 만드는 기계라고 생각해보면,
쿠키를 만들려면 처음부터:
쿠키의 모양
쿠키의 크기
쿠키의 맛
이런 것들을 정해져야 하며,
이때 "쿠키를 만들 때 초기 설정을 도와주는 것"이 바로 생성자입니다.

사실 생성자는 클래스의 개념을 이해해야 합니다. 참고로 파이썬의 클래스와 느낌이 다르기에, 일단 여기서 간단하게 설명만 하겠습니다.

C#에서 쿠키를 만드는 기계를 클래스로 표현하고, 쿠키를 처음 만들 때 설정을 생성자로 표현해본다면, 
public class Cookie
{
    public string Shape; // 쿠키 모양
    public int Size;     // 쿠키 크기
    public string Flavor; // 쿠키 맛

    // 생성자: 쿠키를 만들 때 모양, 크기, 맛을 정함
    public Cookie(string shape, int size, string flavor)
    {
        Shape = shape;   // 모양 설정
        Size = size;     // 크기 설정
        Flavor = flavor; // 맛 설정
    }
}

// 쿠키를 만들어 보자!
Cookie myCookie = new Cookie("별", 5, "초콜릿");

 


내가 찾은 배워야할 개념들
1. 기초
1.1. 데이터 타입 (Value Types, Reference Types)
1.2. 변수와 상수 (Variables, Constants)
1.3. 연산자 (Operators)
1.4. 조건문 (if, else, switch)
1.5. 반복문 (for, while, do-while, foreach)
1.6. 배열 (Arrays)
1.7. 문자열 처리 (String Manipulation)
1.8. 함수 (Methods)
1.9. 클래스와 객체 (Classes and Objects)
1.10. 네임스페이스 (Namespaces)

2. 객체지향 프로그래밍 (OOP)
2.1. 클래스와 객체
2.2. 생성자와 소멸자 (Constructors, Destructors)
2.3. 접근 제한자 (Access Modifiers: public, private, protected, internal)
2.4. 상속 (Inheritance)
2.5. 다형성 (Polymorphism)
2.6. 메서드 오버로딩 (Method Overloading)
2.7. 메서드 오버라이딩 (Method Overriding)
2.8. 추상 클래스 (Abstract Classes)
2.9. 인터페이스 (Interfaces)
2.10. 캡슐화와 프로퍼티 (Encapsulation and Properties)

3. 고급 문법
3.1. 제네릭 (Generics)
3.2. 컬렉션 (Collections: List, Dictionary, Queue, Stack)
3.3. 델리게이트 (Delegates)
3.4. 이벤트 (Events)
3.5. 람다 표현식 (Lambda Expressions)
3.6. 익명 함수 (Anonymous Methods)
3.7. LINQ (Language Integrated Query)
3.8. 확장 메서드 (Extension Methods)
3.9. nullable 타입과 null 병합 연산자
3.10. 튜플 (Tuples)

4. 예외 처리
4.1. try-catch-finally
4.2. 예외 클래스 (Custom Exceptions)
4.3. using 문과 Dispose 패턴

5. 파일 입출력
5.1. 파일 읽기 및 쓰기 (File I/O)
5.2. 스트림 (Streams)
5.3. JSON 처리 (Newtonsoft.Json, Systehttp://m.Text.Json)
5.4. XML 처리

6. 비동기 프로그래밍
6.1. async와 await
6.2. Task와 Task<TResult>
6.3. 비동기 스트림 (Async Streams)

7. .NET 라이브러리와 기술
7.1. .NET의 주요 라이브러리 이해
7.2. System.Collections.Generic
7.3. System.Linq
7.4. System.Threading

8. 고급 기술
8.1. Reflection
8.2. Attributes
8.3. Dynamic 타입
8.4. 메모리 관리 (Garbage Collection, IDisposable)
8.5. 이벤트와 대리자 심화
8.6. 함수형 프로그래밍 (Functional Programming)

9. 응용
9.1. Windows Forms 또는 WPF
9.2. ASP.NET Core (웹 개발)
9.3. Entity Framework (데이터베이스 연동)
9.4. Blazor (웹 프론트엔드)
9.5. 게임 개발 (Unity에서의 C#)

10. 최적화 및 배포
10.1. 성능 최적화 (Performance Optimization)
10.2. 디버깅 (Debugging)
10.3. 코드 분석 및 프로파일링
10.4. 배포 및 빌드 (Deployment, Build Systems)

조건문
드디어 조건문입니다.
파이썬에선 
If 조건:
을 했다면,

C#에서는 
if (조건) {로직}을 해야합니다(참고로 조건은 ()로 감싸야함)
int a = 10;
if (a == 10) {
    Debug.Log($"A는 {a}입니다.");
}​

 

대충 이런식으로...
참고로 else도 else {}처럼 쓰면 됩니다.

참고로 파이썬에 elif가 있다면 C#에는 else if로 써야합니다.

switch, case
사용법
switch (변수) {
	case 값1:
    	break;
	case 값2:
    	break;
	case 값3:
    	break;
}​

 

여기서 각 case마다 break;는 필수
switch 문은 하나의 변수 값을 여러 경우에 따라 처리할 때 사용하는 조건문이야.

switch 문의 동작 원리
변수의 값을 확인한다.
case 뒤에 적힌 값과 변수의 값이 일치하는 경우를 찾는다.
일치하는 case의 코드를 실행한다.
break를 만나면 switch문을 빠져나간다.
일치하는 case가 없으면 default 블록을 실행한다. (선택 사항)

더 자세히 알아보면,

예시:
int day = 3;

switch (day)
{
    case 1:
        Console.WriteLine("월요일");
        break;
    case 2:
        Console.WriteLine("화요일");
        break;
    case 3:
        Console.WriteLine("수요일");
        break;
    case 4:
        Console.WriteLine("목요일");
        break;
    case 5:
        Console.WriteLine("금요일");
        break;
    default:
        Console.WriteLine("주말");
        break;
}

day의 값이 3이므로:
case 3: 블록을 실행 → "수요일" 출력.
break를 만나면 switch문을 빠져나간다.


default 블록
default는 case들 중 아무것도 일치하지 않을 때 실행되는 코드야.위 예제에서 day 값이 6이나 7이라면 default 블록이 실행되고, "주말"이 출력된다.

아니 그런데 이러면 if-else문하고 비슷하지 않은가? 그렇지는 않습니다.
switch 문이 유용한 경우
여러 값을 비교해야 할 때, if-else보다 깔끔하게 사용할 수 있습니다.
예를 들어, 버튼 입력, 메뉴 선택 등 값에 따라 다른 작업을 해야 할 때 유용합니다.
int f = 5;
switch (f) 
{
    case 1:
    Debug.Log("1입니다.");
    break;
    case 2:
    Debug.Log("2입니다.");
    break;
    case 3:
    Debug.Log("3입니다.");
    break;
    default: 
    Debug.Log("확인 불가");
    break;
}

최종 예시

Console.WriteLine, Console.Write
간단합니다.
WriteLine의 특징 문장을 출력한 후 줄을 바꿔준다.
Console.WriteLine("첫 번째 줄");
Console.WriteLine("두 번째 줄");

출력:
첫 번째 줄
두 번째 줄​


값도 출력할 수 있다.

int number = 10;
Console.WriteLine(number); // 10 출력


값과 문자열을 섞어서 출력 가능

int age = 25;
string name = "Alice";

Console.WriteLine("이름: " + name + ", 나이: " + age); // "이름: Alice, 나이: 25"
Console.WriteLine($"이름: {name}, 나이: {age}");      // 같은 결과

 

WriteLine: 출력 후 줄을 바꾼다.
Write: 출력 후 줄을 바꾸지 않는다.

그냥 Write

Console.Write("첫 번째 문장 ");
Console.Write("두 번째 문장 ");
Console.WriteLine("세 번째 문장");
Console.WriteLine("네 번째 문장");

출력:
첫 번째 문장 두 번째 문장 세 번째 문장
네 번째 문장

그런데.....사실 Unity에서는 Console.WriteLine 못 씁니다. C# 전용이지, Unity 환경에서는  Debug.Log써야합니다.


하지만 이렇게 보면 if-else문이랑 솔직히 다른 느낌이 안 납니다.
그래서 사실 case문을 서로 묶을 수도 있습니다.
int f = 7;
switch (f) 
{
    case 1:
    case 7:
    Debug.Log("1혹은 7입니다.");
    break;
    case 2:
    Debug.Log("2입니다.");
    break;
    case 3:
    Debug.Log("3입니다.");
    break;
    default: 
    Debug.Log("확인 불가");
    break;
}​

저렇게 case1:, case7:을 묶으면 두개 중 하나라도 맞을 시 그에 맞는 로직이 실행이 됩니다.


반복문
while -> 조건이 True일 때, 로직 반복 실행.
파이썬이랑 비슷하다
while (조건) {
	로직
}​

 

대충 이렇게 만듭니다.
while (h < 20) {
    Debug.Log(h);
    h+=1;
}​


파이썬에선

a = 1
while a < 5:
  print(a)
  a+=1

이렇게 쓸 수 있습니다.
단, 알아야 할 사실이 있습니다.

파이썬
a+=1 -> a = a + 1

C#
a++ -> a + 1
혹은
a+=1 -> a = a + 1

이렇듯, C#에서는 두개의 방법으로 1을 더해갈 수 있습니다.

자 여기서 잠깐 꿀팁

int h = 6;
while (h > 0) {
    Debug.Log(h);
    h--;
    if (h == 1) 
        Debug.Log("1남음");
    else
        Debug.Log("살아있어");
    
}

여기서 한번 봅시다.
문제는 없어보이지만, 뭔가 이상합니다 바로 if 문에서 {}으로 로직은 감싸지 않았습니다.

하지만 문제 없이 작동합니다. 왜 그럴까요?
C#에서 if문은 단일 문장(statement)일 때 중괄호 {} 없이 사용할 수 있습니다. 그렇기 때문에 위 코드는 문제없이 작동하는 겁니다. 하지만 여러 문장(statement)을 포함하려면 반드시 중괄호 {}로 감싸야 합니다.

if나 else 뒤에 단일 문장만 있다면 중괄호 {} 없이 사용해도 됩니다.

int x = 5;

if (x > 3)
    Console.WriteLine("x는 3보다 큽니다.");
else
    Console.WriteLine("x는 3보다 작거나 같습니다.");


만약 if 또는 else 뒤에 두 개 이상의 문장이 있다면 반드시 중괄호 {}로 감싸야 합니다.

if (h == 1)
{
    Debug.Log("1남음");
    Debug.Log("이건 if 내부입니다!");
}

 

하지만 가독성과 유지보수성을 생각하면 항상 써주는게 좋습니다.
왜냐하면 C#에서는 {}은 거의 필수이기 때문에 잘못하면 코드를 잘못이해할 수 있기 때문입니다.

 for문.....파이썬과 어떤점이 다를까요?
쓰는 방법은 while문과 같습니다.
for (연산될 변수; 조건; 연산) {
    로직
}​
for은 ()안에 저렇게 3가지가 들어가게 됩니다.
파이썬은 for x in y:로, y에 있는 값을 하나씩 꺼내서 x에 넣는 것과 다르게 나옵니다.

하지만 C#에서 반복문을 쓰는 이유는 그룹형 변수와의 조합입니다.
string[] monsters = {"사람", "동물", "곤충"};
for (int list_len = 0; list_len < monsters.Length; list_len ++) {
    Debug.Log($"종류들: {monsters[list_len]}");
}​

 

이렇게 배열을 하나 만들고 0을 가진 숫자 list_len을 만들고, 그리고 조건은 list_len < monsters.Length
즉, 0<3인것을 알 수 있습니다. 0부터 2까지. 그리고 연산은 list_len++로 돌때마다 1씩 더하는 것으로 했습니다.
참고로 저기 저 .Length는 파이썬의 len(monsters)와 같습니다.

그러면 

Debug.Log($"종류들: {monsters[0]}");
Debug.Log($"종류들: {monsters[1]}");
Debug.Log($"종류들: {monsters[2]}");
이렇게 값이 들어가게 됩니다.

참고로 이렇게 말고 진짜 파이썬의 for문 같은 녀석이 있습니다.
바로 foreach문 입니다.
foreach (string monster in monsters) {
    Debug.Log(monster);
}​

 

이렇게 사용합니다.
위에 방법과 비슷하게 가져오지만, 이건 파이썬의 방식이랑 정말 비슷합니다.
저 in 보이시나요 저건 파이썬 for문에 있는 for in에서 in과 똑같은 역할을 합니다.
즉, monsters에 있는 값들을 하나씩 가져오는 역할을 합니다.
그리고 하나씩 받은 값들을 string monster라는 새로운 변수에 넣어주는 역할을 하며, 그것을 Debug.Log로 보여줍니다.

함수
파이썬의 함수와 비슷합니다. 하지만 어떤 부분은 또 다르죠. 그 부분을 설명하겠습니다.
먼저 플레이 버튼을 누르면 그 값들이 나올 수 있었던 이유가 바로 void Start()라는 함수 덕분입니다.
먼저 간단한 함수 만드는 법을 알아보겠습니다.
int function(int fun) 
{
    로직
}​

 

대충 이렇게 생겼습니다.
먼저, 저 function이라는 함수 앞에 붙은 int은 이 function의 형태가 아니라, 나중에 반환할 값의 타입을 지정하는 것입니다. 그리고 저 ()안에는 어떤 값을 줄 것인지(파이썬에서는 매게변수 느낌) 정하는 것입니다.

함수를 하나 만들었습니다.

int sums(int f) 
{
    f += 20;
    Debug.Log(f);
    return f;
}

 

참고로 이 함수는 Start 함수 밖에서 만들었습니다.

그리고 Start 함수 안에 
f = sums(f);​

 

이렇게 써 넣으면 27이 정삭적으로 나옵니다.

그런데 신기하지 않으신가요? 사실
f = sums(f);이것은  저 sums 함수 보다 위에 작성되어 있습니다.
파이썬은 위에서 아래로 코드를 읽어서 함수가 먼저 정의되어 있지 않으면 사실상 될 수 없는 구조입니다.
하지만, C#은 실행 전에 컴파일 과정에서 코드를 분석합니다. C#의 함수 호출 구조는 프로그램의 전체 코드 맥락을 이해하고, 정의된 함수들을 미리 인지할 수 있습니다. 그래서 호출 위치가 함수 정의보다 위에 있어도 동작합니다.

즉, 받은 값을 받아서 그 값에 20을 더해주고 반환하는 함수 입니다.

자 그런데, 위에 보면
void Start()

가 있습니다. 저 void란건 뭘까요?

여기서 파이썬에도 그렇고 C#에서도 그렇고 반환하는 값이 없을 수 있습니다.
하지만 C#에서는 그것을 알려줘야 하기때문에, 그 알리는 것을 void를 써서 알립니다.
즉, void는 값을 반환하지도 않고, 반환하지 않기에 타입도 없다라는 뜻입니다.

한번 반환하지 않고 그냥 실행만 시켜주는 함수를 만들어 보겠습니다.

void sums() 
{
    f += 20;
    Debug.Log(f);
}

이렇게 만들었습니다.
그런데 어? 저 f는 그럼 어디서 받아오죠? 하실 수 있습니다.
여기서 파이썬 아시죠?
지역변수 -> 함수 안에서 선언된 변수. 즉, 다른 함수에는 못 쓴다. 저 f는 start함수에 쓰였으므로)

이럴때는 그냥 가장 밖에 즉, 클래스 바로 밑쪽에 선언하면 됩니다. 파이썬에서 했던것처럼 그냥 함수 밖에 선언한다 라고 생각 하시면 됩니다.

public class NewMonoBehaviourScript : MonoBehaviour
{
    int f = 15;
    void Start()

이렇게 말입니다.
이러면 거의 모든 함수에서 이 변수를 사용할 수 있습니다.
즉, 이것은 전역변수라고 합니다 -> 함수 바깥에 선언된 변수

이러고 Start 함수에 sums()를 호출하면 제대로 작동합니다....
라고 하기에는 이상하지 않으신가요?
python에서는 저렇게 작동하지 않습니다.

a = 2
def sums():
  a += 2
sums()

이것은 무조건 에러가 납니다.
Python에서는 함수 내부에서 변수를 사용할 때, 해당 변수를 함수 내부에서 수정하면 Python은 그 변수를 로컬 변수로 간주합니다. 따라서 아래 코드에서 a는 함수 내에서 로컬 변수로 처리되려고 하지만, a += 2는 a를 먼저 읽고 수정하려고 하므로, 아직 초기화되지 않은 로컬 변수를 참조하려 한다는 점에서 오류가 발생합니다.
즉, 파이썬에서는 sums 함수에 매게변수를 받을 수 있게 해주거나, 혹은 global을 써서 전역 번수임을 명시해야 합니다.

a = 2
def sums():
    global a
    a += 2
    print(a)
sums()
이렇게 하거나

a = 2
def sums(a):
    a += 2
    print(a)
sums(a)
이렇게 해야합니다.


하지만

int a = 2; 
void sums() 
{
    a += 4;
    Debug.Log(a);
}
sums()

이건 C#에서는 가능합니다. 어떻게 가능할까요?
C#에서는 함수 외부의 변수를 함수 내부에서 바로 수정할 수 있습니다. C#은 기본적으로 전역 변수 접근이 허용되며, 특별한 키워드 없이도 수정 가능합니다.

int a = 2;  // 전역 변수
void sums() 
{
    a += 4;  // 전역 변수 'a'에 접근 및 수정
    Debug.Log(a);  // 출력: 6
}
sums();
그렇기 때문에 Python에서는 저 a 바로 밑에 a를 새로 정의할 수 있지만, C#에서는 불가합니다. (즉, 같은 공간안에 같은 변수가 존재할 수 없습니다)
C#에서 변수 선언의 스코프 규칙
같은 스코프 내에서는 변수 이름 중복 불가:
int a = 2;
int a = 3; // 오류: 같은 스코프에서 중복 선언 불가


다른 스코프에서는 같은 이름을 사용할 수 있음:
함수 내부와 외부에서 동일한 이름의 변수를 사용할 수 있음.

int a = 2; // 전역 변수

void Test() 
{
    int a = 3; // 지역 변수, 전역 변수와는 별개
}


중첩 블록 안에서 동일한 이름의 변수를 사용할 수 있음.

void Test() 
{
    int a = 2;
    {
        int a = 3; // 내부 스코프의 지역 변수
        Debug.Log(a); // 3 출력
    }
    Debug.Log(a); // 2 출력
}

 


값을 저장을 해?
자, Unity C#에서는 알아야 할 점이 있습니다.

먼저 Python에는 전역변수, 지역변수를 통해 값을 어떻게 처리할 지 결정할 수 있습니다.

전역 변수를 사용
a = 2
def sums():
    global a
    a += 2
    print(a)
sums()
def minus():
    global a
    a -= 1
    print(a)
minus()
출력:
4
3​

함수 매개변수를 사용
a = 2
def sums(a):  # a는 함수 내부의 매개변수 (로컬 변수)
    a += 2
    return a
print(sums(a))  # 4 출력, 전역 변수 a는 변경되지 않음

def minus(a):  # a는 또 다른 함수의 매개변수 (로컬 변수)
    a -= 1
    return a
print(minus(a))  # 1 출력, 전역 변수 a는 변경되지 않음

 

먼저, 전역 변수의 동작 원리는
global a를 사용하여 함수 내부에서 전역 변수 a를 직접 수정합니다.
sums() 호출 시, 전역 변수 a의 값이 2에서 4로 변경됩니다.
minus() 호출 시, 같은 전역 변수 a의 값이 4에서 3으로 변경됩니다.
전역 변수 a는 프로그램 전체에서 공유되므로, 한 함수에서 변경된 값이 다른 함수에서도 유지됩니다.

하지만 전역 변수의 동작 원리는
a는 함수 매개변수로 전달되며, 함수 내부에서는 이 a를 로컬 변수로 처리합니다.
sums(a) 호출 시:
- 전역 변수 a의 값 2가 함수에 전달됩니다.
- 함수 내부에서 a += 2가 실행되어 로컬 변수 a의 값이 4가 됩니다.
- 함수는 4를 반환하지만, 전역 변수 a는 여전히 2로 유지됩니다.
minus(a) 호출 시:
- 동일한 방식으로, 전역 변수 a의 값 2가 함수에 전달됩니다.
- 함수 내부에서 로컬 변수 a -= 1이 실행되어 값이 1로 변경됩니다.
- 함수는 1을 반환하지만, 전역 변수 a는 여전히 2로 유지됩니다.

하지만 Unity는 다릅니다.
#start 함수 안
int f = 15;
f = sums(f);
f = minus(f);

#start 함수 바깥
int sums(int f)
{
    f += 20;
    Debug.Log(f);
    return f;
}

int minus(int f) 
{
    f -= 10;
    Debug.Log(f);
    return f;
}
출력: 
35
25
--------------------------------------------------------------------------
전역 변수:
int f = 15;
#start 함수 안
sums();
minus();


#start 함수 바깥
void sums()
{
    f += 20;
    Debug.Log(f);
}

void minus()
{
    f -= 10;
    Debug.Log(f);
}
출력:
35
25

즉, 어떻게 하든 값을 저장한다는 의미 입니다.

그리고
Unity의 C#에서는 변수 선언만 하고 초기값을 지정하지 않는 것이 가능합니다. 그러나 Python에서는 변수를 선언만 하는 것이 불가능하며, 반드시 초기값을 할당해야 합니다.

string a; // 변수 선언만 (초기화하지 않음)
a = "Hello, Unity!"; // 값 할당
Debug.Log(a); // 출력: Hello, Unity!

 


클래스
클래스는.....다음 시간에!!!!!

 

'Unity 개인 공부' 카테고리의 다른 글

Unity 개인 공부(2025-01-22)  (2) 2025.01.22
Unity 개인 공부(2025-01-21)  (0) 2025.01.21
Unity 개인 공부(2025-01-20)  (0) 2025.01.20
Unity 개인 공부(2025-01-19)  (0) 2025.01.19
Unity 개인 공부(2025-01-17)  (0) 2025.01.17