버튼 클릭시 몬스터 생성
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class TestMonsterGenerator : MonoBehaviour
{
public Button btn;
public int amount;
public string[] monsterPrefabNames;
public List<GameObject> monsterPrefabs;
public List<Monster> monsters;
void Start()
{
this.monsterPrefabs = new List<GameObject>();
this.monsters = new List<Monster>();
this.monsterPrefabNames = new string[] { "SlimePrefab", "TurtleShellPrefab", "ChestMonsterPrefab", "BeholderPrefab"};
//Debug.Log(this.monsterPrefabNames.Length);
this.LoadMonsterPrefabs();
//this.btn.onClick.AddListener(() =>
//{
// Debug.Log("hello!");
// for (int i = 0; i < this.amount; i++)
// {
// CreateMonster();
// }
//});
}
private void Update()
{
if (this.monsters.Count <= 0)
{
for (int i = 0; i < this.amount; i++)
{
CreateMonster();
}
}
}
private void LoadMonsterPrefabs()
{
foreach (var prefabName in this.monsterPrefabNames)
{
//리소스 폴더 경로설정
string path = string.Format("Prefabs/Monster/{0}", prefabName);
GameObject prefab = Resources.Load<GameObject>(path);
//해당 이름을 가진 프리팹이 리소스 폴더에 바로 있다면
//GameObject prefab = Resources.Load<GameObject>(prefabName);
this.monsterPrefabs.Add(prefab);
}
Debug.Log(this.monsterPrefabs.Count);
}
private void CreateMonster()
{
float x = Random.Range(-3f, 3f);
float z = Random.Range(-3f, 3f);
Vector3 initPos = new Vector3(x, 0, z);
GameObject go = new GameObject();
go.name = "monster";
go.tag = "Monster";
int monsterPrefabsIndex = Random.Range(0, this.monsterPrefabs.Count);
GameObject prefab = this.monsterPrefabs[monsterPrefabsIndex];
GameObject model = Instantiate<GameObject>(prefab, go.transform);
model.name = "model";
Monster monster = go.AddComponent<Monster>();
this.monsters.Add(monster);
monster.OnDie = () =>
{
Destroy(monster.gameObject);
//반드시 관리되는 컬렉션에서 제거
this.monsters.Remove(monster);
};
monster.Init(initPos);
}
}
| //데이터 테이블에서 불러올 프리팹이름 public string[] monsterPrefabNames; //몬스터 프리팹리스트 public List<GameObject> monsterPrefabs; //프리팹을 통해 생성된 몬스터 들을 관리 //사망시 리스트에서 제거해줘야된다 public List<Monster> monsters; //리소스 폴더의 프리팹 경로 string path = string.Format("Prefabs/Monster/{0}", prefabName); //해당 경로의 프리팹 파일 GameObject prefab = Resources.Load<GameObject>(path); //리스트에 추가 this.monsterPrefabs.Add(prefab); //몬스터 사망 이벤트를 받으면 monster.OnDie = () => { Destroy(monster.gameObject); //반드시 관리되는 컬렉션에서 제거 this.monsters.Remove(monster); }; |
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
public class Monster : MonoBehaviour
{
public float hp;
public float maxHp;
public float damage;
public float range;
public float moveSpeed;
public GameObject model;
private Animator anim;
Coroutine hitRoutin;
Coroutine attackRoutin;
bool isHit;
bool isAttack;
public bool isDie;
public UnityAction OnDie;
private void Start()
{
this.model = this.transform.GetChild(0).gameObject;
this.anim = this.model.GetComponent<Animator>();
}
public void Init(Vector3 initPos)
{
this.transform.position = initPos;
this.moveSpeed = 0.5f;
this.maxHp = 15;
this.hp = this.maxHp;
this.damage = 5;
this.range = 0.3f;
}
public void Hit(GameObject hero)
{
this.hp -= hero.GetComponent<Hero>().damage;
//때린 적을 바라본다.
this.transform.LookAt(hero.transform.position);
if (this.hitRoutin != null)
{
StopCoroutine(this.hitRoutin);
}
this.hitRoutin = StartCoroutine(HitAnimImpl());
if (this.hp <= 0)
{
this.OnDie();
StopCoroutine(this.hitRoutin);
StartCoroutine(DieAnimImpl());
}
//피격이 끝나면
Attack(hero);
}
IEnumerator HitAnimImpl()
{
this.isHit = true;
this.anim.SetBool("isHit", this.isHit);
yield return new WaitForSeconds(1/30*25); //1초에 30프레임, 25 애니메이션 프레임
this.isHit = false;
this.anim.SetBool("isHit", this.isHit);
yield return null;
}
IEnumerator DieAnimImpl()
{
this.isDie = true;
this.anim.SetBool("isDie", this.isDie);
yield return new WaitForSeconds(this.anim.GetCurrentAnimatorStateInfo(0).length);
Destroy(this.gameObject);
}
public void Attack(GameObject target)
{
//this.transform.LookAt(target.transform.position);
if (this.attackRoutin != null)
{
StopCoroutine(this.attackRoutin);
}
this.attackRoutin = StartCoroutine(AttackAnimImpl(target));
if (this.hp <= 0)
{
StopCoroutine(this.attackRoutin);
StartCoroutine(DieAnimImpl());
}
}
IEnumerator AttackAnimImpl(GameObject target)
{
//this.anim.Play("run@loop");
while (true)
{
this.transform.LookAt(target.transform.position);
float distance = Vector3.Distance(target.transform.position, this.transform.position);
if (distance <= this.range)
{
break;
}
this.transform.Translate(Vector3.forward * this.moveSpeed * Time.deltaTime);
yield return null;
}
this.isAttack = true;
this.anim.SetBool("isAttack", this.isAttack);
yield return new WaitForSeconds(1 / 30 * 9);
target.GetComponent<Hero>().Hit(this.gameObject);
yield return new WaitForSeconds(1 / 30 * 16);
this.isAttack = false;
this.anim.SetBool("isAttack", this.isAttack);
yield return null;
//this.anim.Play("idle@loop");
}
}
| using UnityEngine.Events; public UnityAction OnDie; //사망하면 이벤트를 전달해줘야됨 this.OnDie(); |
몬스터가 0마리면 자동생성
업데이트에서 몬스터리스트의 카운트가 0이면 생성
랜덤한 몬스터가 0마리면 자동생성
몬스터 생성시 몬스터 프리팹 리스트의 랜덤한 인덱스를 넣어서 랜덤한 몬스터 생성.
| int monsterPrefabsIndex = Random.Range(0, this.monsterPrefabs.Count); |
'Unity > 게임 엔진 응용 프로그래밍' 카테고리의 다른 글
| [Unity 3D] AppleCatch : 씬전환, 싱글턴 패턴 (0) | 2021.10.26 |
|---|---|
| [Unity] 데이터 테이블 로드하기 (0) | 2021.10.22 |
| [Unity 3D] MiniRPG : 몬스터와 전투 (0) | 2021.10.20 |
| [Unity 3D] MiniRPG : 캐릭터 공격 애니메이션 (0) | 2021.10.19 |
| [Unity 3D] MiniRPG : 캐릭터 생성과 이동 연결하기 (0) | 2021.10.19 |