유니티3D 3강
3강 소스자료
http://freebox.myqnapcloud.com:8080/share.cgi?ssid=0976X1B
애니메이션 리셋 트리거. 찾아볼것.
MoveNext() 찾아보기
NGUI
UI편집할때는 화면을 2D로 본다.
아틀라스 선행작업. 속도와 안정성 때문에 사용한다.
UI Root 는 NGUI의 캔버스라고 생각...
해상도 설정
Scaling Style
- flexible : 원래 이미지 크기
- Constrained (pc작업시) : 해상도 사이즈에 맞게 늘어나고 줄어듬 (가장 많이 쓰는 타입)
- Constrained Mobil (모바일 작업시) :
버튼 스프라이트 추가하고 버튼 스크립트 컴포넌트 연결
눌렀을때 크기 조절
==[ delgate ]=====
using UnityEngine; using System.Collections; public class delgate : MonoBehaviour { // 델리게이트 // 같은 매개변수를 가지고 있는 메서드를 대입 할 수 있다. 몇개라도. delegate void Calc(int a, int b); void Add(int a, int b) { // 스트링 변수 선언한 뒤에 들어오는 숫자는 문자가 된다. string result = "add :" + (a + b); print(result); } void Mul(int a, int b) { print("mul : " + (a * b)); } // Use this for initialization void Start () { /* Calc calc = Add; calc(10, 30); */ /* Calc calc = Add; calc = Mul; Mul(10, 10); */ /* Calc calc = Add; calc += Mul; calc(5, 5); */ /* Calc calc = Add; calc = Mul; Mul(10, 10); Add(15, 10); */ // 델리게이트형 배열 변수 calc생성 Calc[] calc = new Calc[2]; // calc에 메서드 대입 calc[0] = Add; calc[1] = Mul; /* for (int i = 0; i < calc.Length; i++) { calc[i](5, 5); } */ foreach (Calc n in calc) { n(5,5); } } }
======[ Spider ]===========
using UnityEngine; using System.Collections; public class Spider : MonoBehaviour { //델리게이트 선언 delegate void State(); // enum 코드의 효율성을 주고 싶을때. 문자로 표시 할 수 있음 가독성을 높일 수 있음. public enum SpiderState { // 첫번째 변수에 0을 대입하면 순차적으로 Move = 1, Attack = 2, Damage = 3 순으로 올라간다 None = -1,// 생성되어 있지 않고 아무것도 아닌 대기상태 Idle, Move, Attack, Damage, Dead, Max } //델리게이트 형 배열 선언 //(int)SpiderState.Max = enum 의 마지막.(int(숫자))형으로 변환 //배열을 맴버변수로 선언할때 메소드 위에 선언하면 메소드의 주소를 찾을 수 없다. State[] funState = null; // 애니메이션 컴포넌트 참조 할 변수 Animation monAni = null; GameObject target = null; //대기 시간 변수 float interVal = 0; //const 를 선언하면 값을 변할 수 없게 한다. const float attackRange = 3; //공격범위 const float attackTime = 2; //공격시간 int hp = 5; // enum 참조 // enum SpiderState를 변수 state에 대입 // 무브를 실행 하려면 = SpiderState state = SpiderState.Move; SpiderState state = SpiderState.Idle; //상태처리 함수 생성 void Idle() // 대기 { // monAni.Play("idle"); //타이머 설정 interVal += Time.deltaTime; //interVal변수에 현재 시간의 흐름(float)을 더해준다. if (interVal > attackRange) //2초 지난뒤 실행 { //2초 지난뒤 SpiderState.Move 호출 state = SpiderState.Move; interVal = 0; // 재활용을 위해 초기화 시킨다 } } void Move() { // 거리값 계간 함수 Vector3.Distance(a의 위치 , b의 위치); float distance = Vector3.Distance(target.transform.position, this.transform.position); //거리값으로 공격 호출 if (distance < attackRange) { state = SpiderState.Attack; // 인터벌 어택타임 3초로 대입하여 플레이어와 가까워 졌을때 바로 공격 interVal = attackRange; } else { // 이동 // 타겟 - 자기 자신 ( 방향 설정 ) * 이동 공식 외울것. // dir에 플레이어의 위지를 대입하고 자기 자신의 위치값을 뺀다. Vector3 dir = target.transform.position - this.transform.position; //normalized = ??? 벡터를 만들기 위해 실행 한 함수. dir.Normalize(); dir.y = 0; //이동 코드 = 자기 자신의 위치 += 이동방향 * 속도 * 시간 this.transform.position += dir * 5 * Time.deltaTime; // 플레이어의 회전 방향 대입 Quaternion to = Quaternion.LookRotation(dir); // 회전 Lerp() = 시간에 따라 부드러운 처리 사용 // Quaternion.Lerp(자기자신의 회전 방향(값), 바라보고 싶은 방향(값 플레이어),시간(회전할 시간 각) ); // 10 * Time.deltaTime 매 프레임마다 각을 계산 //this.transform.rotation = Quaternion.Lerp(this.transform.rotation,to, 10 * Time.deltaTime); this.transform.rotation = Quaternion.Lerp(this.transform.rotation, to, 0.05f); monAni.Play("walk"); // 이동 애니메이션 호출 } } void Attack() // 공격 { interVal += Time.deltaTime; // 2초에 한번 공격 if (interVal > attackTime) { monAni.Play("attack"); // 공격 애메니이션 호출 // PlayQueued : attack(이전 attack은 루프가 되면 안됨) 애니메이션 뒤에 idle 애니메이션을 추가 함. monAni.PlayQueued("idle"); interVal = 0; } //플레이어와 거리가 멀어지면 다시 idel 호출 if (Vector3.Distance(target.transform.position, this.transform.position) > attackRange) { state = SpiderState.Idle; interVal = 0; } } void Damage() // 데미지 { monAni.Play("damage"); monAni.PlayQueued("idle"); interVal = 0; state = SpiderState.Idle; hp--; if (hp <= 0) { state = SpiderState.Dead; } } void Dead() // 죽음 { state = SpiderState.None; // 코루틴 작동 안됨 StartCoroutine(DeadProcess()); // //Destroy(this.gameObject, 0.5f); } void Reset() { hp = 5; state = SpiderState.Idle; monAni.Play("idle"); } //public AnimationClip[] clip = null; IEnumerator DeadProcess() { monAni.Play("death"); //애니메이션 시간 구하기(레거시용) float length = monAni["death"].length; yield return new WaitForSeconds(length + 1); // 애니메이션 시간 + 1초 // 몬스터 사망시 아래로 내려가는 코드 while (this.transform.position.y > -2) { Vector3 temp = this.transform.position; //this.transform.position.y = .y로 바로 접근 할 수 없음. temp.y -= 0.5f * Time.deltaTime;// 매프레임마다 0.5f만큼 뺀다 this.transform.position = temp; // 코루틴 대기 ,일정 프레임에 한번씩 대기 동시 작업 가능 // 코루틴에서 while문을 사용 할 때 사용 yield return new WaitForEndOfFrame(); } Reset(); this.gameObject.SetActive(false); } void OnCollisionEnter(Collision col) { if (state == SpiderState.None || state == SpiderState.Dead) return; // 레이어 인덱스는 문자로 넣어도 숫자로 반환된다. // 레이어 인덱스는 int형 변수에 대입된다 int layerIndex = col.gameObject.layer; //레이어 마스크로 부딪히는 오브젝트 이름 가져옴 if (layerIndex == LayerMask.NameToLayer("ball")) { state = SpiderState.Damage; } /* if (col.gameObject.tag == "bullet") { state = SpiderState.Damage; } */ } void Start() { // 델리게이트 배열 대입 한줄로 선언. funState = new State[(int)SpiderState.Max] { Idle, Move, Attack, Damage, Dead }; // 델리게이트 배열에 각 메소드 대입 초기화 /* funState[(int)SpiderState.Idle] = Idle; funState[(int)SpiderState.Move] = Move; funState[(int)SpiderState.Attack] = Attack; funState[(int)SpiderState.Damage] = Damage; funState[(int)SpiderState.Dead] = Dead; */ // 매카닉(new) 애니메이션 방식은 Animator 레거시(old) 방식은 Animation // 몬스터 애니메이션에서 idle 애니메이션을 플레이 시킨다. 레거시 방식은 초기 루프가 기본이 아니다. monAni = GetComponent<Animation>(); // 태그로 플레이어 검색 target = GameObject.FindGameObjectWithTag("myPlayer"); } void Update() { // enum 의 메소드 호출 방법 delegate사용 if (state == SpiderState.None) return; funState[(int)state](); // enum 의 메소드 호출 방법 swich사용 /* switch (state) { case SpiderState.Idle: { Idle(); } break; case SpiderState.Move: { Move(); } break; case SpiderState.Attack: { Attack(); } break; case SpiderState.Damage: { Damage(); } break; case SpiderState.Dead: { Dead(); } break; } */ } }
===== [ MonsterGen ] =========
using UnityEngine; using System.Collections; public class MonsterGen : MonoBehaviour { float randX; float randZ; Vector3 genPos; public GameObject monster = null; //몬스터를 담아놓을 공간. 배열 생성 ( 배열을 생성할때 new를 붙인다) //const 절대 변하지 않는 변수 선언 , 배열에 변수를 대입할때는 const 선언을 해준다. const int poolArraySize = 10; GameObject[] enemyPool = new GameObject[poolArraySize]; void Start() { /* IEnumerator f = Factoy(); StartCoroutine(f); */ for (int i = 0; i < poolArraySize; ++i) { // 몬스터를 배열에 담음 enemyPool[i] = Instantiate(monster); //enemyPool[0] = monster0번이됨. enemyPool[i].SetActive(false); //SetActive는 업데이트에서 사용하면 느려진다. } StartCoroutine(Factoy()); } // 몬스터 생성 IEnumerator Factoy() { //몬스터 이름 인덱스 설정 //int index = 0; while (true) { yield return new WaitForSeconds(3); for (int i = 0; i < poolArraySize; ++i) { // enemyPool[i] 배열에 담긴 게임오브젝트를 mom 게임오브젝트 변수에 담는다 GameObject mon = enemyPool[i]; //activeSelf 게임오브젝트 자신의 active에 대한 반환값 (true of flase) if (mon.activeSelf == true) //배열에 담긴 게임오브젝트의 activeSelf 가 true라면 { continue; //true라면 재실행 false 라면 아래 코드 실행 } randX = Random.Range(20, -20); randZ = Random.Range(20, -20); genPos = new Vector3(randX, 0, randZ); mon.transform.position = genPos; mon.SetActive(true); break; // for 코드 종료 yield return new WaitForSeconds(3); 실행 } /* randX = Random.Range(20, -20); randZ = Random.Range(20, -20); genPos = new Vector3(randX, 0, randZ); GameObject mon = Instantiate(monster); mon.transform.position = genPos; // 몬스터의 이름 설정 mon.name = "Monster" + index; index++; */ } } }
댓글
댓글 쓰기