자, 저희 C#의 인스턴스의 개념이 뭔지 알아봅시다. 참고로 이 부분을 자세히 들여다봐야 어제 했던 내용이 이해가 갑니다.
먼저, 클래스와 인스턴스를 알아야합니다.
C#에서의 클래스는 Python과 다르게 다가옵니다. 근데 이전에 저희가 클래스를 만드는 법에 대해 배웠기 때문에.....하지만 거기에 숨겨진 의미가 있습니다. 기본 구조
publicclassDog
{
publicstring name;
publicDog(string name)
{
this.name = name;
}
}
// 인스턴스 만들기
Dog dog1 = new Dog("Buddy"); // "Buddy"라는 이름을 가진 Dog 클래스의 인스턴스를 만들었어요.
C#에서의 인스턴스는 클래스를 바탕으로 실제 객체를 만들어 사용하는 것입니다. Dog 클래스는 설계도이고, dog1은 그 설계도를 바탕으로 만든 실제 객체입니다.
여기까지는 배운 구조입니다. 하지만 이제 조금씩 느낌이 달라집니다. 이제 클래스와 타입에 대해서 이해해야 합니다. C#에서는 클래스가 곧 타입입니다. Python에서도 비슷하게, 클래스가 정의되면 그 클래스는 타입이 되고, 그 타입을 바탕으로 객체를 만들죠.
Dog dog1 = new Dog("Buddy"); // dog1은 Dog 타입의 객체
자, 여기서 중요! Dog dog1 = new Dog("Buddy");에서 Dog가 왜 앞에 붙는지에 대해 더 파고들어 보겠습니다.
타입 지정: Dog dog1 Dog는 클래스입니다. dog1은 그 클래스를 바탕으로 만들어진 인스턴스입니다. 이렇게 생각해 볼 수 있어요: Dog는 타입(type)을 의미합니다. 즉, dog1이 어떤 데이터 형태를 가질지 정의해요. dog1이 Dog 타입이기 때문에 dog1에는 Dog 클래스에서 정의한 내용만 들어갈 수 있어요. 타입을 지정하는 이유는 컴퓨터가 변수에 어떤 종류의 데이터를 넣을 수 있는지 알게 하기 위해서예요. 즉, dog1은 Dog 타입의 객체여야 하고, 그 안에는 Dog 클래스에서 정의된 속성과 메소드만 있을 수 있어요.
그런데 여기서 타입을 정의하는 것이 무엇을 의미하는 것일까요 C#에서 타입을 정의한다는 것은 변수나 객체가 어떤 종류의 값을 가질 수 있는지 제한하는 것입니다. 예를 들어:
int a = 5; // a는 int 타입string s = "Hello"; // s는 string 타입
여기서 a는 int 타입으로 정의되었으므로, a에는 정수만 들어갈 수 있습니다. a에 문자열이나 다른 타입의 값을 넣으려 하면 컴파일 에러가 발생합니다. 이때 int는 타입이므로, a는 정수만 받을 수 있습니다. 이와 비슷하게, string은 문자열만 받을 수 있습니다.
Dog라는 사용자 정의 타입의 의미 이제 Dog라는 클래스를 정의하면, 그것은 사용자가 만든 타입입니다. Dog는 단순한 데이터가 아니라, Dog라는 구조체로, 내부에 속성이나 메소드를 가질 수 있습니다. 예를 들어:
이제 Dog는 타입이자 클래스입니다. 이 Dog 타입을 사용하면, dog1과 같은 객체는 Dog에서 정의한 속성(예: Name, Age)과 메소드(예: Bark())만 사용할 수 있게 됩니다.
Dog dog1 = new Dog();
dog1.Name = "Buddy";
dog1.Age = 3;
dog1.Bark(); // "Woof!" 출력
타입을 정의할 때 dog1에 미치는 영향 Dog라는 클래스를 정의하고 dog1을 생성하면, dog1은 Dog 타입이므로 Dog에서 정의한 속성과 메소드만 사용할 수 있습니다. 이는 dog1이 Dog 타입이라는 제약을 가지게 된다는 뜻입니다. 즉, dog1에는 Dog 클래스에서 정의한 속성이나 메소드만 포함될 수 있고, 그 외의 다른 타입이나 클래스의 속성을 가질 수 없습니다.
타입에 따른 제약
Dog dog1 = new Dog();
dog1.Name = "Buddy"; // 유효
dog1.Age = 3; // 유효
dog1.Bark(); // 유효
dog1 = 5; // 에러: Dog 타입은 int를 받을 수 없음
dog1 = 5;와 같이 dog1에 정수를 할당하려고 하면 에러가 발생합니다. 왜냐하면 dog1은 Dog 타입으로 정의되었기 때문입니다. dog1은 Dog 클래스에서 정의된 속성인 Name, Age, Bark()만 사용할 수 있으며, 그 외의 int나 다른 타입의 값은 받을 수 없습니다
다른 타입과 비교
int a = 5; // a는 int 타입
a = "Hello"; // 에러: a는 string을 받을 수 없음
타입을 지정하지 않으면 어떤 일이 발생하는가? 타입을 지정하지 않으면 변수나 객체가 어떤 데이터를 다룰지 알 수 없게 되어 컴파일러가 이를 이해할 수 없습니다. 예를 들어, C#에서 타입을 지정하지 않으면 코드가 제대로 동작하지 않게 됩니다.
dog1 = new Dog(); // 에러: dog1의 타입이 명시되지 않으면 어떤 객체를 가질지 알 수 없음
그럼 다시 시작해볼까요? 새로운 Input System의 개념 Unity의 새로운 Input System은 입력을 처리하는 방식을 대폭 개선했습니다. 주요 개념은 다음과 같습니다:
Input Action: 입력(예: "Move", "Jump")을 추상적으로 정의합니다. 특정 키(W, A, S, D)나 입력 장치(조이스틱, 마우스)를 바인딩(연결)합니다.
Input Action Asset: 여러 Input Action을 모아놓은 파일. (예: "Move", "Jump", "Shoot" 액션 포함)
이벤트 기반 처리: 키를 누를 때마다 특정 이벤트를 발생시켜 입력을 처리합니다. 왜 Input System을 써야 할까? 장치 간 일관성: 키보드, 게임패드, 터치스크린 등 모든 입력 장치를 동일하게 처리 가능. 유연성: 복잡한 조합(예: WASD + 마우스 클릭)을 쉽게 처리. 확장성: 네트워크 플레이어나 AI가 같은 입력 시스템을 사용할 수 있도록 설계.
Input Action Asset 생성 1. Project 창에서 우클릭 > Create > Input Actions를 선택하여 새로운 Input Action Asset을 생성합니다. 파일 이름: InputControl. 2. Asset을 더블 클릭하여 Input Action Editor를 엽니다. 3. 새 액션을 추가: 이름: Move. 타입: Value. 제어 유형(Control Type): Vector2. 4. Move 액션에 키를 바인딩: Binding Path에서 Keyboard를 선택하고 W, A, S, D를 각각 추가합니다.
using UnityEngine;
using UnityEngine.InputSystem; // Input System 관련 클래스 가져오기publicclassPlayerInput : MonoBehaviour
{
private InputAction moveAction; // "Move" 액션을 저장할 변수voidStart()
{
// Input Action Asset 로드var asset = Resources.Load<InputActionAsset>("InputControl");
// "Move" 액션 찾기
moveAction = asset.FindAction("Move", true);
// Move 액션 활성화
moveAction.Enable();
}
voidUpdate()
{
// "W", "A", "S", "D" 입력 상태 확인
Vector2 input = moveAction.ReadValue<Vector2>();
if (input.y > 0) // "W" 키가 눌린 상태
{
Debug.Log("W 키가 눌렸습니다!");
}
elseif (input.x < 0) // "A" 키가 눌린 상태
{
Debug.Log("A 키가 눌렸습니다!");
}
}
}
밑 코드들을 보겠습니다. 1. ReadValue란? ReadValue는 Unity의 Input System에서 사용자의 입력 값을 가져오는 함수입니다. 쉽게 말해, 현재 입력된 값을 읽는 역할을 합니다. 왜 ReadValue를 써야 할까? Input System은 키보드, 조이스틱, 마우스 등 다양한 입력 장치를 지원합니다. 이 함수는 현재 연결된 입력 장치에서 데이터를 읽어옵니다. 데이터의 타입(예: Vector2, float, bool)에 따라 다르게 동작합니다. 예를 들어: Vector2: 방향 데이터를 반환 (예: 이동). float: 크기 데이터를 반환 (예: 스로틀). bool: 참/거짓 데이터를 반환 (예: 버튼 누름).
어떻게 동작할까? moveAction.ReadValue<Vector2>()는 Move 액션의 입력 값을 2D 벡터(Vector2)로 반환합니다. 반환된 값은 입력 장치에서 입력된 방향(예: WASD 키의 조합)을 나타냅니다.
2. Vector2란? Vector2는 Unity에서 2D 공간의 방향 또는 위치를 표현할 때 사용되는 구조체입니다. Vector2는 x와 y라는 두 축으로 구성되어 있습니다. Vector2의 특징 x와 y 값: x 축: 왼쪽(음수)과 오른쪽(양수) 방향. y 축: 아래(음수)와 위(양수) 방향. 예: (1, 0)은 오른쪽 방향, (0, 1)은 위쪽 방향을 나타냅니다.
Vector2 direction = new Vector2(1, 1); // x: 1, y: 1
Debug.Log(direction); // 출력: (1.0, 1.0)
게임에서의 활용: 2D 이동: 캐릭터가 위/아래/왼쪽/오른쪽으로 움직일 때 사용. 조이스틱 입력: 방향 조작을 벡터로 처리.
왜 W는 y 축이고, A는 x 축인가? WASD 키와 Vector2의 관계 Input System에서 W, A, S, D 키를 Vector2로 매핑하면 다음과 같이 동작합니다:
왜 이렇게 정의되었나요? x와 y는 2D 공간에서의 좌표 체계: x는 왼쪽-오른쪽의 수평 축. y는 아래-위의 수직 축. 키보드 방향에 맞춘 표준 매핑: W는 위쪽을 나타내므로 y = +1. A는 왼쪽을 나타내므로 x = -1. S는 아래쪽을 나타내므로 y = -1. D는 오른쪽을 나타내므로 x = +1.
코드로 확인해 보기 아래 코드는 Vector2의 값을 출력하여 W, A, S, D 키의 동작을 확인합니다:
using UnityEngine;
using UnityEngine.InputSystem;
publicclassInputTest : MonoBehaviour
{
private InputAction moveAction;
voidStart()
{
var asset = Resources.Load<InputActionAsset>("InputControl");
moveAction = asset.FindAction("Move", true);
moveAction.Enable(); // Move 액션 활성화
}
voidUpdate()
{
Vector2 input = moveAction.ReadValue<Vector2>();
Debug.Log($"x: {input.x}, y: {input.y}");
}
}
PlayerInput과 InputAction을 사용하여 입력을 처리하는 방식
using UnityEngine;
using UnityEngine.InputSystem;
publicclassInputExample : MonoBehaviour
{
private PlayerInput playerInput; // Input Action Asset과 연결된 Player Input 인스턴스private InputAction moveAction;
privatevoidAwake()
{
playerInput = new PlayerInput(); // Input Actions Asset 초기화
moveAction = playerInput.Player.Move; // "Move" 액션 접근
moveAction.Enable(); // 액션 활성화
}
privatevoidUpdate()
{
// 특정 버튼을 누르고 있는지 확인if (moveAction.ReadValue<Vector2>().y > 0)
{
Debug.Log("Up 키가 눌렸습니다!");
}
}
}