[4Idle - Gazzlers] GameScene에 Wave 별로 Enemy 1,2,3 생성
https://made-myblog.tistory.com/72
-이 포스팅에서는 팀원이 test로 만들어준 Enemy관리 포스팅을 참고하여 GameScene에서 enemy1,2,3을 생성한다.
-enemy들은 wave별로 생겨나며, 각각 HPBar도 가지고 있으므로 연동시켜줘야한다.
Enemy생성
-EnemyPoolManager.cs에서 Enemy를 생성해두고, 비활성화 시켜두도록한다.
-비활성화 해둔 Enemy들을 필요할 때(Wave가 진행되어 호출할 때) 가져와서 활성화시킨다.
-EnableEnemy가 Enemy를 활성화시키는 코드이다.
-activeSelf를 사용해 enemy가 비활성화상태인지 확인한다.
https://docs.unity3d.com/ScriptReference/GameObject-activeSelf.html
-main의 start에서 코루틴을 호출한다. 코루틴함수는 enemy를 나타나게하는 함수이다.
-spawnEnemy에서 웨이브 1,2,3 을 확인하도록한다. 웨이브에 따라 나타나는 몬스터가 달라지게된다.
Enemy들에게 HPBar 연동
-main에서 enemy를 생성할 때, 대리자를 호출해 enemy의 정보를 가져오도록한다.
-정보는 enemyData를 돌며 enemy의 태그를 비교하여 확인한다.
- 가져온 정보를 Enemy1Move에 전달하여 값을 활용하도록 하였다.
=> OnGenerateEnemy에서 slider값을 변경시키고, 데이터를 전달한다.
Enemy 충돌처리 수정
-플레이어가 공격했을때 Enemy1만 확인되던 문제를 righthandController를 수정하여 해결하였다.
- 태그로 오브젝트를 식별하고 있었는데, enemy1만 받아오고 있었기 때문이다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System;
public class EnemyPoolManager : MonoBehaviour
{
public static EnemyPoolManager instance;
//[SerializeField] private GameObject enemyPrefab;
[SerializeField] private GameObject[] arrEnemyPrefabs;
// private List<Enemy1Move> enemyPool = new List<Enemy1Move>();
private List<List<GameObject>> enemyPool = new List<List<GameObject>>();
void Awake()
{
instance = this;
}
private void Start()
{
this.GenerateEnemy();
}
private void GenerateEnemy()
{
// for (int i = 0; i < 2; i++)
for(int i=0;i<this.arrEnemyPrefabs.Length; i++)
{
List<GameObject> list = new List<GameObject>();
for (int j = 0; j < 2; j++)
{
GameObject go = Instantiate(arrEnemyPrefabs[i], this.transform);
go.SetActive(false);
list.Add(go);
//GameObject go = Instantiate(enemyPrefab, this.transform);
//go.SetActive(false);
//enemyPool.Add(go.GetComponent<Enemy1Move>());
}
this.enemyPool.Add(list);
}
}
public GameObject EnableEnemy(int idx)
{
GameObject result = null;
for (int i = 0; i < enemyPool[idx].Count; i++)
{
// Debug.Log(enemyPool[idx][i]);
if (enemyPool[idx][i].activeSelf == false)
{
result = enemyPool[idx][i];
//result.gameObject.SetActive(true);
result.transform.SetParent(null);
break;
}
}
if (result == null)
{
result = Instantiate(arrEnemyPrefabs[idx]);
enemyPool[idx].Add(result);
}
return result;
}
public void DisableEnemy(GameObject enemy)
{
enemy.SetActive(false);
enemy.transform.SetParent(this.transform);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using System;
using System.Linq;
using Newtonsoft.Json;
using System.IO;
public class GameMain : MonoBehaviour
{
[SerializeField] Canvas worldCanvas;
[SerializeField] Canvas rightHandCanvas;
[SerializeField] TextMeshProUGUI guideText;
[SerializeField] GameObject uiHPBarPrefab;
[SerializeField] GameObject uiDamageTextPrefab;
[SerializeField] GameObject uiEnergyCellPrefab;
[SerializeField] GameObject gunEnergyCellGo;
[SerializeField] EnergyCellController energyCellForCharge;
[SerializeField] RightHandController rightHand;
[SerializeField] Transform uiEnergyCellTransform;
[SerializeField] Transform worldUITransform;
public bool isFirstHP = false;
private GameObject hpBarUIGo;
private GameObject damageTextUIGo;
private GameObject energyTextUIGo;
private Action<Enemy1Move> OnGenerateEnemy;
private string currGunType;
private int currGunDamage;
private int currGunEnergy;
private int currGunMaxEnergy;
private List<GameObject> enemyHpBarPools = new List<GameObject>();
private List<GameObject> activeHPBar = new List<GameObject>();
//----------------------------------SJY Map Main-----------------------------------------------------------
[SerializeField] private MapController mapController;
[SerializeField] private CamMove camMove;
//----------------------------------SJY Enemy1Move Main-----------------------------------------------------------
public enum eWave
{
WAVE1, WAVE2, WAVE3
}
private eWave wave;
[SerializeField] private Transform[] arrTargetPos;
private List<Enemy1Move> listEnemies = new List<Enemy1Move>();
private List<bool> isTargeted = new List<bool>();
private int EnemyCount = 2;
private int[] maxWaveEnemyCount = new int[3] { 3, 6, 9 };
private int remainEnemyCount;
private void Awake()
{
}
// Start is called before the first frame update
void Start()
{
Debug.Log("Start");
this.guideText.gameObject.SetActive(false);
this.worldCanvas.transform.SetParent(this.worldUITransform);
this.worldCanvas.transform.localPosition = Vector3.zero;
this.worldCanvas.transform.localRotation = Quaternion.identity;
this.energyTextUIGo = this.uiEnergyCellPrefab;
this.rightHandCanvas.transform.SetParent(this.uiEnergyCellTransform);
this.rightHandCanvas.transform.localPosition = Vector3.zero;
this.rightHandCanvas.transform.localRotation = Quaternion.identity;
DataManager.Instance.LoadPlayerDatas();
DataManager.Instance.LoadGunrDatas();
DataManager.Instance.LoadEnemyDatas();
List<PlayerData> playerData = DataManager.Instance.GetPlayerDatas();
List<GunData> gunData = DataManager.Instance.GetGunDatas();
List<EnemyData> enemyData = DataManager.Instance.GetEnemyDatas();
Debug.LogFormat("player Data Count: {0}",playerData.Count);
var playerGunId = playerData[0].currGunId;
//var playerGunId = 1000;
Debug.LogFormat("Gun Data Count: {0}", gunData.Count);
for (int i = 0; i < gunData.Count; i++)
{
if (playerGunId == gunData[i].gunId)
{//Find player's current gun's Data on GunData
Debug.Log(gunData[i].gunType);
this.currGunType = gunData[i].gunType;
this.currGunDamage = gunData[i].gunDamage;
this.currGunEnergy = gunData[i].gunEnergyCell;
this.currGunMaxEnergy = gunData[i].gunEnergyCell;
}
}
this.enemyHpBarPool();
this.damageTextUIGo = Instantiate(this.uiDamageTextPrefab, this.worldCanvas.transform);
this.damageTextUIGo.SetActive(false);
this.OnGenerateEnemy = (enemy) =>
{
var go = this.CreateHpBar(enemy.hpBarPoint.position);
this.activeHPBar.Add(go);
for (int j = 0; j < enemyData.Count; j++)
{
if (enemy.tag == enemyData[j].enemyType)
{
Debug.Log(enemyData[j].enemyType);
var slider = go.GetComponent<Slider>();
slider.maxValue = enemyData[j].enemyHp;
Debug.Log(slider.maxValue);
slider.value = slider.maxValue;//reset slider value as full state
//this.listEnemies[j].currHP = (int)slider.value; //set EnemyHp
//Debug.Log(listEnemies[j].gameObject);
enemy.OnGetData(enemyData[j]);
}
}
};
this.rightHand.OnHitEnemy = (hitPos,hitObject) =>
{
// Debug.LogFormat("Hit Enemy! Point: {0}", hitPos);
StartCoroutine(this.CoShowDamageText(hitPos));
for (int i = 0; i < this.listEnemies.Count; i++)
{
if (hitObject == this.listEnemies[i].gameObject)
{
Debug.LogFormat("Object: {0} , Damage : {1}",i,currGunDamage);
this.activeHPBar[i].GetComponent<Slider>().value -= currGunDamage;
hitObject.GetComponent<Enemy1Move>().OnGetHit(currGunDamage);
if(this.activeHPBar[i].GetComponent<Slider>().value <= 0)
{
this.activeHPBar[i].SetActive(false);
this.activeHPBar.Remove(this.activeHPBar[i]);
}
}
}
};
this.rightHand.OnShoot = () =>
{
this.currGunEnergy -= 1;
};
this.energyCellForCharge.OnCharge = () => {
this.currGunEnergy = this.currGunMaxEnergy;//reset energyCell as full state
this.gunEnergyCellGo.SetActive(true);
StartCoroutine(this.CoResetEnergyCellItem());
};
//----------------------------------SJY Map Main-----------------------------------------------------------
Vector3 camPos = Vector3.zero;
this.mapController.onInformInitPos = (pos) =>
{
camPos = pos;
};
this.mapController.onInformRoute = (rail) =>
{
this.camMove.UpdateRoute(rail.GetRoute());
};
this.mapController.Init();
this.camMove.Init(camPos);
//----------------------------------SJY Enemy1Move Main-----------------------------------------------------------
// EnemyPool.instance.LoadAll();
for (int i = 0; i < arrTargetPos.Length; i++)
{
isTargeted.Add(false);
}
this.StartCoroutine(this.CoStartSpawnEnemy1());
}
private IEnumerator CoResetEnergyCellItem()
{
this.energyCellForCharge.gameObject.SetActive(false);
yield return new WaitForSeconds(2f);
// Debug.Log("Rest Energy Item");
this.energyCellForCharge.transform.SetParent(this.energyCellForCharge.energyCellOriginalPoint);
this.energyCellForCharge.transform.localPosition = Vector3.zero;
this.energyCellForCharge.transform.localRotation = Quaternion.identity;
this.energyCellForCharge.gameObject.SetActive(true);
}
private void enemyHpBarPool()
{
for (int i = 0; i < this.EnemyCount; i++)
{
GameObject go = Instantiate(this.uiHPBarPrefab, this.worldCanvas.transform);
go.SetActive(false);
this.enemyHpBarPools.Add(go);
}
}
private GameObject GetEnemyHpBarInPool()
{
foreach(GameObject hpBar in enemyHpBarPools)
{
if(hpBar.activeSelf == false)
{
return hpBar;
}
}
return null;
}
private GameObject CreateHpBar(Vector3 position)
{
GameObject go = this.GetEnemyHpBarInPool();
go.transform.position = position;
go.SetActive(true);
return go;
}
private IEnumerator CoShowDamageText(Vector3 UIPos)
{
this.damageTextUIGo.transform.position = UIPos;
this.damageTextUIGo.SetActive(true);
var text = this.damageTextUIGo.GetComponent<TextMeshProUGUI>();
text.text = string.Format("{0}",this.currGunDamage);
yield return new WaitForSeconds(0.3f);
this.damageTextUIGo.SetActive(false);
}
// Update is called once per frame
void Update()
{
if (activeHPBar.Count != 0)
{
for (int i = 0; i < this.listEnemies.Count; i++)
{
Debug.LogFormat("{0}, {1}", this.activeHPBar[i], this.listEnemies[i]);
this.activeHPBar[i].transform.position = this.listEnemies[i].hpBarPoint.position;
}
}
this.energyTextUIGo.GetComponent<TextMeshProUGUI>().text = string.Format("{0}", this.currGunEnergy);
this.rightHand.isAttack = true;
if(this.currGunEnergy <= 0)
{
this.gunEnergyCellGo.SetActive(false);
this.rightHand.isAttack = false;
}
if (isFirstHP)
{
this.guideText.gameObject.SetActive(true);
this.guideText.text = "물약을 잡아 HP를 회복하세요.";
}
}
//Methods
//----------------------------------SJY Enemy1Move Main-----------------------------------------------------------
private IEnumerator CoStartSpawnEnemy1()
{
this.remainEnemyCount = maxWaveEnemyCount[(int)this.wave];
for (int i = 0; i < this.EnemyCount; i++)
{
yield return new WaitForSeconds(5f);
this.SpawnEnemy1();
}
}
private void SpawnEnemy1()
{
float x = UnityEngine.Random.Range(-3f, 3f);
float z = UnityEngine.Random.Range(10f, 15f);
while (true)
{
int layer = 1 << 3 | 1 << 6 | 1 << 7;
//Debug.Log(layer.ToBinaryString());
//Debug.Log(enemy.gameObject.layer.ToString());
Collider[] hit = new Collider[10];
int num = Physics.OverlapSphereNonAlloc(this.arrTargetPos[2].position + Vector3.right * x
+ Vector3.forward * z, 2f, hit, layer);
if (num == 0)
break;
x = UnityEngine.Random.Range(-3f, 3f);
z = UnityEngine.Random.Range(10f, 20f);
}
Vector3 pos = this.arrTargetPos[2].position + Vector3.right * x + Vector3.forward * z;
int idx = 0;
int number = UnityEngine.Random.Range(0, 10);
switch (this.wave)
{
case eWave.WAVE1:
idx = (int)EnemyMove.eEnemyType.Enemy1;
break;
case eWave.WAVE2:
if (number < 3)
{
idx= (int)EnemyMove.eEnemyType.Enemy1;
}
else
idx=(int)EnemyMove.eEnemyType.Enemy2;
break;
case eWave.WAVE3:
if (number < 2)
{
idx = (int)EnemyMove.eEnemyType.Enemy1;
}
else if (number < 4)
{
idx = (int)EnemyMove.eEnemyType.Enemy2;
}
else
{
idx = (int)EnemyMove.eEnemyType.Enemy3;
}
break;
}
GameObject enemyGo = EnemyPoolManager.instance.EnableEnemy(idx);
Enemy1Move enemy = enemyGo.GetComponent<Enemy1Move>();
enemy.Init(pos);
listEnemies.Add(enemy);
enemy.onChangeTarget = (idx) =>
{
Debug.Log("target change!");
Debug.LogFormat("<color=yellow>{0} preTargetPos: {1}</color>", enemy.name, arrTargetPos[idx]);
this.SetTargetPos(enemy);
this.isTargeted[idx] = false;
};
enemy.onDieEnemy = (enemy) =>
{
this.remainEnemyCount--;
listEnemies.Remove(enemy);
this.isTargeted[enemy.target.Key] = false;
EnemyPoolManager.instance.DisableEnemy(enemy.gameObject);
if (this.remainEnemyCount >= this.EnemyCount)
{
Invoke("SpawnEnemy1", 2f);
}
else
{
if (this.remainEnemyCount == 0)
{
Debug.LogFormat("{0} completed", this.wave.ToString());
if (this.wave == eWave.WAVE3) return;
this.wave++;
this.StartCoroutine(CoStartSpawnEnemy1());
}
}
};
this.SetTargetPos(enemy);
this.OnGenerateEnemy(enemy);
}
private void SetTargetPos(Enemy1Move enemy)
{
List<int> listIndex = new List<int>();
for (int i = 0; i < this.isTargeted.Count; i++)
{
if (!isTargeted[i])
{
listIndex.Add(i);
}
}
int rand = UnityEngine.Random.Range(0, listIndex.Count);
int idx = listIndex[rand];
enemy.UpdateTargetPos(idx, this.arrTargetPos[idx]);
this.isTargeted[idx] = true;
Debug.LogFormat("<color=magenta>{0} curTargetPos: {1}</color>", enemy.name, arrTargetPos[idx]);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class Enemy1Move : EnemyMove
{
public Action<EnemyData> OnGetData;
public Action<int> OnGetHit;
public Transform hpBarPoint;
public int currHP = 0;
private int maxHP = 0;
public Action<Enemy1Move> onDieEnemy;
private void Awake()
{
this.OnGetData = (data) =>
{
//this.currHP = data.enemyHp; ;//set HP;
this.maxHP = data.enemyHp; ;//set HP;
this.currHP = this.maxHP;
};
}
private void Start()
{
this.rBody = GetComponent<Rigidbody>();
this.OnGetHit = (damage) =>
{
this.currHP -= damage;
};
}
private void FixedUpdate()
{
this.Detect();
this.DecideDir();
this.Move();
if(this.currHP <= 0)
{
Debug.Log("<color=red>Enemy1 Die!!!!!!!!!</color>");
// this.gameObject.SetActive(false);
this.onDieEnemy(this);
}
}
public override void Init(Vector3 pos)
{
base.Init(pos);
this.currHP = this.maxHP;
}
public override void Detect()
{
base.Detect();
}
public override void DecideDir()
{
base.DecideDir();
}
public override void Move()
{
base.Move();
}
public override void RecurDrawAndHitRay(Vector3 pos1, Vector3 pos2, int depth)
{
base.RecurDrawAndHitRay(pos1, pos2, depth);
}
public override void DrawAndHitRay(Ray ray)
{
base.DrawAndHitRay(ray);
}
public override void UpdateTargetPos(int idx, Transform targetTrans)
{
base.UpdateTargetPos(idx, targetTrans);
}
public override IEnumerator CoChangeTarget()
{
return base.CoChangeTarget();
}
public override void OnDrawGizmos()
{
base.OnDrawGizmos();
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RightHandController : MonoBehaviour
{
public System.Action<Vector3, GameObject> OnHitEnemy;
public System.Action OnShoot;
[SerializeField] Transform shootTrans;
[SerializeField] Transform shootDistance;
[SerializeField] GameObject gunLaserGo;
[SerializeField] GameObject impactEffectGo;
private GameObject gunLaserBeamGo;
private GameObject laserImpactGo;
public bool isAttack = false;
// Start is called before the first frame update
void Start()
{
//this.gunLaserBeamGo = Instantiate<GameObject>(this.gunLaserGo);
this.gunLaserBeamGo = this.gunLaserGo;
this.laserImpactGo = Instantiate<GameObject>(this.impactEffectGo);
this.gunLaserBeamGo.SetActive(false);
this.laserImpactGo.SetActive(false);
}
// Update is called once per frame
void Update()
{
if (isAttack)
{
this.gunLaserBeamGo.transform.position = this.shootTrans.position;
if (OVRInput.GetDown(OVRInput.Button.SecondaryIndexTrigger))
{
Debug.Log("right Hand Index Trigger");
StartCoroutine(this.CoLaserBeam());
StartCoroutine(this.CoCheckImpact());
this.OnShoot();
}
}
}
private IEnumerator CoLaserBeam()
{
//this.gunLaserBeamGo.transform.position = this.shootTrans.position;
this.gunLaserBeamGo.SetActive(true);
this.gunLaserBeamGo.transform.LookAt(this.shootDistance.position);//hit nothing
yield return new WaitForSeconds(0.2f);
this.gunLaserBeamGo.SetActive(false);
this.laserImpactGo.SetActive(false);
}
private IEnumerator CoCheckImpact()
{
//-----------------------------check impact---------------------------------------
Ray ray = new Ray(this.shootTrans.position, this.gunLaserBeamGo.transform.forward);
Debug.DrawRay(ray.origin, ray.direction * 20f, Color.red, 0.3f);
var layerMask = 3 << LayerMask.NameToLayer("Monster");
RaycastHit hit;
if (Physics.Raycast(ray.origin, ray.direction, out hit, 20.0f))
{
// Debug.Log("Hit Monster!!");
if (!hit.collider.gameObject.CompareTag("Vehicle"))
{ this.CreateImpactEffect(hit.point); }
if (hit.collider.gameObject.CompareTag("Enemy1")|| hit.collider.gameObject.CompareTag("Enemy2")|| hit.collider.gameObject.CompareTag("Enemy3"))
{
Debug.Log("Enemy");
this.OnHitEnemy(hit.point, hit.collider.gameObject);
}
var particleSys = this.gunLaserBeamGo.GetComponent<ParticleSystemRenderer>();
particleSys.lengthScale = hit.distance;
}
else
{
var particleSys = this.gunLaserBeamGo.GetComponent<ParticleSystemRenderer>();
particleSys.lengthScale = 12f;
}
//-----------------------------------------------------------------------------------
yield return null;
}
private void CreateImpactEffect(Vector3 pos)
{
this.laserImpactGo.transform.position = pos;
this.laserImpactGo.SetActive(true);
}
}