[VR] GroundZero 개발

[4Idle - Gazzlers] Enemy의 Player 공격 GameScene에 적용

meltingmelvin 2023. 12. 28. 12:47

https://made-myblog.tistory.com/75

 

Gazzlers 개발일지 - Enemy 공격

기존에 R&D했던 Enemy 공격 부분을 구현하는 작업을 진행해보았다. (팀장님의 GameScene을 받아 제작해보았슴댯,,,,ㅎ) (1) Enemy 추가된 속성은 다음과 같다. muzzleTrans : 총알이 발사될 지점 muzzleGo : player

made-myblog.tistory.com

-팀원분이 만들어주신 Enemy 공격 테스트씬을 참고하여 GameScene에 적용하기 위한 포스팅이다.

 

EnemyMove

 

-EnemyMove.cs를 수정하였다.

 

muzzleTrans : 총알이 발사될 지점

muzzleGo : player를 향해 겨눌 총구의 object

playerTrans : 적이 공격할 player의 transform

attackCount : 공격 횟수(한 번 공격을 시작할 때 몇 번 쏠 것인지)

dealLossTime : attackCount만큼 공격할 때 간격(주기)

onAttackPlayer : enemy가 player 공격에 성공했을 때 main에게 알리는 대리자

onCompleteAttack : enemy가 attackCount만큼 공격을 다 하고 난 뒤 main에게 알리는 대리자

isAttack : 현재 enemy가 공격하는 중인지 아닌지를 알리는 상태

 

Enemy1Move.cs 수정

 

-Enemy 1, 2, 3에게 muzzleTrans, muzzleGo, AttackCount, DeadLossTime을 다음과 같이 할당한다.

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using System;


    public class EnemyMove : MonoBehaviour
    {

        public enum eEnemyType
        {
            Enemy1, Enemy2, Enemy3
        }

        public eEnemyType enemyType;

        public KeyValuePair<int, Transform> target;
        protected bool isReady;
        public float moveSpeed = 5.5f;
        public float rotSpeed = 8f;
        public float changeTargetTime = 5f;

        public float trackingTargetTime = 2f;
        private float elapsedTime = 3f;

        public float offset = 0.5f;
        public float length = 3.5f;
        public int depth = 3;
        public Action<int> onChangeTarget;
        protected Rigidbody rBody;
        private List<Tuple<Ray, bool>> listRays = new List<Tuple<Ray, bool>>();
        private Vector3 dir;
        private bool isDetected;
        //player attack
        //=============================================================================================================================
        [SerializeField] protected Transform[] muzzleTrans;
        [SerializeField] protected GameObject muzzleGo;
        protected Transform playerTrans;
        public int attackCount = 3;
        public float dealLossTime = 0.2f;
        public Action onAttackPlayer;
        public Action onCompleteAttack;
        protected bool isAttack;
        //=============================================================================================================================

    private void FixedUpdate()
        {
            if (!this.isReady) return;
            this.AimPlayer();
            this.Detect();
            this.DecideDir();
            this.Move();
        }

        private void Start()
        {
            this.rBody = this.GetComponent<Rigidbody>();
        }

        virtual public void Init(Vector3 pos)
        {
            //..Enemy 위치 지정 후
            this.transform.position = pos;
            //..활성화(보여주기)
            this.gameObject.SetActive(true);
        }

        virtual public void Detect()
        {
            this.listRays.Clear();
            this.isDetected = false;
            Vector3[] pos = new Vector3[] { this.transform.right, -this.transform.right, this.transform.forward };
            for (int i = 0; i < pos.Length; i++)
            {
                Ray ray = new Ray(this.transform.position + Vector3.up * this.offset, pos[i]);
                DrawAndHitRay(ray);
            }
            for (int i = 0; i < 2; i++)
            {
                this.RecurDrawAndHitRay(pos[i], pos[2], 0);
            }
        }

        virtual public void Move()
        {
            float curSpeed = this.moveSpeed;
            float posZ = this.transform.position.z;
            float targetPosZ = this.target.Value.position.z;
            if (posZ > targetPosZ + 15)
            {
                curSpeed = this.moveSpeed * 1.5f;
            }
            else if (posZ > targetPosZ + 7)
            {
                curSpeed = this.moveSpeed;
            }
            else if (posZ > targetPosZ + 3)
            {
                curSpeed = this.moveSpeed * 0.9f;
            }
        if (this.isDetected) curSpeed *= 0.8f;
        //float velocityY = this.rBody.velocity.y;
        //this.rBody.velocity = this.transform.forward * curSpeed;
        //this.rBody.velocity += Vector3.up * velocityY;
        this.rBody.MovePosition(this.rBody.position + this.transform.forward * curSpeed * Time.fixedDeltaTime);
        //Debug.LogFormat("<color=green>curspeed: {0}</color>", curSpeed);
    }


    virtual public void DecideDir()
        {
            List<List<Ray>> listNotHitRays = new List<List<Ray>>();
            List<Tuple<Ray, bool>> newListRays = listRays.OrderBy(x => Vector3.Distance(x.Item1.direction, this.transform.right)).ToList();
            for (int i = 0; i < newListRays.Count; i++)
            {
                Tuple<Ray, bool> tupleRay = newListRays[i];

                if (!tupleRay.Item2)
                {
                    if (listNotHitRays.Count == 0)
                    {
                        listNotHitRays.Add(new List<Ray>());
                    }
                    listNotHitRays[listNotHitRays.Count - 1].Add(tupleRay.Item1);
                    if (i < newListRays.Count - 1 && newListRays[i + 1].Item2)
                    {
                        listNotHitRays.Add(new List<Ray>());
                    }
                }
            }
            if (this.isDetected)
            {
                this.elapsedTime = 0f;

                int maxCount = 0;
                int maxCountIndex = 0;
                for (int i = 0; i < listNotHitRays.Count; i++)
                {
                    if (listNotHitRays[i].Count > maxCount)
                    {
                        maxCount = listNotHitRays[i].Count;
                        maxCountIndex = i;
                    }
                }

                this.dir = Vector3.zero;
                for (int i = 0; i < listNotHitRays[maxCountIndex].Count; i++)
                {
                    this.dir += listNotHitRays[maxCountIndex][i].direction;
                }
                this.dir /= maxCount;
                this.transform.rotation = Quaternion.Lerp(this.transform.localRotation, Quaternion.LookRotation(this.dir), this.rotSpeed * Time.deltaTime);
            }
            else
            {
                this.elapsedTime += Time.deltaTime;
                if (this.elapsedTime > this.trackingTargetTime)
                {
                    this.dir = this.target.Value.position - this.transform.position;
                    //Debug.LogFormat("<color=red>{0}</color>", Quaternion.LookRotation(this.dir));
                    this.transform.rotation = Quaternion.Lerp(this.transform.rotation, Quaternion.LookRotation(this.dir), this.rotSpeed * Time.deltaTime * 0.6f);
                }
                else
                    this.transform.rotation = Quaternion.Lerp(this.transform.localRotation, Quaternion.LookRotation(this.dir), this.rotSpeed * Time.deltaTime);
            }
        }

        virtual public void RecurDrawAndHitRay(Vector3 pos1, Vector3 pos2, int depth)
        {
            Ray ray = new Ray(this.transform.position + Vector3.up * this.offset, (pos1 + pos2).normalized);
            this.DrawAndHitRay(ray);
            if (depth < this.depth)
            {
                this.RecurDrawAndHitRay(pos1, (pos1 + pos2).normalized, depth + 1);
                this.RecurDrawAndHitRay(pos2, (pos1 + pos2).normalized, depth + 1);
            }
        }

        virtual public void DrawAndHitRay(Ray ray)
        {
            int layerMask = 1 << 3 | 1 << 6 | 1 << 7;
            RaycastHit hit;
            if (Physics.Raycast(ray, out hit, this.length, layerMask))
            {
                this.isDetected = true;
                Debug.DrawRay(ray.origin, ray.direction.normalized * this.length, Color.red);
                this.listRays.Add(new Tuple<Ray, bool>(ray, true));
            //    Debug.LogFormat("<color=blue>hit</color>: {0}", hit.collider.gameObject);
            }
            else
            {
                Debug.DrawRay(ray.origin, ray.direction.normalized * this.length, Color.green);
                this.listRays.Add(new Tuple<Ray, bool>(ray, false));
            }
        }

        virtual public void UpdateTargetPos(int idx, Transform targetTrans)
        {
            this.target = new KeyValuePair<int, Transform>(idx, targetTrans);
            if (!isReady)
            {
                isReady = true;
                this.StartCoroutine(this.CoChangeTarget());
            }
        }

        virtual public IEnumerator CoChangeTarget()
        {
            while (true)
            {
                yield return new WaitForSeconds(this.changeTargetTime);
                this.onChangeTarget(this.target.Key);
            }
        }
    //추가 구현(공격)===========================================================================================================================


    //조준
    protected void AimPlayer()
    {
        this.muzzleGo?.transform.LookAt(this.playerTrans);
    }

    //player 공격 method
    public void AttackPlayer()
    {
        StartCoroutine(this.CoAttackPlayer());
    }

    //dealLossTime에 맞춰 player를 공격하는 method
    protected IEnumerator CoAttackPlayer()
    {
        for (int i = 0; i < this.attackCount; i++)
        {
            for (int j = 0; j < this.muzzleTrans.Length; j++)
            {
                GameObject bulletGo = BulletGenerator.Instance.GenerateBullet(this.muzzleTrans[j]);
                Bullet bullet = bulletGo.GetComponent<Bullet>();
                Debug.Log(bullet);
                bullet.Init(() =>
                {
                    this.onAttackPlayer();
                });
            }
            yield return new WaitForSeconds(this.dealLossTime);
        }
        this.onCompleteAttack();        //공격이 완료되면 대리자를 사용하여 TestEnemy1Main.cs에게 공격 완료를 알림.
    }

    //=======================================================================================================================================
    virtual public void OnDrawGizmos()
        {
            Gizmos.color = Color.red;
            Gizmos.DrawWireSphere(this.transform.position, 2f);
        }


    }
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.onDieEnemy(this);

            if (isAttack)
            {
                this.onCompleteAttack();
            }
        }
        }

        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();
        }
    }

-----------------------------------------------------------------------------------------------------------------------------------------------------------------Bullet

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

public class Bullet : MonoBehaviour
{
    private Transform target;
    private Rigidbody rBody;
    private Vector3 targetPos;
    public float moveSpeed = 5f;
    public Action onAttackPlayer;

    // Start is called before the first frame update
    void Start()
    {
        this.target = GameObject.Find("CenterEyeAnchor").transform;
        this.targetPos = this.target.position;
        this.rBody = this.GetComponent<Rigidbody>();
    }

    public void Init(Action callback)
    {
        this.onAttackPlayer = callback;
    }

    // Update is called once per frame
    void FixedUpdate()
    {
        this.transform.LookAt(this.target);
        this.rBody.MovePosition(this.rBody.position + this.transform.forward * this.moveSpeed * Time.fixedDeltaTime);
        if (this.transform.position.z < this.target.position.z)
        {
            Destroy(this.gameObject);
        }
    }

    private void OnTriggerEnter(Collider collision)
    {
        Debug.LogFormat("gameObject: {0}, tag: {1}", collision.gameObject.name, collision.tag);
        if (collision.CompareTag("Player"))
        {
            Debug.Log("attack player");
            this.onAttackPlayer();
        }
        Destroy(this.gameObject);
    }

}

-Bullet 프리팹 생성 후 Bullet.cs 부착해준다.

-빈오브젝트를 생성해 BulletGenerator를 붙여준 후 Bullet Prefab에 생성한 Bullet 프리팹을 할당해준다.

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

Main 수정

main 수정
DataManager 수정

 

 

-Player의 CeneterEyeAnchor의 자식으로 다음과 같은 오브젝트를 넣어준다.

-Player와 충돌했는지 확인하게하는 역할을 한다.

----------------------------------------------------------------------------------------------------------------------------------------------------------------- -----------------------------------------------------------------------------------------------------------------------------------------------------------------

 

Player HP 연동

-main에서 저장하고있는 현재 PlayerHp를 공격당함에 따라 감소시켜줘야한다.

-이 HP는 플레이어의 정면에있는 UI에 나타난다.

main 수정

-메인에 플레이어의 데이터를 초기화하기 위해 start 시 데이터를 가져오도록했다.

- 플레이어가 공격당했을 때 현재 player의 HP를 감소시킨다.

- HP 슬라이더의 max 값을 처음에 데이터 가져올때 함께 셋팅시킨다.

UI와 데이터 연동

-플레이어의 현재 HP 값을 UI에 보여지도록 update에서 변경되도록 하였다.

 

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] GameObject uiPlayerHpText;
        [SerializeField] GameObject uiPlayerHpSlider;
        [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 int currPlayerHp;
        private int currScore;
        private int currShiledGauge;
        private int currGunId;

        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;
    //----------------------------------SJY EnemyAttack-----------------------------------------------------------
    private float enemyAttackCoolTime = 4f;
    private float enemyAttackelapsedTime;
    private bool isEnemyAttack;
    private int enemyAttackIdx = 0;



    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);
        for(int i = 0; i < playerData.Count; i++)
        {//get player data
            if (playerData[i].playerUserName == "Unknown")
            {
                Debug.Log("default user");
                this.currPlayerHp = playerData[i].playerHp;
                this.currScore = playerData[i].score;
                this.currShiledGauge = playerData[i].shiledGauge;
                this.currGunId = playerData[i].currGunId;
            }
        }

        this.uiPlayerHpSlider.GetComponent<Slider>().maxValue = this.currPlayerHp;
       //   var playerGunId = playerData[0].currGunId;

       Debug.LogFormat("Gun Data Count: {0}", gunData.Count);
        for (int i = 0; i < gunData.Count; i++)
            {
                if (this.currGunId == 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()
        {
        //enemy 공격 구현=======================================================================================
        if (this.listEnemies.Count > 0 && !isEnemyAttack)
        {
            this.enemyAttackelapsedTime += Time.deltaTime;
            if (this.enemyAttackelapsedTime > this.enemyAttackCoolTime)
            {
                this.listEnemies[(enemyAttackIdx++ % this.listEnemies.Count)].AttackPlayer();
                this.isEnemyAttack = true;
            }
        }
        else
        {
            this.enemyAttackelapsedTime = 0f;
            this.isEnemyAttack = false;
        }
        //=======================================================================================

        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;

            }
        }
        //change energyCell UI's text
        this.energyTextUIGo.GetComponent<TextMeshProUGUI>().text = string.Format("{0}", this.currGunEnergy);

        //change player HP UI
        this.uiPlayerHpText.GetComponent<TextMeshProUGUI>().text = string.Format("{0}", this.currPlayerHp);
        this.uiPlayerHpSlider.GetComponent<Slider>().value = this.currPlayerHp;

        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());
                }
            }
        };
        //enemy Attack 추가부분================================================================================================
        enemy.onAttackPlayer = () =>
        {
            int damage = DataManager.Instance.GetEnemyData(enemy.tag).enemyDamage;
            Debug.LogFormat("player get {0} damage / current Player's HP: {1}", damage, this.currPlayerHp);
            this.currPlayerHp -= damage;
            
        };

        enemy.onCompleteAttack = () =>
        {
            Debug.Log("enemy attack complete");
            this.isEnemyAttack = false;
            this.enemyAttackelapsedTime = 0f;
        };
        //====================================================================================================================


        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]);
    }
}

Enemy가 공격시 HP 감소