Hello C# &Unity

김동현·2022년 5월 26일
0

책을 보며 간단한 유니티 예제를 공부하였다.
여태 배웠던 C언어와는 많이 다르다는게 느껴졌고 재미있을거라고 생각된다.

책을 보며 새롭게 알게된 것들을 정리 해 보았다.

──────────────────────────────────────────

Unity??

유니티는 2D와 3D그래픽을 지원하는 다목적 게임 엔진입니다.

멀티플렛폼을 지원하기에 한 프로젝트에서 모바일과 데스크톱, 콘솔 게임용으로 빌드가 가능합니다.

유니티는 코드를 작성하기 전에 미리 만들어진 부품을 조립하여 게임 오브젝트를 만듭니다.

──────────────────────────────────────────

간단 기능 소개


위 이미지는 하이어라키 라고 불리는 현재 씬에 존재하는 모든 게임 오브젝트가 표시되는 곳 입니다.

다른 창들고 소개하겠습니다. 계속 하다보면 뭐가뭔지 익숙해지기에 이미지는 생략합니다.

씬(Scene) 창 : 게임 월드인 씬을 시각적으로 편집하는 창
하이어라키(Hierarchy) 창 : 씬에 존재하는 모든 게임 오브젝트가 나열되는 창
인스펙터(Inspector) 창 : 선택한 게임 오브젝트의 정보가 표시되는 창
게임(Game) 창 : 프로젝트에 사용할 에셋들이 표시되는 창
콘솔(Console) 창 : 로그나 에러가 표시되는 창

방금 생성한 큐브 게임 오브젝트를 선택하면 위 사진과 같이 인스펙터 창에 큐브 게임 오브젝트의 정보가 표시됩니다.
인스펙터 창은 선택한 오브젝트의 정보와 컴포넌트가 나열되는 곳 입니다.


생성한 큐브 게임 오브젝트를 중력을 받아 떨어지게 해 보겠습니다.
-인스펙터 창에서 Add Component > Physics > Rigidbody

리지드바디(Rigidbody) 컴포넌트는 게임 오브젝트가 물리와 중력의 영향을 받게 합니다.

트랜스폼(Transform) : 오브젝트의 3차원 좌표와 크기, 회전을 지정합니다.
메시 필터(Mesh Filter) : 3D 메시 파일을 받아 오브젝트의 외곽선을 지정합니다.
메시 렌더러(Mesh Renderer) : 메시를 따라 색을 채워 그래픽 외형을 그립니다.
박스 콜라이더(Box Cllider) : 다른 물체가 부딪칠 수 있는 물리적인 표면을 만듭니다.


다음은 씬 편집툴 이다.

우측부터 순서대로 말하겠다.

핸드(Hand) 툴 : 씬 카메라를 움직입니다.
평행이동(Translate) 툴 : 오브젝트를 이동시킵니다.
회전(Rotate) 툴 : 오브젝트를 회전시킵니다.
스케일(Scale) 툴 : 오브젝트의 크기를 조정합니다.
렉트(Rect) 툴 : UI 와 2D 오브젝트의 크기를 조정합니다.
트랜스폼(Transform) 툴 : 평행이동, 회전, 스케일 툴을 하나로 합친 툴입니다.

──────────────────────────────────────────

Component(컴포넌트)

Component의 방식을 이해하려면 예전에 사용했던 상속 방식을 알아야 합니다.
상속방식은 Class에 필요한 기초를 제공하는 가장 부모격의 Class부터 시작됩니다.

내가 만들고 싶은 Class에 부모격 Class를 가져오고 기능을 추가합니다.

이 과정은 어찌보면 편리하지만 새로 만들 Class에 추가하고 제거해야 할 기능들이 다수 생긴다면 개발자들은 할일이 기하급수적으로 늘어나게 되어 좋지않은 결과를 만듭니다.

그로인해 Unity는 보다 효율적인 작업을 위해 컴포넌트 패턴 혹은 컴포지션 패턴이라 불리는 것을 사용합니다.

컴포넌트 패턴은 미리 만들어진 부품을 조립하여 완성된 오브젝트를 만드는 방식입니다.
다시 말하면 텅 빈 게임 오브젝트에 컴포넌트를 조립하여 새로운 오브젝트로 만드는 것 입니다.

그 게임 오브젝트에 필요한 컴포넌트를 찾아 게임 오브젝트에 붙여 기능을 부여하는 것 입니다.

변수로 컴포넌트 사용하기

참조 변수는 실체가 아니라 실체로 향하는 참조값을 저장합니다.
씬에 있는 게임 오브젝트와 컴포넌트에 접근하여 이들을 조종할 수 있습니다.
변수로 게임 오브젝트를 제어해보겟습니다.

Rigidbody타입의 변수 myRigidbody를 선언했습니다.
public으로 지정했기에 외부에서 접근할 수 있습니다.

리지드바디 컴포넌트는 물리기능을 제공합니다.
따라서 힘을 주는 기능 (AddForce)를 가지고 있습니다.
Rigidbody 타입에 내장된 AddForce( ) 메서드는 x, y, z 방향으로 입력한 값 만큼 힘을 줍니다.

위 사진에선 y방향으로 600, z방향으로 150만큼의 힘을 주었습니다.

스크립트를 게임 오브젝트에 추가하는 방법은 간단합니다. 드래그&드롭 만 해주면 됩니다.

물론 스크립트를 끌어 하이어라키에 있는 원하는 게임 오브젝트에 해주어야 합니다.

넣어주면 인스펙터 창에 스크립트가 추가된것을 볼 수 있습니다.

스트립트의 public 변수는 인스펙터 창에서 편집 가능하도록 표시됩니다.
위 사진에선 푸른색 박스입니다.

myRigidbody.AddForce(0, 600, 150); 는 myRigidbody가 가리키는 Rigidbody 타입의 오브젝트로 접근하고 AddForce( ) 메서드를 실행합니다.
하지만 myRigidbody는 어떠한 실체도 가리키고 있지 않습니다.


위 사진은 myRigidbody에 Rigidbody 컴포넌트 할당을 해 준 것 입니다.

──────────────────────────────────────────

브로드캐스팅

게임 오브젝트가 포함하고 있는 컴포넌트 가 있습니다.
컴포넌트가 가지고 있는 기능들을 메서드(함수) 라고 부릅니다.

이 때 어떤 특정한 메서드를 실행시키려고 합니다.
특정한 메서드를 Dance()라고 지칭하겠습니다.

게임 세상에 Dance 라는 메시지를 브로드캐스팅 해 줍니다.
그러면 모든 게임 오브젝트와 컴포넌트가 Dance라는 메시지를 듣게 됩니다.
이들은 메시지의 출처를 따지지 않고 본인이 Dance라는 메시지를 포함하고 있다면 반응하고 그렇지 않다면 무시합니다.
Dance와 같은 이름의 Dance() 기능을 가지고 있다면 실행합니다.

단 한번의 브로드캐스팅으로 Dance()를 가진 모든 컴포넌트가 Dance()를 실행하게 합니다.

──────────────────────────────────────────

Script

스크립트 초기화면이다.
하나씩 살펴보겠다.

using

using 키워드를 이용하여 사용할 라이브러리의 경로를 지정하여 해당 라이브러리에 있는 코드를 가져와 사용할 수 있습니다.
위 사진의 using UnityEngine; 의 경우 UnityEngine 네임스페이스에 존재하는 코드를 가져와 사용한다는 의미입니다.

Start() 메서드(함수)

start()메서드는 게임이 시작될 때 한번 실행됩니다.
게임 시작과 실행 될 코드를 넣으면 됩니다.

문자출력

여태 배웠던 C언어와는 문자 출력방식이 다르다.
Debug.Log("출력할문자"); 의 방법으로 문자출력이 된다.
Debug.Log(); 메서드(함수)를 꼭 기억하자
위에서 언급했던 using UnityEngine; 가 Debug.Log() 메서드를 가지고 있다.
풀어서 쓴다면 UnityEngine.Debug.Log(); 가 되는 것 이다.

──────────────────────────────────────────

스크립트 완성 후 꼭 저장을 해줘야 적용이 된다.
저장 후 스크립트를 게임 오브젝트에 드래그&드롭으로 추가하면 적용된다.

──────────────────────────────────────────

변수

변수를 선언 한 후 출력하는 법을 알아보겠다.

친숙한 타입들이 보인다.
변수선언은 C언어와 큰 차이가 있진 않았지만 출력방식은 많이 달랐다.

Debug.Log("캐릭터 이름 : " + characterName);
Debug.Log("혈액형 : " + bloodType);
Debug.Log("나이 : " + age);
Debug.Log("키 : " + height);
Debug.Log("여성인가? : " + isFemale);

위의 형식으로 출력이 된다.
Debug.Log()메서드에 "입력할문자"를 넣고 + 를 입력 후 변수를 넣어주면 아래와 같이 출력된다.

──────────────────────────────────────────

빗변 구하기

평면의 두 점 사이의 간격을 구하려면 피타고라스의 정의를 이용하여 구할 수 있다.

지정된 숫자의 제곱근을 반환하는 메서드를 이용하면 간편하다.

간단한 메서드를 만들어서 간편하게 구해보겠다.

GatDistance() 메서드를 만들것이다. 매개변수로는 두 점의 좌표값이 되겠다.
좌표값이 실수로 들어올 수 있으니 float 로 선언 해 주고
GetDistance(float x1, float y1, float x2, float y2)
를 해준뒤
피타고라스의 정리를 이용하기 위해 직각삼각형의 밑변과 높이를 구하기 위해
float width = x2 - x1;
float height = y2 - y1;
서로 같은 축의 좌표값을 빼 주면 밑변과 높이가 구해진다.
밑변의 제곱 + 높이의 제곱 = 빗변의 제곱 이니
float distance = width width + height height;
지금의 distance값은 빗변의 제곱값이니
distance = Mathf.Sqrt(distance);
Mathf.Sqrt()메서드를 이용 이 메서드는 제곱근은 구해주는 메서드이다.
Mathf.Sqrt(distance);의 값을 distance에 넣어주어
return distance; 반환 해 주면
void Start()
{
float distance = GetDistance(2, 2, 5, 6);
Debug.Log("(2,2)에서 (5,6)까지의 거리 : " + distance);
}
GetDistance()메서드가 완성되어
GetDistance(2, 2, 5, 6) 매개변수들(좌표값)을 입력 후
distance에 넣어주고 출력한다.


──────────────────────────────────────────

배열

배열은 C# 와 C 에서 만드는 법이 다르다.

우선 int[ ]처럼 뒤에 [ ]를 붙여 해당 타입에 대한 배열 변수를 선언합니다.
new 키워드는 어떠한 타입의 오브젝트를 새로 생성한다는 의미입니다.

──────────────────────────────────────────

Class(클래스)

클래스와 오브젝트는 객체지향의 핵심입니다. 객체지향은 "사람이 현실 세상을 보는 방식" 에 가깝게 프로젝트를 완성하는 것 입니다.

class Human
{
string name;
void Walk();
}
여기서의 변수 name과 메서드 Walk()는 그냥 '이름' 과 '걷기' 가 아닙니다.
사람의 이름, 사람의 걷기 입니다.

클래스는 표현하고 싶은 대상을 추상화 하여 대상과 관련된 변수와 메서드를 정의하는 틀 입니다.

클래스 라는 틀 을 사용해 오브젝트를 찍어낼 수 있습니다. 이것을 인스턴스화 라고 불리며 인스턴스화를 이용해 생성된 오브젝트를 인스턴스 라고 부릅니다.


Class Animal을 만들었습니다.

클래스에 속하며 해당 클래스의 데이터와 행위를 표현하는 요소를 멤버라고 합니다.
name, sound, PlaySound()가 이에 해당됩니다.

클래스의 멤버 중 변수를 필드라고 부릅니다.
name, sound가 Class Animal의 필드 입니다.

접근 제한자

public : 클래스 외부에서 멤버에 접근 가능
private : 클래스 내부에서만 멤버에 접근 가능
protected : 클래스 내부와 파생 클래스에서만 멤버에 접근 가능

위 변수선언을 public string sound 가 아닌 private string sound 로 사용하면 다른 곳에서 접근이 불가능하기에 오류가 뜹니다.

  • 클래스는 오브젝트를 생성하는 틀입니다.

  • new를 사용하여 클래스로부터 오브젝트를 생성합니다.

  • 한 클래스로 여러 오브젝트를 만들 수 있습니다.

참조 타입

클래스로 만든 변수는 reference(참조)타입이기 때문입니다.
참조 타입의 변수는 실체화된 오브젝트가 아닙니다.
참조 타입의 변수를 선언하는 것만으론 오브젝트가 생성되지 않기 때문에 new를 사용해 오브젝트를 개별적으로 생성해야 합니다.

위에서 생성한 tom, jerry변수는 Animal 오브젝트로 향하는 참조값 입니다.

변수 jerry에 변수 tom의 값을 대입하여보았습니다.

jerry의 값이 tom으로 덮어 쓰기 된다고 착각하기 쉽습니다.
하지만 위 코드를 실행 해 보면 예상하던 결과가 나오지 않습니다.

jerry = tom;을 대입한후 출력된 것을 보면

예상했던 톰 : 냐옹! 이 나오지 않고
미키 : 냐옹! 이 출력됩니다.

이것은 변수 jerry와 tom이 참조값이라 그렇습니다.

jerry와 tom에 할당된 참조값을 찾아가면 Animal 오브젝트가 있습니다.
결국 Animal 오브젝트의 name을 "미키"로 수정합니다.

결론적으로 변수는 2개이지만 이 변수가 참조하는 오브젝트는 1개입니다.
Animal의 name이 변경되었기에 "미키"로 출력되는 것 입니다.
참조 타입의 변수는 오브젝트의 분신 이라고 이해하면 될것 같습니다.

위 내용은 참조타입만 적용되는 부분 입니다.
int float char string 같은 값 타입은 해당 변수공간에 값 자체를 저장합니다.

──────────────────────────────────────────

profile
해보자요

0개의 댓글