[C#] 배열, 리스트와 유니티 예제

2023. 8. 10. 14:26C#

728x90
반응형

배열은 클래스이며, 레퍼런스로 동작하기 때문에 선언만 해서는 안되고 new를 이용해 메모리를 만들어야 한다.

int[] nums = new int[5];
string[] strs = new string[3];

nums, strs는 레퍼런스 변수이다.

 

 


 

 

배열 선언

int[] nums = new int[5];
nums[0] = 1;
nums[1] = 2;

int[] nums = new int[]{1,2,3,4,5};
int[] nums = new int[5]{1,2,3,4,5};
int[] nums = {1,2,3,4,5};

배열의 실제 데이터는 힙 메모리 영역에 생긴다. nums 레퍼런스 변수는 스택 메모리 영역에 생긴다.

 

 

배열 접근

print(nums[0]);

for(int i=0; i<5; i++)
{
    print(nums[i]);
}

index를 통해 배열에 접근 가능하며 범위를 벗어나면 오류가 생긴다. 함수 내에서 출력 후 nums 레퍼런스 스택 메모리가 사라지고, 힙 메모리에 있는 실제 데이터는 레퍼런스가 없어졌으므로 가비지 컬렉터가 지우게 된다.

 

 


 

 

배열 예제 1

int[] nums;
void Start()
{
    nums = new int[5]{1,2,3,4,5};
    for(int i=0; i<5; i++)
    {
        print(nums[i]);
    }
}

위와 같이 nums 배열이 함수 바깥에서 선언되면 힙 데이터 영역에 생기게 되며 Start 함수가 끝나도 해당 레퍼런스 변수와 배열 데이터는 사용할 수 있다. 나중에 클래스가 사라질 때 둘 다 사라진다.

 

 


 

 

배열 예제 2

public class Test : MonoBehaviour
{
    public int[] nums;
    void Start()
    {
        for(int i =0; i < nums.Length; i++)
        {
            print(nums[i]);
        }
    }
}

위의 예제는 유니티에서 배열 값을 입력받는다.

 

 


 

 

리스트

배열과 비슷하다. Generic 문법이 있어 타이핑이 조금 더 오래 걸린다. 추가 삭제가 가능하다.(Add, Remove, RemoveAt, RemoveAll)

List<int> arr = new List<int>()
List<int> strs = new List<int>(){1,2,3};

 

 

public class Test : MonoBehaviour
{
    void Start()
    {
        List<int> nums = new List<int>() {1,2,3};
        nums.Add(100);
        nums.RemoveAt(0);
        for(int i = 0; i < nums.Count; i++)
        {
            print(nums[i]);
        }
    }
}

리스트에 100이라는 요소가 추가되고, RemoveAt을 통해 0번 인덱스 요소가 지워진다. 값 1이 지워지면 2가 인덱스 0이 된다. nums 변수 레퍼런스는 스택 메모리 영역, 리스트 내용은 힙 메모리 영역에 저장된다.

 

 


 

 

리스트 예제

public class Test : MonoBehaviour
{
    public List<GameObject> objs;
    void Start()
    {
        objs = new List<GameObject>();
        GameObject obj1 = new GameObject();
        obj1.name = "아이템1";
        objs.Add(obj1);
        GameObject obj2 = new GameObject();
        obj2.name = "아이템2";
        objs.Add(obj2);
        Destroy(objs[0]);
        objs.RemoveAt(0);
        for (int i = 0; i < objs.Count; i++)
        {
            print(objs[i].name);
        }
    }
}

obj1, obj2를 생성하고, 레퍼런스로 리스트에 추가하고 Destroy로 인덱스 0에 있는 실제 오브젝트를 삭제하고 objs.removeAt으로 남아있는 리스트에서 삭제한다. 리스트에서도 지웠다면 나중에 추가된 리스트 요소가 다시 인덱스 0이 된다. 모든 데이터는 힙 메모리 영역에 저장된다.

 

 

Destroy만 실행되면, Hierarchy 상에서 오브젝트는 지워지지만 리스트에는 Missing으로 아래와 같이 남아있게 된다.

해당 리스트를 지우기 위해서 objs.removeAt을 사용하는 것이다.

(**순서가 반대로 되면 오류가 생긴다.)

728x90
반응형