728x90
Main
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
namespace Test3
{
//씬에 있는 모든 객체들 관리(Hero,Monster,MonsterGenerator)하는 컴포넌트
public class TestCreatePortalMain : MonoBehaviour
{
[SerializeField]
private MonsterGenerator monsterGenerator;
[SerializeField]
private GameObject heroPrefab;
[SerializeField]
private GameObject portalPrefab;
[SerializeField]
private ItemGenerator itemGenerator;
private HeroController heroController;
private List<MonsterController> monsterList;
// Start is called before the first frame update
void Start()
{
//히어로 생성
this.CreateHero();
//몬스터 생성
//컬렉션 사용전 반드시 초기화
this.monsterList = new List<MonsterController>();
MonsterController turtle = this.monsterGenerator.Generate(GameEnums.eMonsterType.Turtle, new Vector3(-3, 0, 0));
turtle.onDie = (rewardItemType) =>
{
Debug.Log("거북이 죽음");
var pos = turtle.gameObject.transform. position;
this.CreateItem(rewardItemType, pos);
Destroy(turtle.gameObject);
};
MonsterController slime = this.monsterGenerator.Generate(GameEnums.eMonsterType.Slime, new Vector3(0, 0, 3));
slime.onDie = (rewardItemType) =>
{
Debug.Log("슬라임 죽음");
var pos = slime.gameObject.transform.position;
this.CreateItem(rewardItemType, pos);
Destroy(slime.gameObject);
};
//만들어진 개체들을 그룹화 관리
//배열, 컬렉션
//동적 배열
this.monsterList.Add(turtle);
this.monsterList.Add(slime);
Debug.LogFormat("this.monsterList.Count : {0}", this.monsterList.Count);
//리스트 요소들을 출력
foreach(MonsterController monster in this.monsterList)
{
Debug.LogFormat("monster: {0}", monster);
}
}
// Update is called once per frame
void Update()
{
//Test
//Ray연습 클릭해서 선택 몬스터를 제거하자
//화면을 클릭하면 Ray를 만든다
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
float maxDistance = 10f;
//화면에 출력
Debug.DrawRay(ray.origin, ray.direction * maxDistance, Color.red, 2f);
//Ray사용하여 충돌체크
RaycastHit hit;
//몬스터와 충돌했다면
if (Physics.Raycast(ray, out hit, maxDistance))
{
//충돌 감지해서
Debug.LogFormat("hit.collider: {0}", hit.collider);
MonsterController controller = hit.collider.gameObject.GetComponent<MonsterController>();
//해당 몬스터를 제거
if (controller != null)
{
//리스트에서 제거
this.monsterList.Remove(controller);
Debug.LogFormat("this.monsterList.Count : {0}", this.monsterList.Count);
//몬스터 죽는 애니메이션 플레이
controller.Die();
}
//남은 몬스터가 없다면 임의의 위치에 포털 생성
if (this.monsterList.Count <= 0)
{
this.CreatePortal();
}
//히어로 이동
this.heroController.Move(hit.point);
}
}
}
//히어로 생성 메서드
private void CreateHero()
{
GameObject heroGo = Instantiate(this.heroPrefab);
this.heroController = heroGo.GetComponent<HeroController>();
}
//포탈 생성 메서드
private void CreatePortal()
{
GameObject portalGo = null;
portalGo = Instantiate(this.portalPrefab);
int x = Random.Range(-3, 3);
int z = Random.Range(-3, 3);
//위치 설정(랜덤)
portalGo.transform.position = new Vector3(x, 0f, z);
}
//아이템 생성 메서드
private void CreateItem(GameEnums.eItemType itemType, Vector3 position)
{
this.itemGenerator.GenerateItem(itemType, position);
}
}
}
GameEnums
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameEnums
{
//몬스터 타입
public enum eMonsterType
{
Turtle, Slime
}
//아이템 타입
public enum eItemType
{
Sword, Shield, Potion
}
}
MonsterGenerator
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Test3
{
public class MonsterGenerator : MonoBehaviour
{
//[SerializeField] private GameObject turtlePrefab;
//[SerializeField] private GameObject slimePrefab;
[SerializeField]
private List<GameObject> prefabList; //동적 배열 (컬렉션 사용전 반드시 인스턴스화)
// Start is called before the first frame update
void Start()
{
//int index = 0;
//foreach(GameObject prefab in this.prefabList)
//{
// Debug.LogFormat("index : {0} ,prefab: {1}",index++, prefab);
//}
for(int i = 0; i < this.prefabList.Count; i++)
{
GameObject prefab = this.prefabList[i];
Debug.LogFormat("index : {0} ,prefab: {1}", i, prefab);
}
}
//몬스터 생성 메서드
//"monsterType" : 생성하려고 하는 몬스터의 타입
//"initPosition" : 생성된 몬스터의 초기 위치(월드좌표)s
public MonsterController Generate(GameEnums.eMonsterType monsterType, Vector3 initPosition)
{
Debug.LogFormat("monsterType: {0}", monsterType);
//몬스터 타입에 따라 어떤 프리팹으로 프리팹 복사본(인스턴스)를 생성할지 결정 해야함
//Instantiate(프리팹)
//몬스터 타입을 인덱스로 변경
int index = (int)monsterType;
Debug.LogFormat("index: {0}", index);
//프리팹 배열에서 인덱스로 프리팹을 가겨옴
GameObject prefab = this.prefabList[index];
Debug.LogFormat("prefab : {0}",index);
//프리팹 인스턴스를 생성
GameObject go = Instantiate(prefab); //위치를 결정하지 않은 상태이기 때문(프리팹의 설정된 위치에 생성됨)
//동적으로 컴포넌트를 부착할 수 있음(몬스터 프리팹에 몬스터 컨트롤러 붙이기!)
//컨트롤러가 부착되어있지 않다면 부착해주자!
//if(go.GetComponent<MonsterController>() == null)
//{
// MonsterController controller = go.AddComponent<MonsterController>();
//}
//위치를 설정
go.transform.position = initPosition;
return go.GetComponent<MonsterController>();
}
}
}
ItemGenerator
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
namespace Test3
{
public class ItemGenerator : MonoBehaviour
{
[SerializeField]
private List<GameObject> itemList;
private MonsterController monsterController;
void Start()
{
for(int i =0; i < itemList.Count; i++)
{
GameObject item = itemList[i];
Debug.LogFormat("index: {0} , prefab : {1}", i, item);
}
}
public void GenerateItem(GameEnums.eItemType itemType,Vector3 position)
{
Debug.LogFormat("itemType : {0}", itemType);
//아이템 타입을 인덱스로 변경
int index = (int)itemType;
Debug.LogFormat("ItemIndex : {0}", index);
//아이템 배열에서 인덱스로 아이템(프리팹)을 가져옴
GameObject item = this.itemList[index];
Debug.LogFormat("item : {0}", index);
//아이템 인스턴스를 생성
GameObject itemGo = Instantiate(item);
itemGo.transform.position = position;
//컨트롤러 가져오기
var controller = itemGo.GetComponent<ItemController>();
}
}
}
HeroController
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Test3
{
public class HeroController : MonoBehaviour
{
private MonsterController target;
private Vector3 targetPosition;
private Animator anim;
//public System.Action onMoveComplete;
// Start is called before the first frame update
void Start()
{
this.anim = GetComponent<Animator>();
}
//이동 메서드
public void Move(Vector3 targetPosition)
{
//이동할 목표지점을 저장
this.targetPosition = targetPosition;
//이동
this.anim.SetInteger("State", 1);
//코루틴 실행
this.StartCoroutine(this.CoMove());
}
//코루틴 이동
private IEnumerator CoMove()
{
//while 동안 실행
while (true)
{
//방향을 바라봄
this.transform.LookAt(this.targetPosition);
//바라봤으니까 정면으로 이동(이동로직)
this.transform.Translate(Vector3.forward * 2f * Time.deltaTime);
//목표지점과 나와의 거리 재기
float distance = Vector3.Distance(this.transform.position, this.targetPosition);
//타겟이 있는가?
if(distance <= 0.1f)
{
//도착
break;
}
yield return null; //다음 프레임 시작
}
Debug.Log("<color=yellow>도착!</color>");
this.anim.SetInteger("State", 0);
//대리자를 호출
//this.onMoveComplete();
}
}
}
MonsterController
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Test3
{
public class MonsterController : MonoBehaviour
{
private Animator anim;
[SerializeField]
private GameEnums.eItemType rewardItemType;
public System.Action<GameEnums.eItemType> onDie; //대리자 변수 선언
public void Awake()
{
this.anim = this.GetComponent<Animator>();
}
public void Die()
{
//코루틴 호출
StartCoroutine(this.coDie());
}
//죽고 리워드 아이템 생성 코루틴
private IEnumerator coDie()
{
this.anim.SetInteger("State", 3);
yield return new WaitForSeconds(2.0f);
this.onDie(this.rewardItemType); //대리자 호출
}
}
}
ItemController
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Test3
{
public class ItemController : MonoBehaviour
{
[SerializeField]
public GameEnums.eItemType itemType;
public GameEnums.eItemType ItemType
{
get { return this.itemType; }
}
}
}
'KDT > 유니티 기초' 카테고리의 다른 글
23/08/11 할거 (0) | 2023.08.11 |
---|---|
23/08/10 내용 복습 (0) | 2023.08.10 |
23/08/09 SimpleRPG (+ 이펙트 효과) (0) | 2023.08.09 |
23/08/09 SimpleRPG 몬스터 공격 및 데미지 받기 (0) | 2023.08.09 |
23/08/08 복습 - 내용정리 (0) | 2023.08.08 |