Send Message
게임 전역적으로 처리해야하는 값,메소드를 모아놓는다
다음 기능을 각 오브젝트가 아닌 전역적으로 처리하도록 해보자.1. 게임 재시작
2. 빨간코인 -> 장애물 삭제
3. 코인획득 -> 점수표
1. 게임 매니저
1. 전역 스크립트에 저장하기/스크립팅
-
절차는 다음과 같다
- 전역에서 실행되기를 가정한 WORLD 오브젝트를 생성한다
- WORLD 오브젝트에 WORLD 스크립트를 삽입한다
-
다음은 게임 매니저에서 전역으로 실행될 메소드를 만든코드이다.
public class GameManager : MonoBehaviour { bool DEBUG = true; private int coinCount = 0; void RestartGame(){ if(DEBUG) {Debug.Log("Total Coins" + coinCount);} Application.LoadLevel("BallGame"); if(DEBUG) {Debug.Log("Restarted");} } void DestroyObstacle(string _Target){ GameObject[] ObstaclesArr = GameObject.FindGameObjectsWithTag(_Target); foreach(GameObject E in ObstaclesArr){ Destroy(E); } if(DEBUG) {Debug.Log("Get RedCoin Remove All");} } void CalCoin(){ coinCount++; } }
2. 전역 스크립트를 불러오기/호출하기
- 다음은 WORLD 오브젝트에 삽입한 스크립트를 호출하는방법이다
GameObject.Find("_WORLD 오브젝트_").SendMessage("_WORLD 스크립트 메소드_, 메소드 인자");
3. 궁극적으로 SendMessage는 쓰지말자
- ??? 잘만 써놓고는 뭔소리죠?
- 대충 예상은 간다.. 직접호출보다 훨씬 느리겠지
- 직접호출보다 느림. 디버깅시 추적이 어려움.
- GameManager오브젝트에 들어간 스크립트를 Find하는것도 자원 낭비일것같다
- 다음과 같은 의문점이 생긴다... 스크립트는 사실 클래스 아닐까? 직접호출 가능 여부
결과
- 다음은 게임 매니저를 통해 전달된 함수 시연이다.
클래스
1. 컴포넌트
- 인스펙터 창에 추가된것을 말한다. 곧 클래스로 구현된것이다.
- 스크립트에서 다른(내부 혹은 외부 오브젝트에 선언된) 컴포넌트 접근하기/가져오기
// 1 GetComponent<_컴포넌트,스크립트 명_>(); 혹은, // 2 _컴포넌트,스크립트명(클래스)_ _instance_ = gameObject.GetComponent<_컴포넌트,스크립트 명_>(); // 컴포넌트 클래스 자료형이다. //gameObject는 컴포넌트를 포함하는 자기자신의 오브젝트를 의미함
- 인스턴스의 분류
- 메소드
- 멤버변수
- 클래스에는 메소드와 멤버변수를 가져올 수 있음
- 스크립트에서 다른(내부 혹은 외부 오브젝트에 선언된) 컴포넌트 접근하기/가져오기
직접 만들어보기
- 가져온 컴포넌트/스크립트명 클래스에서 메소드나 멤버변수를 사용하려면 조건이 있다
- public으로 선언하면 .___으로 사용가능
//참조할 스크립트 내부 public class GameManager : MonoBehaviour { private bool DEBUG = true; private int coinCount = 0; public void CalCoin(){ } public void RestartGame(){ } public void DestroyObstacle(string _Target){} }
- public으로 선언하면 .___으로 사용가능
- 메소드로 호출하자
- 다음 컴포넌트 접근 방법은 worldGM을 통해 메소드를 실행할 것이다.
- 게임 재시작
public class RestartGame : MonoBehaviour { bool DEBUG = false; private GameManager worldGM; public GameObject G; //인스펙터에서 GM 지정하기 void OnTriggerEnter(Collider _collider) { if(DEBUG) {Debug.Log(_collider.gameObject.name);} if(_collider.gameObject.name == "Ball"){ worldGM.RestartGame(); //Application.LoadLevel("BallGame"); } } // Start is called before the first frame update void Start(){ worldGM = G.GetComponent<GameManager>(); } }
- 빨간코인 -> 장애물삭제
public class RedCoin : MonoBehaviour { private GameManager worldGM; public GameObject G; //인스펙터에서 GM 지정하기 void OnTriggerEnter(Collider _col){ if(_col.gameObject.name == "Ball"){ worldGM.DestroyObstacleWithTarget("_Obstacle"); Destroy(gameObject); } } // Start is called before the first frame update void Start() { worldGM = G.GetComponent<GameManager>(); } }
- 코인획득 -> 점수표
public class GetCoin : MonoBehaviour { private GameManager worldGM; public GameObject G; //인스펙터에서 GM 지정하기 void OnTriggerEnter(Collider _col){ if(_col.gameObject.name == "Ball"){ worldGM.CalCoin(); //Debug.Log(gameObject.name +" " + gameObject.tag); Destroy(gameObject); } } void Start(){ worldGM = G.GetComponent<GameManager>(); } }
- 게임 재시작
2. 인스펙터와 Public
- public 으로 선언한 멤버변수가 인스펙터에서 오염될 수도 있지 않을까?
- 음.. 그래서 일반적으로 다음과 같이 캡슐화 하라고 한다..
- 멤버 변수는 private
- 메소드는 public
- 혹시 모르니 아예 게임 Start()에서 멤버변수를 초기화 해주자.
- 음.. 그래서 일반적으로 다음과 같이 캡슐화 하라고 한다..
using UnityEngine.UI; (UI 보여주기)
응집성을 낮추기 위해 따로 DrawText() 메소드를 만들자
보간문자열 String Formating
- "문자열" 이라고 있는 이 큰 따옴표(") 앞에 달라($)표기를 해주면 중괄호 안에 변수를 입력할 수 있습니다.
- 예를들어 $"문자열 테스트 {num}" 이런식으로 만들 수 있다는 이야기 입니다. 직접 예제를 보시죠.
int a = 10; int b = 20; Console.WriteLine($"string example1 : {a} + {b} = {a+b}")
- 예를들어 $"문자열 테스트 {num}" 이런식으로 만들 수 있다는 이야기 입니다. 직접 예제를 보시죠.
코인획득 UI 결과
- 다음은 코인을 얻을때 좌측상단의 초록 텍스트의 숫자가 올라가는것을 볼 수있다
스크립트 클래스 컴포넌트의 차이
같은 클래스라도 따로 생성된 인스턴스는 각각 메모리 공간이 다르다.
오브젝트 슈터 & Time.Delta
1. 오브젝트 슈터
오브젝트의 발사는 어떻게 하는건가?
- 날아간다는것은 어떻게 표현되는거지?
- 목표지점/타겟 설정
- Vector3.MoveTowards
transform.position = Vector3.MoveTowards(vector3 _현재위치_ ,vector3 _타겟_,_스피드f_);
- 애니메이션 설정 (Rotate)
transform.Rotate(new Vector3(x,y,z));
- 소비된후 파괴
- OnCollisionEnter & 트리거를 쓰든...
void OnCollisionEnter(Collider _col){ if(_col.gameObject.name == "Ball"){ worldGM.Restart(); } }
- OnCollisionEnter & 트리거를 쓰든...
결과_1 : 직선 탄
- 타겟 위치는 Start에서만 초기화
public GameObject GM; public GameObject target; private GameManager worldGM; private Vector3 targetPos; private void OnCollisionEnter(Collision _col) { if(_col.gameObject.name == target.name){ Destroy(gameObject); worldGM.RestartGame(); } } // Start is called before the first frame update void Start() { worldGM = GM.GetComponent<GameManager>(); targetPos = target.transform.position; } // Update is called once per frame void Update() { transform.Rotate(new Vector3(0,0,5)); transform.position = Vector3.MoveTowards(transform.position, targetPos, 0.1f); }
결과_2 : 유도 탄
- Update 마다 타겟위치 초기화
void Update() { targetPos = target.transform.position; transform.Rotate(new Vector3(0,0,5)); transform.position = Vector3.MoveTowards(transform.position, targetPos, 0.1f); }
2. 오브젝트 위치 세팅 Global & Local
1.Local은 Scene 기준 기즈모
2.Global은 대상 오브젝트 기준 기즈모
Local | Global |
---|---|
3. Time.delta
- 델타 타임 카운트
timeCount += Time.deltaTime; if(timeCount > _N초_){...}
- 델타 타임 초기화
timeCount = 0;
4. 오브젝트 생성/출산(?)
Instantiate
- Instantiate를 통해 오브젝트를 런타임동안 생성할 수 있다
Instantiate(_만들 오브젝트_, _자신의 위치_, _돌아간 정도_);
- 적용 코드
public GameObject GenOb; float timeCount = 0f; void Update() { timeCount += Time.deltaTime; if(timeCount > 3){ Instantiate(GenOb, transform.position, Quaternion.identity); timeCount = 0; } }
결과물
- 3개의 장애물이 탄막을 발사한다
4 Prefeb
Hierarchy에서 Project_Asset으로 드래그
- 나중에도 사용할 수 있게끔 오브젝트를 저장한다
- 다음은 드래그하는 모습
- 프리펩의 인스펙터 컴포넌트도 저장되었다.
- 다음은 드래그하는 모습
상속
1. 중복한 코드를 넣는것 비효율적이고 수정하기도 어렵다.
부모와 자식 & 설정
-
public class Shoting : MonoBehaviour //상속전 public class Shoting : _상속할 스크립트_ //상속후
부모클래스의 메소드 사용하기
- 일단 부모 클래스의 메소드는 다음과 같아야한다
- protected 작성
- 오직 자식 클래스만 호출할 수 있음
protected void _METHOD_() {};
- 자식 클래스에서 부모 메소드 호출하기
- base.부모메소드
base.Update();
- base.부모메소드
같은 클래스라도 따로 생성된 인스턴스는 각각 메모리 공간이 다르다.
⭐완강 경축⭐
❓❓❓ 의문점 & 해야할 일 ❓❓❓
1.스크립트는 사실 클래스 아닐까? ❓(다음에 찾아보기)
2.디자인 패턴 ❓(다음에 찾아보기)
3.MoveToward의 단점 ❓(다음에 찾아보기)
4. 타임 개념을 잘 알아보기 ❓(다음에 찾아보기)
5.C# 과 OOP를 확실하게 배우자 ❓(다음에 찾아보기)
6. 등등 여러강의를 더 보면서 공부하자 ❓(다음에 찾아보기)
1. 볼트
'게임 > 개발' 카테고리의 다른 글
| 니앙팽이 - 스크립터블 오브젝트 (게임 개발 : Unity) | ScriptableObject (0) | 2023.05.16 |
---|---|
|유니티| 4 | 충돌 감지 & 아이템과 배열 (0) | 2022.02.06 |
|유니티| 3 | 유저 입력 & 오브젝트 말풍선(텍스트) 띄우기 & 카메라와 마주보는 스프라이트 (0) | 2022.02.02 |
|유니티| 2 | 유니티 스크립트 (C# 문법) & 카메라가 오브젝트 따라가게 하기 & 밤낮 표현하기 (Light 회전) (0) | 2022.01.31 |
|유니티| 1 | 유니티 UI & 물리 적용시키기 & Rigid-Body & Bouncy (0) | 2022.01.25 |