1.GameEnums.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameEnums
{
public enum eMonsterType
{
Turtle, Slime
}
public enum eItemType
{
Sword, Shield, HealthPotion
}
public enum eHeroState
{
Idle, Run, Attack
}
public enum eMonsterState
{
Idle, Die=3
}
}
2.ItemGenerator.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Test3
{
public class ItemGenerator : MonoBehaviour
{
[SerializeField]
private List<GameObject> itemPrefabs;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
public ItemController GenerateItem(GameEnums.eItemType itemType, Vector3 position)
{
GameObject prefab = itemPrefabs[(int)itemType];
GameObject item = Instantiate(prefab);
item.transform.position = position;
return item.GetComponent<ItemController>();
}
}
}
3.ItemController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Test3
{
public class ItemController : MonoBehaviour
{
[SerializeField]
private GameEnums.eItemType itemType;
public GameEnums.eItemType ItemType { get { return itemType; } }
//// Start is called before the first frame update
//void Start()
//{
//}
//// Update is called once per frame
//void Update()
//{
//}
}
}
4.MonsterGenerator.cs
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using UnityEngine;
namespace Test3
{
public class MonsterGenerator : MonoBehaviour
{
//[SerializeField]
//private GameObject TurtlePrefpb;
//[SerializeField]
//private GameObject SlimPrefab;
[SerializeField]
private List<GameObject> prefabList;
// Start is called before the first frame update
//void Start()
//{
//}
/// <summary>
/// 몬스터 생성
/// </summary>
/// <param name="monsterType">생성 하려고 하는 몬스터의 타입</param>
/// <param name="initPosition">생성된 몬스터의 초기 월드좌표param>
public MonsterController Generate(GameEnums.eMonsterType monsterType, Vector3 initPosition)
{
Debug.LogFormat("monster: {0}", monsterType);
//몬스터 타입에 따라 어떤 프리팹으로 복사본(인스턴스)를 생성할지 결정 해야 함
int index = (int)monsterType;
GameObject prefab = this.prefabList[index];
Debug.LogFormat("prefab: {0}", index);
GameObject go = Instantiate(prefab); //위치를 결정 하지 않은 상태이기때문(프리팹에 설정된 위치에 생성됨)
go.transform.position = initPosition;
return go.GetComponent<MonsterController>();
////게임오브젝트에 MonsterController가 이미 부착되어 있다면
//if (go.GetComponent<MonsterController>() != null)
//{
// Destroy(go.GetComponent<MonsterController>());
//}
//go.AddComponent<MonsterController>();
////게임오브젝트에 MonsterController가 부착 되어 있지 않다면
//if (go.GetComponent<MonsterController>() == null)
//{
// //동적으로 컴포넌트를 부착 할 수 있음.
// MonsterController controller = go.AddComponent<MonsterController>();
//}
}
}
}
5.MonsterController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Test3
{
public class MonsterController : MonoBehaviour
{
[SerializeField]
private GameEnums.eItemType itemType;
private Animator anim;
public System.Action<GameEnums.eItemType> onDie;
private GameEnums.eMonsterState monsterState;
// Start is called before the first frame update
void Awake()
{
anim=this.GetComponent<Animator>();
}
// Update is called once per frame
//void Update()
//{
//}
public void Die()
{
StartCoroutine(CoDie());
}
private IEnumerator CoDie()
{
this.monsterState = GameEnums.eMonsterState.Die;
this.anim.SetInteger("State", (int)this.monsterState);
Debug.LogFormat("monster state: {0}", this.monsterState);
AnimatorStateInfo animatorStateInfo = this.anim.GetCurrentAnimatorStateInfo(0);
yield return new WaitForSeconds(animatorStateInfo.length);
onDie(this.itemType);
yield return null;
}
}
}
6.HeroController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Test3
{
public class HeroController : MonoBehaviour
{
private Vector3 targetPosition;
private Coroutine moveRoutine;
private Animator anim;
GameEnums.eHeroState state;
public System.Action<ItemController> onGetItem;
private ItemController leftHandItemController;
private ItemController rightHandItemController;
// Start is called before the first frame update
void Start()
{
anim = this.GetComponent<Animator>();
}
// Update is called once per frame
//void Update()
//{
//}
public void Move(Vector3 targetPosition)
{
this.targetPosition = targetPosition;
this.transform.LookAt(this.targetPosition);
this.PlayAnimation(GameEnums.eHeroState.Run);
}
private void PlayAnimation(GameEnums.eHeroState state)
{
this.state = state;
this.anim.SetInteger("State", (int)this.state);
switch (this.state)
{
case GameEnums.eHeroState.Run:
if (moveRoutine != null)
StopCoroutine(moveRoutine);
moveRoutine = StartCoroutine(CoMove());
break;
}
}
private IEnumerator CoMove()
{
while (true)
{
this.transform.Translate(Vector3.forward * Time.deltaTime);
float distance = Vector3.Distance(this.targetPosition, this.transform.position);
if (distance < 0.1f)
{
break;
}
yield return null;
}
moveRoutine = null;
this.PlayAnimation(GameEnums.eHeroState.Idle);
}
private void OnTriggerEnter(Collider other)
{
if (other.tag == "Item")
{
if(moveRoutine!=null)
StopCoroutine(moveRoutine);
Debug.LogFormat("moveroutine: {0}", this.moveRoutine);
PlayAnimation(GameEnums.eHeroState.Idle);
ItemController item = other.GetComponent<ItemController>();
onGetItem(item);
}
}
public void SetItem(GameObject item)
{
ItemController itemController = item.GetComponent<ItemController>();
GameEnums.eItemType itemType = itemController.ItemType;
switch (itemType)
{
case GameEnums.eItemType.Sword:
GameObject preSwordGo = GameObject.Find("SwordPolyart");
preSwordGo.transform.SetParent(null);
preSwordGo.transform.position = this.transform.position;
preSwordGo.transform.Translate(0.5f, 0, 0.5f);
GameObject swordGo = GameObject.Find("Weapon");
Debug.LogFormat("swordGo: {0}", swordGo);
item.transform.position = swordGo.transform.position;
item.transform.SetParent(swordGo.transform);
break;
case GameEnums.eItemType.Shield:
GameObject preShieldGo = GameObject.Find("ShieldPolyart");
preShieldGo.transform.SetParent(null);
preShieldGo.transform.position = this.transform.position;
preShieldGo.transform.Translate(0.5f, 0, 0.5f);
GameObject shieldGo = GameObject.Find("Shield");
Debug.LogFormat("shieldGo: {0}", shieldGo);
item.transform.position = shieldGo.transform.position;
item.transform.SetParent(shieldGo.transform);
break;
case GameEnums.eItemType.HealthPotion:
break;
}
}
}
}
7.Test_CreatePortalMain.cs
using System.Collections;
using System.Collections.Generic;
using System.Security.Cryptography;
using UnityEngine;
namespace Test3
{
//씬의 모든 객체들을 관리하는 클래스 (컴포넌트)
public class Test_CreatePortalMain : MonoBehaviour
{
[SerializeField]
private MonsterGenerator monsterGenerator;
[SerializeField]
private GameObject portalPrefab;
[SerializeField]
private ItemGenerator itemGenerator;
private List<MonsterController> monsterList;
private List<ItemController> itemList;
[SerializeField]
private GameObject heroPrefab;
private HeroController heroController;
//private GameObject hero;
// Start is called before the first frame update
void Start()
{
//컬렉션 사용전 반드시 초기화
this.monsterList = new List<MonsterController>();
this.itemList = new List<ItemController>();
MonsterController turtle = this.monsterGenerator.Generate(GameEnums.eMonsterType.Turtle, new Vector3(-3, 0, 0));
//turtle.onDie = (item) =>
//{
// ItemController itemController = this.CreateItem(item, turtle.transform.position);
// itemList.Add(itemController);
// Destroy(turtle.gameObject);
// monsterList.Remove(turtle);
// Debug.LogFormat("count: {0}", monsterList.Count);
// if (monsterList.Count == 0)
// {
// this.CompleteAttackMonster();
// }
//};
MonsterController slime = this.monsterGenerator.Generate(GameEnums.eMonsterType.Slime, new Vector3(0, 0, 3));
//slime.onDie = (item) =>
//{
// ItemController itemController = this.CreateItem(item, slime.transform.position);
// itemList.Add(itemController);
// Destroy(slime.gameObject);
// monsterList.Remove(slime);
// Debug.LogFormat("count: {0}", monsterList.Count);
// if (monsterList.Count == 0)
// {
// this.CompleteAttackMonster();
// }
//};
//만들어진 개체들을 그룹화 관리
monsterList.Add(turtle);
monsterList.Add(slime);
Debug.LogFormat("this.monsterList.Count: {0}", this.monsterList.Count);
foreach (MonsterController monster in this.monsterList)
{
Debug.LogFormat("monster: {0}", monster);
}
//몬스터 대리자
for(int i=0;i<monsterList.Count;i++)
{
MonsterController temp = monsterList[i];
temp.onDie = (item) =>
{
ItemController itemController = this.CreateItem(item, temp.transform.position);
itemList.Add(itemController);
Destroy(temp.gameObject);
monsterList.Remove(temp);
Debug.LogFormat("count: {0}", monsterList.Count);
if (monsterList.Count == 0)
{
this.CompleteAttackMonster();
}
};
}
}
// Update is called once per frame
void Update()
{
//Test
//Ray연습할겸 클릭해서 선택 몬스터를 제거하자
//화면을 클릭하면 Ray를 만든다
//Ray를 사용해서 충돌체크를 한다
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Debug.DrawRay(ray.origin, ray.direction * 100f, Color.red, 2f);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 100f))
{
Debug.LogFormat("collider: {0}", hit.collider.tag);
if (hit.collider.tag == "Monster")
{
hit.collider.GetComponent<MonsterController>().Die();
}
else
{
if(monsterList.Count == 0)
{
float x = hit.point.x;
float z = hit.point.z;
Vector3 targetPosition = new Vector3(x, 0, z);
this.heroController.Move(targetPosition);
}
}
}
}
}
IEnumerator CoCreatePortal()
{
yield return new WaitForSeconds(0.3f);
GameObject portal = Instantiate(portalPrefab);
float x = Random.Range(-3.7f, 3.7f);
float z = Random.Range(-3.7f, 3.7f);
portal.transform.position = new Vector3(x, 0, z);
}
IEnumerator CoCreateHero()
{
yield return new WaitForSeconds(0.3f);
GameObject hero = Instantiate(heroPrefab);
float x = Random.Range(-3.7f, 3.7f);
float z = Random.Range(-3.7f, 3.7f);
hero.transform.position = new Vector3(x, 0, z);
heroController=hero.GetComponent<HeroController>();
heroController.onGetItem = (item) =>
{
Debug.LogFormat("{0}을 획득하였습니다.", item.ItemType);
itemList.Remove(item);
//Destroy(item.gameObject);
heroController.SetItem(item.gameObject);
};
}
private ItemController CreateItem(GameEnums.eItemType item, Vector3 position)
{
return this.itemGenerator.GenerateItem(item, position);
}
private void CompleteAttackMonster()
{
StartCoroutine(CoCreatePortal());
StartCoroutine(CoCreateHero());
}
}
}
추가할 예정임다,,,,
'K-digital traning > 유니티 기초' 카테고리의 다른 글
[주말과제]SimpleRPG (1) | 2023.08.14 |
---|---|
[주말과제] 이동 및 몬스터 공격 (0) | 2023.08.07 |
애니메이션 전환 연습 (0) | 2023.08.03 |
캐릭터 이동(달리기) 애니메이션 (0) | 2023.08.03 |
ClimbCloud (0) | 2023.08.02 |