목표
- Classes에 대해 이해한다.
Classes
Script
- Unity에서 Script에는 Class에 대한 정의가 포함될 수 있다.
- 앞선 튜토리얼에서 스크립트를 생성했을 때, class라는 키워드가 자동으로 생성되는 것을 알 수 있을 것이다.
- 이 클래스명은 스크립트 파일과 동일한 이름을 공유한다.
- 이 명칭은 클래스와 스크립트 파일명을 동일하게 유지해줘야 하기 때문에 변경에 유의해야 한다.
public class BoxFactory : MonoBehaviour
{
public void Start()
{
}
public void Update()
{
}
}
OOP (Object-Oriented Programming)
- 프로그래밍을 공부하다 보면 Object-Oriented Programming이라는 단어를 들어봤을 것이다.
- Object-Oriented Programming는 OOP라고 줄여서 부르기도한다.
- 객체 지향 프로그래밍은 컴퓨터 프로그래밍의 패러다임 중 하나로, 프로그래밍에 필요한 데이터를 추상화(핵심 개념 또는 기능을 간추리는 행위)시켜 상태와 행위를 가진 객체를 만들고 그 객체들 간의 유기적인 상호작용을 통해 로직을 구성하는 프로그래밍 방법이다.
- 객체 지향 설계에는 SOLID라는 5원칙이 존재한다.
원칙 | 설명 |
단일 책임 원칙 / Single responsibility principle | 한 클래스는 하나의 책임만 가져야 한다. |
개방-폐쇄 원칙 / Open-Closed principle | 소프트웨어 요소는 확장에는 열려 있으나, 변경에는 닫혀 있어야 한다. |
리스코프 치환 원칙 / Liskov substitution principle | 프로그램의 객체는 프로그램의 정확성을 개뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다. |
인터페이스 분리 원칙 / Interface segregation principle | 특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다. |
의존 역전 원칙 / Dependency inversion principle | 프로그래머는 추상화에 의존해야지 구체화에 의존하면 안된다. 의존성 주입은 이 원칙을 따르는 방법 중 하나다. |
SingleCharacterScript 예제
- 다음은 Stuff(소지품 : 총알, 수류탄, 로켓), Movement(움직임), Shoot(발사)가 정의되어 있는 예시이다.
- SingleCharacterScript는 소지품, 캐릭터 컨트롤러, 행동에 대한 정의 3가지가 한 클래스에 모두 구현되어 있는 '좋지 못한 프로그래밍 방식'을 보여주기 위한 의도이다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SingleCharacterScript : MonoBehaviour
{
public class Stuff
{
public int bullets;
public int grenades;
public int rockets;
public Stuff(int bul, int gre, int roc)
{
bullets = bul;
grenades = gre;
rockets = roc;
}
}
public Stuff myStuff = new Stuff(10, 7, 25);
public float speed;
public float turnSpeed;
public Rigidbody bulletPrefab;
public Transform firePosition;
public float bulletSpeed;
void Update()
{
Movement();
Shoot();
}
void Movement()
{
float forwardMovement = Input.GetAxis("Vertical") * speed * Time.deltaTime;
float turnMovement = Input.GetAxis("Horizontal") * turnSpeed * Time.deltaTime;
transform.Translate(Vector3.forward * forwardMovement);
transform.Rotate(Vector3.up * turnMovement);
}
void Shoot()
{
if (Input.GetButtonDown("Fire1") && myStuff.bullets > 0)
{
Rigidbody bulletInstance = Instantiate(bulletPrefab, firePosition.position, firePosition.rotation) as Rigidbody;
bulletInstance.AddForce(firePosition.forward * bulletSpeed);
myStuff.bullets--;
}
}
}
SingleCharacterScript 나누기
- 소지품을 관리하기 위하여 Inventory(가방)를 별도로 제작하였고, Stuff(소지품) 정보를 가지게 하였다.
using UnityEngine;
using System.Collections;
public class Inventory : MonoBehaviour
{
public class Stuff
{
public int bullets;
public int grenades;
public int rockets;
public float fuel;
public Stuff(int bul, int gre, int roc)
{
bullets = bul;
grenades = gre;
rockets = roc;
}
public Stuff(int bul, float fu)
{
bullets = bul;
fuel = fu;
}
// Constructor
public Stuff ()
{
bullets = 1;
grenades = 1;
rockets = 1;
}
}
// Creating an Instance (an Object) of the Stuff class
public Stuff myStuff = new Stuff(50, 5, 5);
public Stuff myOtherStuff = new Stuff(50, 1.5f);
void Start()
{
Debug.Log(myStuff.bullets);
}
}
- 움직임을 관리하기 위하여, MovementControls 클래스를 제작하였다.
using UnityEngine;
using System.Collections;
public class MovementControls : MonoBehaviour
{
public float speed;
public float turnSpeed;
void Update ()
{
Movement();
}
void Movement ()
{
float forwardMovement = Input.GetAxis("Vertical") * speed * Time.deltaTime;
float turnMovement = Input.GetAxis("Horizontal") * turnSpeed * Time.deltaTime;
transform.Translate(Vector3.forward * forwardMovement);
transform.Rotate(Vector3.up * turnMovement);
}
}
- 쏘는 행위를 정의하기 위하여 Shooting 클래스를 제작하였다.
using UnityEngine;
using System.Collections;
public class Shooting : MonoBehaviour
{
public Rigidbody bulletPrefab;
public Transform firePosition;
public float bulletSpeed;
private Inventory inventory;
void Awake ()
{
inventory = GetComponent<Inventory>();
}
void Update ()
{
Shoot();
}
void Shoot ()
{
if(Input.GetButtonDown("Fire1") && inventory.myStuff.bullets > 0)
{
Rigidbody bulletInstance = Instantiate(bulletPrefab, firePosition.position, firePosition.rotation) as Rigidbody;
bulletInstance.AddForce(firePosition.forward * bulletSpeed);
inventory.myStuff.bullets--;
}
}
}
비고
위 예제는 프로그램 작성 시 '작은 단위로 기능을 구현해야 한다'라는 의도를 전달하기 위해 만들어 졌다.
좋은 구현은 예시는 아니다.
Rigidbody는 Physics Part에서 나오고, Instantiate나 Prefabs는 다음 글에서 설명할 예정이다.
'프로그래밍 > Unity C#' 카테고리의 다른 글
[Unity] Tutorial 05 - Beginner Gameplay Scripting (Arrays) (0) | 2019.11.04 |
---|---|
[Unity] Tutorial 05 - Beginner Gameplay Scripting (Instantiate) (0) | 2019.11.04 |
[Unity] Tutorial 05 - Beginner Gameplay Scripting (Data Types) (0) | 2019.11.04 |
[Unity] Tutorial 05 - Beginner Gameplay Scripting (DeltaTime) (0) | 2019.10.30 |
[Unity] Tutorial 05 - Beginner Gameplay Scripting (GetComponent - 2) (0) | 2019.10.29 |