[4].1 메서드 만들기 |
[4].2 클래스 만들기 |
[4].3 Vector 클래스 사용하기 |
[4].1 메서드 만들기
>> 메서드
- 스크립트가 끝없이 길어질 때, 길어진 처리를 의미가 있는 처리 블록으로 분해하고 이름을 붙이는 구조를 만든다.
- 이렇게 분해한 각 처리를 메서드(또는 함수)라고 함
- 메서드의 역할: 처리를 기능 단위로 묶는 역할 외에도 메서드에 값을 전달해서 계산하거나 계산 결과를 돌려받을 수 있도록 함
- 인수: 메서드로 건네는 값, 반환값: 메서드에서 돌려받는 값
- 인수는 여러 개 건넬 수 있지만 반환값은 한 개로 정해져 있음
🔍내가 찾아본 내용
- 메서드는 일련의 문을 포함하는 코드 블록입니다.
- 일련의 코드를 하나의 이름 아래 묶은 것
- 메소드(메서드)는 C/C++에서는 함수, 파스칼에서는 프로시져 등으로 부름
>> 메서드를 만드는 방법
- 반환값의 데이터 형에는 호출자의 메서드로 반환하는 값의 데이터 형을 지정함
- 지정할 데이터 형은 변수의 데이터 형과 같음
- 값을 반환하지 않는 메서드에는 void를 지정함
- void의 의미: '반환값이 없음'
- 인수는 호출자의 메서드에서 받은 값임
- 메서드는 인수 값을 사용해서 처리를 실행함
- 인수를 갖지 않는 메서드도 있는데 이때는 메서드명 뒤에 붙는 괄호 안을 공백으로 비움
- 호출하는 메서드명에 이어 괄호 안에 전달하는 인수를 기술함
- 인수가 여러 개면 쉼표(,)로 구분함
>> ⭐① 인수도 반환값도 없는 메서드⭐
- 코드: Console 창에 Hello를 출력하는 메서드
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test : MonoBehaviour
{
void SayHello()
{
Debug.Log("Hello");
}
void Start()
{
SayHello();
}
}
\ 출력 결과 /
Hello
>> 메서드 작성 방법
- 7~10번 줄이 Console 창에 문자를 출력하는 SayHello 메서드임
- 이 메서드는 Console 창에 문자를 출력할 뿐 호출자의 값을 반환하지 않으므로(반환값을 갖지 않음), 반환값의 데이터 형에 void를 지정함
- 인수가 없으므로 메서드명 뒤에 붙는 괄호 안을 공백으로 비움
- 계속해서 중괄호 안에 실행할 처리를 작성함
- 여기서는 Debug.Log를 사용해서 Console 창에 Hello를 출력함
- SayHello 메서드를 사용할 위치는 Start 메서드를 벗어나더라도 Test 클래스의 중괄호 안(7~15번 줄)이라면 어디든 상관없음
>> 메서드 호출 방법
- Start 메서드에서 SayHello 메서드를 호출함(14번 줄)
- 메서드를 호출하려면 메서드명에 이어 전달하고 싶은 인수를 씀
- 이 예제에서는 SayHello 메서드에 인수가 없으므로 괄호 안을 공백으로 비움
- 여기서 작성한 SayHello 메서드는 Start 메서드가 Update 메서드에서 호출될 때까지는 처리가 실행되지 않음
- 작성한 메서드는 호출해서 사용한다는 것을 기억해두자
>> ⭐② 인수가 있는 메서드⭐
- 코드: 인수를 출력하는 메서드
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test : MonoBehaviour
{
void CallName(string name)
{
Debug.Log("Hello" + name);
}
void Start()
{
CallName("Tom");
}
}
\ 출력 결과 /
Hello Tom
>> 메서드 작성 방법
- 10번 줄이 CallName 메서드임
- CallName 메서드에는 반환값이 없으므로 void를 지정함
- 문자열을 인수로 받으므로 메서드명에 이어 괄호 안에 string형의 name 변수를 선언함
>> 메서드 호출 방법
- 14번 줄에서 CallName 메서드를 호출함
- 메서드명 CallName에 이어 괄호 안에 메서드로 전달하는 이름(문자열)을 씀
- CallName 메서드를 호출하면 인수의 문자열인 "Tom"이 자동으로 메서드 안의 name 변수에 대입됨
- name 메서드는 메서드에서 변수처럼 쓸 수 있으므로 Debug.Log를 써서 name 변수 값을 출력함
>> 인수 형에 주의한다!
- 14번 줄에서 인수를 지정하지 않고 CallName();으로 메서드를 호출하면 오류가 발생함
- 기본적으로 인수 수는 호출되는 쪽과 호출하는 쪽이 일치해야 함
>> ⭐③ 인수와 반환값이 있는 메서드⭐
- 이번에 살펴볼 예제는 인수로 변수를 두 개 받고, 두 변수의 합계를 반환하는 Add 메서드임
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test : MonoBehaviour
{
int Add(int a, int b)
{
int c = a + b;
return c;
}
void Start()
{
int answer;
answer = Add(2, 3);
Debug.Log(answer);
}
}
\ 출력 결과 /
5
>> 메서드 작성 방법
- 7~11번 줄은 이번에 작성한 Add 메서드임
- 메서드의 반환값은 int형 인수를 합한 것이므로 int형으로 지정함
- Add 메서드는 인수가 두 개이므로 각 인수를 쉼표(,)로 구분해 선언함
- 10번 줄에서 인수의 합계를 반환값으로 돌려줘야 하므로 return 문을 씀
- return 문 뒤에 공백을 두고 변수명을 적으면 그 변수 값을 메서드를 호출한 곳으로 반환할 수 있음
>> 메서드 호출 방법
- Add 메서드를 호출하는 흐름을 정리하면 다음과 같음
- 메서드를 호출하는 쪽에서는 메서드명에 이어 인수를 두 개(2와 3) 전달함
- 메서드 호출과 동시에 a와 b 변수에는 각각 2와 3이 대입됨
- a와 b 변수에는 메서드를 호출하는 곳에서 지정한 순서대로 값이 대입됨
- Ad(2, 3)이 아닌 Add(3, 2)를 쓰면 a 변수에 3이 대입되고 b 변수에 2가 대입됨
- 메서드에서는 a와 b 변수를 합한 값을 c 변수에 대입하고 return 문을 사용해서 합계를 호출한 곳으로 반환함
- 메서드를 실행한 후에는 메서드의 호출 부분이 반환값으로 바뀌는 형태임
- Add(2, 3) 부분이 반환값 c 값으로 바뀌기 때문에 answer = Add(2, 3);은 answer = c;이 되고 answer에 c 값이 대입됨
[4].2 클래스 만들기
>> 클래스
- 메서드 : 처리를 모아 둔 것
- 클래스 : 메서드와 변수를 모아 둔 것
- 유니티로 게임을 만들려면 플레이어, 적, 무기, 아이템 등 물체마다 그 움직임을 정의하는 스크립트를 작성해야 함
- 이때는 '처리 단위'보다는 '물건 단위'로 스크립트를 작성하는 것이 편리함
- 변수와 메서드를 하나로 합치지 않고 따로따로 구현하면 어느 변수와 메서드가 연결되어 있는지 알기 어려움
- 클래스를 사용하면 관계가 있는 변수와 메서드를 하나로 합칠 수 있으므로 스크립트를 관리하기 쉬움
- class 키워드 다음에 클래스명을 쓰고, 그 안에 클래스에서 사용하는 변수와 메서드를 씀
- 클래스에서 사용한 변수를 멤버 변수, 클래스에서 사용한 메서드를 멤버 메서드라고 함
- 작성한 클래스는 int나 string 등 데이터 형으로 사용할 수 있음
- 즉. Player 클래스를 만들면 Player형을 사용할 수 있게 됨
- int num;을 쓰면 int형의 num 변수를 만들 수 있음
- Player myPlayer;을 쓰면 Player형의 myPlayer 변수를 만들 수 있음
- 이 상태에서 myPlayer 변수의 상자 안은 비어 있음
- int형의 num 변수에는 2나 1500 같은 숫자를 대입함
- Player형의 myPlayer 변수에는 플레이어의 실체를 대입함 ⭐
- 이 실체를 인스턴스라고 함 ⭐
- myPlayer 변수가 가진 멤버 메서드나 멤버 변수를 사용하려면 myPlayer;멤버 메서드명(또는 멤버 변수명)을 씀
- 앞으로 마침표(.)로 연결된 형태가 자주 나옴
- OO.xx가 나오면 OO 클래스가 갖는 xx 메서드(또는 변수)를 사용한다고 이해해 두자
>> 유니티가 제공하는 클래스도 있다!
- 직접 클래스를 만들 수도 있지만 유니티가 처음부터 제공하는 클래스도 있음
- Vector 클래스와 로그 표시를 할 때 쓰는 Debug 클래스 등이 유니티가 제공하는 클래스임
- 유니티를 사용하려면 클래스 개념을 제대로 이해하는 것이 중요함
[4].2 클래스 만들기
>> 클래스 작성하기
- 지금까지 써 온 Test 스크립트(Test.cs)에 Player 클래스를 추가함
- Player 클래스는 Test 클래스 외부에 추가하는 것에 주의함
🖥️ 코드: Player 클래스 구현하기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player
{
private int hp = 100;
private int power = 50;
public void Attack()
{
Debug.Log(this.power + "데미지를 입혔다");
{
public void Damage(int damage)
this.hp -= damage;
Debug.Log(damage + "데미지를 입었다");
}
}
public class Test : MonoBehaviour
{
void Start()
{
Player myPlayer = new Player();
myPlayer.Attack();
myPlayer.Damage(30);
}
}
\ 출력 결과 /
50 데미지를 입혔다
30 데미지를 입었다
✏️ (5번 줄) Player 클래스는 public 선언을 했기 때문에 외부 클래스에서 사용할 수 있음
✏️ 만약 public을 붙이지 않으면 private가 자동으로 설정되기 때문에 public을 사용하고 싶을 때는 꼭 붙여준다!
✏️ (7, 8번 줄) private 선언을 했기 때문에 외부 클래스에서는 hp와 power라는 변수에 접근을 할 수 없게 되고, 만약 접근하려고 하면 에러가 발생함, Player 클래스 안에서만 접근 가능
✏️ (10번 줄) Attack 앞에 public을 붙여주었기 때문에 다른 클래스에서도 사용 가능함
✏️
- 5~20번 줄이 이번에 작성한 Player 클래스임
- 클래스 구성을 간단히 살펴보면 5번 줄에서 Player 클래스를 선언함
- 7~8번 줄에서 플레이어의 HP를 나타내는 멤버 변수(power)를 선언함
- 10~19번 줄에서는 공격하는 멤버 메서드(Attack)와 데미지를 받는 멤버 메서드(Damage)를 작성함
>> 클래스를 사용하는 방법
- 코드 2~29의 Start 메서드에 있는 26~28번 줄에서는 방금 작성한 Player 클래스의 인스턴스를 만들어 사용함
- 먼저 26번 줄의 왼쪽에 Player myPlayer를 써서 Player형의 myPlayer 변수를 선언함
- 이 단계에서는 Player형의 상자를 만들었을 뿐이므로 Player형의 실체인 인스턴스를 작성해 대입해야 함
- 인스턴스를 만들려면 new 키워드 다음에 클래스 이름()을 씀(26번 줄의 오른쪽)
- Player 클래스의 인스턴스가 만들어지고 이것을 myPlayer 변수 안에 대입함
- 27번 줄에서는 인스턴스를 가진 Attack 메서드를 myPlayer.Attack()인 변수명.멤버 메서드명() 형태로 호출함
- 마찬가지로 28번 줄에서는 Damage 메서드를 호출함
- 실행 도구를 클릭해 Console 창에 무엇이 출력되는지 확인함
>> 접근 수식자
- 코드 2~29를 보면 Player 클래스의 멤버 변수와 멤버 메서드 앞에 public이나 private 키워드가 붙어 있음
- 이것을 접근 수식자라고 하는데, OO.xx라고 썼을 때 다른 클래스에서 멤버로 접근 가능한지 여부를 나타냄
- public이 붙어 있는 멤버는 다른 클래스에서도 호출할 수 있지만, private가 붙어 있는 멤버는 다른 클래스에서 호출할 수 없음
- Attack 메서드에는 public이 붙어 있으므로 myPlayer. Attack()이라고 써서 Attack 메서드를 호출할 수 있음
- hp 변수에는 private가 붙어 있으므로 myPlayer.hp라고 써도 hp 변수에 접근할 수 없음
- private을 쓰는 이유는 다른 사람이 자신이 만든 클래스를 사용할 때 'private 메서드는 사용하지 마세요, private 변수는 변경하지 마세요'라는 의사 표시를 할 수 있기 때문임
- 즉, 다른 사람이 만든 클래스를 쓸 때는 public이 붙은 변수와 메서드만 써야 함
- 접근 수식자를 생략하면 private으로 간주되므로 공개하고 싶은 변수와 메서드가 있다면 public 수식자를 붙이는 것이 좋음
>> this 키워드
- this는 자신의 인스턴스를 가리키는 키워드임
- this.power는 자신의 인스턴스가 가진 power 변수(Player 클래스의 인스턴스가 가진 power 변수)를 나타냄
- 사실 this를 붙이지 않아도 자기 클래스의 멤버 변수를 사용할 수 있음
- '코드: Player 클래스 구현하기' 의 Attack 메서드에서 다음과 같이 멤버 변수와 동일한 이름의 로컬 변수 (power)를 선언했다고 할 때, power라고만 쓰면 로컬 변수의 값이 우선해서 사용됨
- 멤버 변수를 쓸 때는 명시적으로 this를 붙여야 오류를 막을 수 있음
>> 상속
- Test 클래스의 선언 부분(코드 2~29의 22번 줄) 뒤에 붙은 MonoBehaviour는 상속이라고 함
- 이 부분은 유니티가 미리 준비한 MonoBehaviour 클래스의 기능을 Test 클래스에 집어넣겠다고 선언하는 과정임
- MonoBehaviour 클래스는 게임 오브젝트를 구성하는 기본 기능을 멤버 변수와 멤버 메서드로 준비한 클래스임
- 게임 오브젝트에 붙여 실행하는 스크립트는 MonoBehaviour 클래스 (또는 MonoBehaviour를 바탕으로 한 클래스)를 상속해야 함
>> Debug.Log는 인스턴스 없이 사용할 수 있을까?
- Player 클래스의 인스턴스를 만들고 '인스턴스 변수명.멤버 메서드명' 형태로 멤버 메서드를 직접 호출함
- 한편 계속해서 쓰고 있는 Debug.Log 메서드는 '클래스명.멤버 메서드명' 형태로 멤버 메서드를 직접 호출함
- Debug.Log가 static 메서드(인스턴스를 만들지 않고도 쓸 수 있는 메서드)로 선언되기 때문
[4].3 Vector 클래스 사용하기
>> Vector
- 3D 게임을 만들려면 공간에서 오브젝트를 어디에 둘지, 어느 쪽으로 옮길지, 어디르 힘을 보낼지 등을 정해야 하므로 float형의 x, y, z 값 세 개를 씀
- C#에는 이러한 값을 하나로 합쳐 다룰 수 있는 Vector3 클래스(정확히는 구조체라고 한다)가 준비되어 있음
- 반면 2D 게임용에는 float형의 x, y 값을 갖는 Vectort2 클래스가 있음
- Vector3 클래스의 구조는 다음과 같음
- Vector3 클래스에는 x, y, z 멤버 변수가 있고, Vector2 클래스는 x, y 멤버 변수가 있음
- 둘 다 좌표나 벡터로 쓸 수 있음
- x = 3, y = 5를 좌표로 쓰면 오브젝트가 (3, 5) 위치에 배치되었다는 것을 뜻함
- 한편 벡터로 쓰면 현재 위치에서 'X 방향으로 3', 'Y 방향으로 5' 움직였다는 것을 뜻함
>> Vector 클래스를 사용하는 방법
- 코드: Vector2 클래스의 멤버 변수에 숫자 더하기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
Vector2 playerPos = new Vector2(3.0f, 4.0f);
playerPos.x += 8.0f;
playerPos.y += 5.0f;
Debug.Log(playerPos);
}
}
\ 출력 결과 /
(11.0, 9.0)
- 9번 줄 왼쪽에 Vector2 클래스의 playerPos 변수를 선언함
- 이 과정은 Vector2형의 상자를 만드는 과정이므로 대입할 수 있는 인스턴스를 이어서 작성해야 함
- new Vector2(3.0f, 4.0f)를 써서 Vector2 클래스의 인스턴스를 작성해 대입함
- new 클래스명()으로 클래스 인스턴스를 작성할 수 있음
- 클래스 부분에서 설명한 대로 멤버 변수인 x와 y값에 접근하려면 변수명x, 변수명y라고 씀
- 이것을 이용해서 10~11번 줄에서 플레이어가 있는 X좌표를 8, Y좌표를 5 증가시킴
- Vector2 클래스 변수를 게임 오브젝트의 좌표로 사용하는 경우에는 값을 증가시키면 화면의 게임 오브젝트가 양수 방향(오른쪽 혹은 위)으로 이동함
- 반대로 값을 감소시키면 음수 방향(왼쪽 혹은 아래)으로 이동함
🖥️ 코드: Vector 클래스끼리 뺄셈하기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
Vector2 startfos = new Vector2(2.0f, 1.0f);
Vector2 endfos = new Vector2(1.0f, 5.0f)
Vector2 dlr = endfos - startfos;
Debug.Log(dlr);
float len = dlr.magnitude;
Debug.Log(len);
}
}
\ 출력 결과 /
(6.0, 4.0)
7.211102
- 이 예제에서는 startPos에서 endPos로 향하는 dlr 벡터를 구함
- 두 점의 좌표에서 벡터를 구하기 때문에 11번 줄의 endPos에서 startPos를 뺌
- 이처럼 Vector2 클래스끼리 뺄셈을 할 수 있음
- 14번 줄에서는 startPos부터 endPos까지 거리를 구함
- 이 거리는 dlr 벡터 길이와 같으므로 Vector2 클래스가 갖는 magnitude 멤버 변수를 사용해서 dlr 벡터의 길이를 구함
>> Vector 클래스 응용하기
- Vector 클래스는 가속도, 힘, 이동 속도 같은 물리 수치로도 사용할 수 있음
>> Visual Studio 동작
- 때때로 Visual Studio의 intellisense 기능을 사용할 수 없고 스크립트 전체가 빨간색 물결선으로 표시될 때가 있음
- 이때는 Visual Studio를 다시 실행해보자
'Project > Unity 게임 제작' 카테고리의 다른 글
[6] 슈팅 게임 제작 (2) (2) | 2023.07.06 |
---|---|
[5] 슈팅 게임 제작 (1) (6) | 2023.07.04 |
[3] C# 스크립트 (2) (6) | 2023.06.29 |
[2] C# 스크립트 (1) (6) | 2023.06.28 |
[1] 유니티 설치 & 조작법 - (3) 오브젝트 다루기 (6) | 2023.06.27 |