유니티로 게임을 개발하다보면 Vector2, Vector3라는 자료형을 많이 쓰게 됩니다.
예를 들어 플레이어를 움직인다고 했을 때, 아래와 같은 코드를 작성할 수 있습니다.
private void Update()
{
// 물론 이렇게 코드를 짜면 옆 친구가 연을 끊을 수도 있습니다.
if(Input.GetKey(KeyCode.A))
{
transform.position += Vector3.left;
}
if(Input.GetKey(KeyCode.D))
{
transform.position += Vector3.right;
}
}
이런식으로 Vector3은 게임을 개발할 때 빼먹을 수 없는 요소 중 하나입니다.
Vector를 자세히 살펴보면 아래와 같은 형태로 되어있습니다.
public struct Vector3 : IEquatable<Vector3>, IFormattable
{
public const float kEpsilon = 1E-05f;
public const float kEpsilonNormalSqrt = 1E-15f;
...
여기서 자세히 보면, Vector3(뿐만 아니라 Vector2, Vector4도 동일함)은 struct를 사용하고 있습니다.
하지만 다른 코드들을 보면, 보통 class를 사용합니다.
그러면 왜 Vector는 struct를 사용할까요?
Struct는 데이터들을 묶어서 하나의 타입으로 만든 것입니다.
가장 큰 특징은 값을 복사해서 사용한다는 점이고, 스택에 저장됩니다.
아래 코드를 예시로 들어보겠습니다.
Vector3 vec1 = Vector3.zero;
Vector3 vec2 = vec1; // 값복사
vec2 = Vector3.one;
print(vec1); // Vector3.zero
print(vec2); // Vector3.one
위 코드에서 vec1는 Vector3.zero를 저장해주고, vec2에는 vec1의 값을 저장해 주는 겁니다.
따라서 vec2의 값을 Vector3.one으로 변경하여도, vec1에 영향을 주지 않습니다.
Class는 데이터와 기능을 묶어서 한 객체로 만든 것입니다.
가장 큰 특징은 값을 복사하지 않고 참조 형식으로 힙에 저장되며, GC가 관리하는 대상입니다.
아래 코드를 예시로 들어보겠습니다.
MyClass class1 = new Class();
MyClass class2 = class1; // 값복사
class2 = new Class();
print(class1); // class2와 동일하게 출력됨.
print(class2); // class1과 동일하게 출력됨.
사실 코드가 약간 잘못됐지만, 간단하게 설명하자면 class2 = class1을 하게 된 후부터는 class2의 값을 바꾸면 class1에도 적용이 되는 겁니다.
그러면 왜 Vector는 Struct를 사용할까요?
일단 Vector는 간단한 구조로 이루어져 있습니다.
x, y, z같은 값들은 모두 float로 이루어져 있고, 주로 벡터 연산을 사용하기 위해 Vector를 사용합니다.
따라서 굳이 참조를 하지 않고 값만 빠르게 복사해서 써도 무방하며, Vector에서는 상속을 쓸 필요가 없기 때문에 Class를 쓸 이유가 없습니다.
간단하게 Vector를 구현하면 아래 코드와 같이 작성할 수 있습니다.
public struct Vector3
{
public float x;
public float y;
public float z;
public Vector3(float x, float y, float z)
{
this.x = x;
this.y = y;
this.z = z;
}
// 벡터 덧셈 기능
public Vector3 Add(Vector3 other)
{
return new Vector3(this.x + other.x, this.y + other.y, this.z + other.z);
}
}
Vector3 a = new Vector3(1, 2, 3);
Vector3 b = new Vector3(4, 5, 6);
Vector3 c = a.Add(b); // c는 (5, 7, 9)
a+b를 할 경우 a, b는 변하지 않고 새로운 값 c가 나오게 됩니다.
만약 이것을 class로 구현하게 된다면, a.Add를 하면서 a의 값도 변하게 되겠죠.
Vector는 간단한 데이터를 다루고, 빠르고 효율적인 복사와 변하지 않는 값이 중요하기 때문에 Class 대신 Struct를 사용하는 것이 더 적합합니다.
이렇게 Struct와 Class에 대해 알아보며 다음에는 어느 상황에 Struct를 사용해야 하는지 알게되는 좋은 경험이 된 것 같습니다.