유니티 기초
몬스터 아이템 드랍 + 장착(?)하고 포탈로 이동하기
송현호
2023. 8. 10. 17:41
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using Test3;
using static Test3.GameEnums;
public class ItemGenerator : MonoBehaviour
{
[SerializeField]
private List<GameObject> prefabList;
// Start is called before the first frame update
public Action onDie;
void Start()
{
}
// Update is called once per frame
void Update()
{
}
public ItemController Generate(GameEnums.eItemType itemType, Vector3 initPosition)
{
int index = (int)itemType;
Debug.LogFormat("index: {0}", index);
//프리팹 배열에서 인덱스로 프리팹 가져옴
GameObject prefab = this.prefabList[index];
Debug.LogFormat("prefab: {0}", index);
//프리팹 인스턴스를 생성
GameObject go = Instantiate(prefab); //위치를 결정 하지 않은 상태이기때문 (프리팹의 설정된 위치에 생성됨)
//위치를 설정
go.transform.position = initPosition;
return go.GetComponent<ItemController>();
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
namespace Test3
{
public class ItemController : MonoBehaviour
{
public GameEnums.eItemType itemType;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
public void OnTriggerEnter(Collider other)
{
if (other.tag == "Hero")
{
HeroController heroController = other.gameObject.GetComponent<HeroController>();
heroController.GetItem(this.gameObject);
Destroy(this.gameObject);
}
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
namespace Test3
{
public class HeroController : MonoBehaviour
{
public Animator anim;
private Coroutine moveRoutine;
private MonsterController target;
private Vector3 targetPosition;
private Action getItem;
[SerializeField]
// Start is called before the first frame update
void Start()
{
anim = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
}
public void Move(Vector3 targetPosition)
{
//타겟을 지움
this.target = null;
//이동할 목표지점을 저장
this.targetPosition = targetPosition;
Debug.Log("Move");
this.anim.SetInteger("State", 1);
if (this.moveRoutine != null)
{
//이미 코루틴이 실행중이다 -> 중지
this.StopCoroutine(this.moveRoutine);
}
this.moveRoutine = this.StartCoroutine(this.CoMove());
}
private IEnumerator CoMove()
{
while (true)
{
//방향을 바라봄
this.transform.LookAt(this.targetPosition);
//이미 바라봤으니깐 정면으로 이동 (relateTo : Self/지역좌표)
this.transform.Translate(Vector3.forward * 1f * Time.deltaTime);
//목표지점과 나와의 거리를 잼
float distance = Vector3.Distance(this.transform.position, this.targetPosition);
//Debug.Log(distance);
//0이 될수 없다 가까워질때 도착한것으로 판단 하자
//타겟이 있을경우
if (this.target != null)
{
if (distance <= (1f + 1f))
{
break;
}
}
else
{
if (distance <= 0.1f)
{
break;
}
}
yield return null; //다음 프레임 시작
}
Debug.Log("<color=yellow>도착!</color>");
this.anim.SetInteger("State", 0);
//대리자를 호출
}
public void GetItem(GameObject item)
{
GameObject Sword = Instantiate(item, this.transform);
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace Test3
{
public class PortalController : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
public void OnTriggerEnter(Collider other)
{
if(other.gameObject.tag == "Hero")
{
SceneManager.LoadScene("BossScene");
}
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Test3 {
public class GameEnums
{
public enum eMonsterType
{
Turtle,Slime
}
public enum eItemType
{
Sword, Shield, Potion
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
namespace Test3
{
public class MonsterGenerator : MonoBehaviour
{
[SerializeField]
private List<GameObject> prefabList; //동적 배열
// Start is called before the first frame update
public Action onDie;
void Start()
{
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];
Debug.LogFormat("prefab: {0}", index);
//프리팹 인스턴스를 생성
GameObject go = Instantiate(prefab); //위치를 결정 하지 않은 상태이기때문 (프리팹의 설정된 위치에 생성됨)
//위치를 설정
go.transform.position = initPosition;
return go.GetComponent<MonsterController>();
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
namespace Test3
{
public class MonsterController : MonoBehaviour
{
private GameEnums.eItemType itemType;
public Action<GameEnums.eItemType> onDie;
[SerializeField]
private Animator anim;
// Start is called before the first frame update
void Start()
{
anim = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
}
public void Die()
{
bool state = false;
AnimationClip[] animationClips = anim.runtimeAnimatorController.animationClips;
for(int i = 0; i < animationClips.Length; i++)
{
if (animationClips[i].name == "Die")
{
state = true;
}
}
if (state)
{
StartCoroutine(CoDie());
}
else
{
this.onDie(this.itemType);
}
}
public IEnumerator CoDie()
{
this.anim.SetInteger("State", 2);
yield return new WaitForSeconds(2.5f);
this.onDie(this.itemType);
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Test3
{
public class TestCreatePortalMain : MonoBehaviour
{
[SerializeField]
private GameObject hero;
private HeroController heroController;
[SerializeField]
private MonsterGenerator monsterGenerator;
private List<MonsterController> monsterList;
[SerializeField]
private PortalController portalController;
[SerializeField]
private List<ItemController> itemList;
[SerializeField]
private ItemGenerator itemGenerator;
// Start is called before the first frame update
void Start()
{
heroController = CreateHero(new Vector3(-3, 0, -3));
this.monsterList = new List<MonsterController>();
MonsterController turtle = this.monsterGenerator.Generate(GameEnums.eMonsterType.Turtle, new Vector3(0,0,3));
turtle.onDie = (itemType) =>
{
this.itemGenerator.Generate(itemType, turtle.transform.position);
Destroy(turtle.gameObject);
};
MonsterController slime = this.monsterGenerator.Generate(GameEnums.eMonsterType.Slime, new Vector3(3, 0, 0));
slime.onDie = (itemType) =>
{
this.itemGenerator.Generate(itemType, slime.transform.position);
Destroy(slime.gameObject);
};
this.monsterList.Add(turtle);
this.monsterList.Add(slime);
this.itemList = new List<ItemController>();
//this.monsterGenerator.onDie = () => {
// //아이템을 생성한다
// //Instantiate(ItemList[]);
// ItemController item = this.itemGenerator.Generate(dropItemType);
// this.itemList.Add(item);
//};
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
float maxDistance = 100f;
Debug.DrawRay(ray.origin, ray.direction, Color.red, 3f);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, maxDistance))
{
MonsterController controller = hit.collider.gameObject.GetComponent<MonsterController>();
if(controller != null)
{
this.monsterList.Remove(controller);
controller.Die();
Debug.LogFormat("남은 수: {0}",this.monsterList.Count);
if (this.monsterList.Count == 0)
{
this.CreatePortal();
}
}
else if (hit.collider.tag == "Ground")
{
Debug.Log(hit.point);
this.heroController.Move(hit.point);
}
}
}
}
public void CreatePortal()
{
Instantiate(portalController);
}
public HeroController CreateHero(Vector3 initPosition)
{
GameObject go = Instantiate(hero);
go.transform.position = initPosition;
return go.GetComponent<HeroController>();
}
private void CreateItem(GameEnums.eItemType itemType, Vector3 position)
{
this.itemGenerator.Generate(itemType, position);
}
}
}
개선점 - 획득한 아이템 원할 때 장착하기, 장착한 아이템 위치/각도 조정하기, UI꾸미기