씬의 몬스터 제거시 포탈 생성 연습(동적 데이터 생성 및 관리)

-Main이 Generator에게 명령해서 몬스터를 생성한
다.

-몬스터 제너레이터에 Generate함수를 만들어준다. GameEnums는 몬스터 타입을 담고있다.


-코드 수정

-몬스터가 제거되면 포탈이 나타나는것을 테스트하기 위해 몬스터 클릭시 제거되는 것으로 한 뒤에 구현해 보았다.


-몬스터가 제거되면 아이템을 생성하기 위해 GameEnums수정








hero프리팹에 rigidbody달고, iskynematic 체크, 콜라이더도 넣는다.
아이템에도 콜라이더를 넣어 충돌체크하자.
OnTriggerEnter사용



그렇다면 아이템을 먹고 그 아이템이 장비아이템이라면 장착은 어떻게 할까?
hero가 착용하고 있던 아이템을 삭제하고, 그 부분에 새로운 아이템이 장착되어야 할 것이다.
코드가 길어졌으므로 다음 포스팅에 이어 작성하겠다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameEnums
{
public enum eMonsterType
{
Tutle,Slime
}
public enum eItemType
{
Potion,Sword,Shield
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Test3
{
public class MonsterController : MonoBehaviour
{
public int monsterhp;
public System.Action<GameEnums.eItemType> onDie; //대리자변수 선언
private GameEnums.eMonsterType monstertype;
[SerializeField]
private GameEnums.eItemType rewardItemType;
private Animator anim;
// Start is called before the first frame update
void Start()
{
this.anim = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
}
public void HitDamage()
{
//if (monsterhp <=0) //hp 0 이하
//{
this.Die();
// }
}
private void Die()
{
StartCoroutine(this.CoDie());
}
private IEnumerator CoDie()
{
this.anim.SetInteger("State", 3);
yield return new WaitForSeconds(2.0f);
this.onDie(this.rewardItemType); //대리자 호출
//죽으면 아이템 타입 리턴
}
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using Test3;
using UnityEngine;
namespace Test3
{
public class Test_CreatePortalSceneMain : MonoBehaviour
{
[SerializeField]
private MonsterGenerator monsterGenerator;
private MonsterController monsterController;
private ItemGenerator itemGenerator;
private ItemController itemController;
private List<MonsterController> monsterList = new List<MonsterController>();
private List<ItemController> itemList = new List<ItemController>();
private float maxDistance = 100f;
[SerializeField]
private GameObject portalPrefab;
[SerializeField]
private GameObject heroPrefab;
// Start is called before the first frame update
void Start()
{
this.monsterGenerator = GameObject.FindObjectOfType<MonsterGenerator>();
this.monsterController = GameObject.FindObjectOfType<MonsterController>();
this.itemGenerator = GameObject.FindObjectOfType<ItemGenerator>();
this.itemController = GameObject.FindObjectOfType<ItemController>();
MonsterController turtleController = this.monsterGenerator.Generate(GameEnums.eMonsterType.Tutle, new Vector3(-3, 0, 0));
turtleController.onDie = (rewardItemType) => {
Debug.Log("거북이 죽음");
var pos = turtleController.gameObject.transform.position;
Destroy(turtleController.gameObject);
this.CreateItem(rewardItemType, pos);
};
MonsterController slimeController = this.monsterGenerator.Generate(GameEnums.eMonsterType.Slime, new Vector3(0, 0, 3));
slimeController.onDie = (rewardItemType) =>
{
Debug.Log("슬라임 죽음");
Vector3 pos = slimeController.gameObject.transform.position;
Destroy(slimeController.gameObject);
this.CreateItem(rewardItemType, pos);
};
//만들어진 개체들을 그룹화 관리
//배열, 컬렉션
//동적 배열
this.monsterList.Add(turtleController);
this.monsterList.Add(slimeController);
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()
{
//Ray로 클릭해서 몬스터 제거
if (Input.GetMouseButton(0))//마우스 좌클릭시
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Debug.DrawRay(ray.origin, ray.direction * maxDistance, Color.red, 3f);//ray 그리기
RaycastHit hit;// Raycast에서 out 키워드 사용을 위한 변수 선언
if (Physics.Raycast(ray, out hit, maxDistance)) //Ray 충돌검사
{ //충돌감지해서 몬스터 제거
monsterController = hit.collider.gameObject.GetComponent<MonsterController>();
if (monsterController != null)//몬스터 클릭시
{
this.monsterList.Remove(monsterController);
Debug.Log("HitMonster");
monsterController.HitDamage();
if (monsterList.Count <= 0)
{//몬스터가 다 제거되면 포탈생성
Instantiate(this.portalPrefab);
this.portalPrefab.transform.position = new Vector3(6, 0, 10);
//영웅 생성
Instantiate(this.heroPrefab);
this.heroPrefab.transform.position = new Vector3(this.transform.position.x+1,0,0);
}
}
}
}
}
private void CreateItem(GameEnums.eItemType itemType, Vector3 position)
{
this.itemGenerator.GenerateItem(itemType, position);
}
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using Test3;
using UnityEngine;
namespace Test3
{
public class Test_CreatePortalSceneMain : MonoBehaviour
{
[SerializeField]
private MonsterGenerator monsterGenerator;
private MonsterController monsterController;
private ItemGenerator itemGenerator;
private ItemController itemController;
private List<MonsterController> monsterList = new List<MonsterController>();
private List<ItemController> itemList = new List<ItemController>();
private float maxDistance = 100f;
[SerializeField]
private GameObject portalPrefab;
[SerializeField]
private GameObject heroPrefab;
// Start is called before the first frame update
void Start()
{
this.monsterGenerator = GameObject.FindObjectOfType<MonsterGenerator>();
this.monsterController = GameObject.FindObjectOfType<MonsterController>();
this.itemGenerator = GameObject.FindObjectOfType<ItemGenerator>();
this.itemController = GameObject.FindObjectOfType<ItemController>();
MonsterController turtleController = this.monsterGenerator.Generate(GameEnums.eMonsterType.Tutle, new Vector3(-3, 0, 0));
turtleController.onDie = (rewardItemType) => {
Debug.Log("거북이 죽음");
var pos = turtleController.gameObject.transform.position;
Destroy(turtleController.gameObject);
this.CreateItem(rewardItemType, pos);
};
MonsterController slimeController = this.monsterGenerator.Generate(GameEnums.eMonsterType.Slime, new Vector3(0, 0, 3));
slimeController.onDie = (rewardItemType) =>
{
Debug.Log("슬라임 죽음");
Vector3 pos = slimeController.gameObject.transform.position;
Destroy(slimeController.gameObject);
this.CreateItem(rewardItemType, pos);
};
//만들어진 개체들을 그룹화 관리
//배열, 컬렉션
//동적 배열
this.monsterList.Add(turtleController);
this.monsterList.Add(slimeController);
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()
{
//Ray로 클릭해서 몬스터 제거
if (Input.GetMouseButton(0))//마우스 좌클릭시
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Debug.DrawRay(ray.origin, ray.direction * maxDistance, Color.red, 3f);//ray 그리기
RaycastHit hit;// Raycast에서 out 키워드 사용을 위한 변수 선언
if (Physics.Raycast(ray, out hit, maxDistance)) //Ray 충돌검사
{ //충돌감지해서 몬스터 제거
monsterController = hit.collider.gameObject.GetComponent<MonsterController>();
if (monsterController != null)//몬스터 클릭시
{
this.monsterList.Remove(monsterController);
Debug.Log("HitMonster");
monsterController.HitDamage();
if (monsterList.Count <= 0)
{//몬스터가 다 제거되면 포탈생성
Instantiate(this.portalPrefab);
this.portalPrefab.transform.position = new Vector3(6, 0, 10);
//영웅 생성
Instantiate(this.heroPrefab);
this.heroPrefab.transform.position = new Vector3(this.transform.position.x+1,0,0);
}
}
}
}
}
private void CreateItem(GameEnums.eItemType itemType, Vector3 position)
{
this.itemGenerator.GenerateItem(itemType, position);
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ItemController : MonoBehaviour
{
[SerializeField]GameEnums.eItemType itemType;
public GameEnums.eItemType ItemType
{
get
{
return this.itemType;
}
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
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()
{
//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);
}
}
// Update is called once per frame
void Update()
{
}
public MonsterController Generate(GameEnums.eMonsterType monsterType, Vector3 initPosition)
{//몬스터 타입에 따라 어떤 프리팹으로 복사본(인스턴스)를 생성할지 결정
Debug.LogFormat("monstertype: {0}", monsterType);
int index = (int)monsterType;//몬스터 타입 인덱스로 변경
Debug.LogFormat("index: {0}", index);
GameObject prefab = this.prefabList[index];
GameObject go = Instantiate(prefab);//위치를 결정 하지 않은 상태 (프리팹의 설정된 위치에 생성됨)
go.transform.position = initPosition;//위치를 설정
//if(go.GetComponent<MonsterController>() != null)
//{//부착되어 있다면
// Destroy(go.GetComponent<MonsterController>());
//}
if (go.GetComponent<MonsterController>()== null)
{
//동적으로 컴포넌트를 부착 할수 있음
MonsterController controller = go.AddComponent<MonsterController>();
}
////몬스터 타입에 따라 프리팹을 골라내야함
//switch(monsterType){=>프리팹 하나씩 생성해야함
// case GameEnums.eMonsterType.Tutle:
// // Instantiate(this.turtlePrefab);
// break;
//}
return go.GetComponent<MonsterController>();
}
}
}
using System.Collections;
using System.Collections.Generic;
using Test3;
using TMPro;
using UnityEngine;
namespace Test3
{
public class HeroController : MonoBehaviour
{
private float maxDistance = 100f;
private Animator anim;
private Vector3 targetPosition;
// private GameEnums.eItemType itemType;
// Start is called before the first frame update
void Start()
{
this.anim = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
if(Input.GetMouseButtonDown(0))//좌클릭시
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Debug.DrawRay(ray.origin,ray.direction*maxDistance,Color.red,3f);//ray그리기
RaycastHit hit;
if(Physics.Raycast(ray, out hit, maxDistance)) //충돌검사
{
// this.transform.position = hit.point;
if (hit.collider.tag == "Item")// 아이템 클릭시
{
Debug.LogFormat("tag:{0}", hit.collider.tag);
//this.Move();
Move(new Vector3(hit.point.x,0,0));
}
else if(hit.collider.tag == "Ground")// Ground 클릭시
{
Debug.LogFormat("tag:{0}", hit.collider.tag);
Move(hit.point);
}
}
}
}
private void Move(Vector3 targetPos)
{ this.targetPosition = targetPos;
Debug.Log("move");
StartCoroutine(CoMove());
}
private IEnumerator CoMove()
{
while(true)
{
this.transform.LookAt(this.targetPosition);
anim.SetInteger("State", 1);//Run animation
this.transform.Translate(Vector3.forward * 2 * Time.deltaTime);//정면으로 이동
float distance = Vector3.Distance(this.transform.position, this.targetPosition);
if (distance < 0.1f)
{
Debug.Log("Stop");
anim.SetInteger("State", 0);//Idle
break;
}
yield return null;
}
Debug.Log("<color=yellow>도착!</color>");
}
private void OnTriggerEnter(Collider other)
{
if (other != null)
{//충돌하면
if (other.tag == "Item")
{
Debug.Log("아이템과충돌!");
Destroy(other.gameObject);
var item = other.gameObject.GetComponent<ItemController>();
if (item != null)
{
Debug.LogFormat("<color=red>ItemType: {0}</color>", item.ItemType);
}
}
}
}
}
}
'3d 콘텐츠 제작' 카테고리의 다른 글
아이템 획득 후 장비 착용 연습 2 (0) | 2023.08.11 |
---|---|
아이템 획득시, 장착 연습 (0) | 2023.08.11 |
SimpleRPG-GameScene에서 플레이어 이동 및 Attack (0) | 2023.08.09 |
Unity-공격 연습 (0) | 2023.08.09 |
Unity-플레이어 조작 구현 연습-이동하기 (0) | 2023.08.08 |