[4Idle - Gazzlers] 오른손 레이저 개수 제한/ 충전 시 reset 기능 구현 (탄창 충전 요구 기능)

-현재 플레이어는 아무 제한없이 쏘고 싶은대로 총을 쏠 수 있다.

-탄창 부착 기능을 추가하였으니, 레이저 빔을 한번에 쏠 수 있는 개수를 제한하여 다 소진한 경우에는 탄창을 부착해야만 총을 쏠 수 있도록 해야한다.

-먼저 오른손에 있는 총에 UI를 달아 현재 남은 총 발사 갯수를 표시할것이다.

 

- WorldCanvas의 자식으로 TextMeshPro를 생성하여 GunEnergyText라 하자.

-이 UI는 총에 달려있으므로 총에 UI가 들어갈 위치를 빈 오브젝트로 생성하여 EnergyTextPos라 하였다.

-GameMain에 EnergyTextPos를 할당해주고, UI의 위치에 넣어주도록 코드를 작성하였다.

 

-gunData에서 energyCell의 최댓값을 받아와 start함수에서 초기화할 수 있도록 변수에 저장하였다.

-저장한 변수값을 UI의 text값에 표시되도록 하였다.

 

-이제 총을 쏠 때마다 텍스트값이 감소되도록 해야한다.

=> 총을 쏠때마다 값을 감소시키고, 이를 update되도록 하면된다.

rightHandController에 대리자 선언 / main에서 감소 / update

-start에서 작성했던 텍스트 변경하는 코드를 upate문 내로 이동시켜 감소될때 텍스트가 변경되도록하였다.

총 쏠때마다 energyCell 감소 UI 표시

 

- 이제 energyCell이 start될때는 총에 부착되어있고, energyCell이 다 소진되면 탄창을 총에서 사라지도록 할 것이다.

-총의 자식으로 새로운 energyCell을 붙여주었다. 이 cell은 energy가 남아있으면 총에 붙어있고, 소진되면 사라진다.

-즉, 박스 위에 올려져있는 energyCell 로 탄창을 충전하여 energy가 다시 충전되면 이 새로운 energyCell이 활성화된다.

energyCellController에서 onCharge호출 / main에서 작동하는 OnCharge

 

-충전이 될 때 OnCharge 대리자를 통해 이벤트가 발생함을 GameMain 스크립트에서 알 수 있도록했다.

- OnCharge는 총에 붙어있는 energyCell을 다시 활성화 시키고, 총의 energy를 충전시켜 초기값으로 reset한다.

GameMain의 CoResetEnergyCellItem()

- 이 코루틴 함수를 통해 박스위에 올려져있는 energyCell 아이템이 충전 후 일정시간이 지나면 다시 제자리에 스폰된다.

 

energy가 0이 되어 충전하면 다시 reset되는 결과

 

-현재에는 energy가 0보다 작아지더라도 총을 계속 쏠수 있으므로 이를 불가하게 해야한다. 따라서 코드 수정이 필요하다.

- main에서 energy가 0보다 작아지면 rightHand의 isAttack을 false로 만들어준다.

rightHandController / Game Main 수정

- 따라서 더 이상 현재 energy는 0보다 작아지지않으며, 0이하일때 총이 쏴지지 않는 결과를 확인하였다.

-처음 충전하고 나서 charge영역에 넣었을때에만 isCharge되도록 하기위해 코드를 수정하여 charge영역이 아닐때에도 충전되는 버그를 해결하였다.

 

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class GameMain : MonoBehaviour
    {
        [SerializeField] EnemyGenerator enemyGen;
        [SerializeField] Canvas worldCanvas;
        [SerializeField] GameObject uiHPBarPrefab;
        [SerializeField] GameObject uiDamageTextPrefab;
        [SerializeField] GameObject uiEnergyCellPrefab;
        [SerializeField] GameObject gunEnergyCellGo;
        [SerializeField] EnergyCellController energyCellForCharge;
        [SerializeField] RightHandController rightHand;
        [SerializeField] Transform uiEnergyCellTransform;

        private GameObject hpBarUIGo;
        private GameObject damageTextUIGo;
        private GameObject energyTextUIGo;
        
        private EnemyGenerator enemyGenerator;

        private string currGunType;
        private int currGunDamage;
        private int currGunEnergy;
        private int currGunMaxEnergy;
        private List<EnemyController> enemyList = new List<EnemyController>();
        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;

    private void Awake()
        {
            this.enemyGenerator = enemyGen;
            //----------------------------------Generate Enemy-----------------------------------------------------------
            this.enemyList.Add(this.enemyGenerator.Generate(GameEnums.eEnemyType.FrankenStein, new Vector3(-0.09f, -1.35f, 4.3f)));
            this.enemyList.Add(this.enemyGenerator.Generate(GameEnums.eEnemyType.FrankenStein, new Vector3(2.41f, -1.35f, 4.3f)));
        }
        // Start is called before the first frame update
        void Start()
        {

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

            var playerGunId = playerData[0].currGunId;

            // Debug.Log(playerGunId);
            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;
                   //gunData[i].gunDamage;
                }
            }

            this.enemyHpBarPool();

            for(int i=0; i < this.enemyList.Count; i++)
            {
                this.activeHPBar.Add(this.CreateHpBar(this.enemyList[i].hpBarPoint.position));
              
              for(int j = 0; j < enemyData.Count; j++)
                {
                    if (this.enemyList[j].name == enemyData[j].enemyType)
                    {
                        //Debug.Log(enemyData[j].enemyType);
                        var slider = this.activeHPBar[i].GetComponent<Slider>();
                        slider.maxValue = enemyData[j].enemyHp;
                        Debug.Log(slider.maxValue);
                        slider.value = slider.maxValue;//reset slider value as full state
                    }
                }
            }

       

            this.damageTextUIGo = Instantiate(this.uiDamageTextPrefab, this.worldCanvas.transform);
            this.damageTextUIGo.SetActive(false);

            this.energyTextUIGo = Instantiate(this.uiEnergyCellPrefab, this.worldCanvas.transform);
           // this.energyTextUIGo.GetComponent<TextMeshProUGUI>().text = string.Format("{0}", this.currGunEnergy);
          
            this.rightHand.OnHitEnemy = (hitPos,hitObject) =>
            {
               // Debug.LogFormat("Hit Enemy! Point: {0}", hitPos);
                StartCoroutine(this.CoShowDamageText(hitPos));
                
                for (int i = 0; i < this.enemyList.Count; i++)
                {
                    if (hitObject == this.enemyList[i].gameObject)
                    {
                        Debug.LogFormat("Object: {0} , Damage : {1}",i,currGunDamage);
                        this.activeHPBar[i].GetComponent<Slider>().value -= currGunDamage;
                    }
            }
                
            };

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


    }
    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.enemyList.Count; 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 void UpdateEnemyHPBar(Vector3 worldPos)
        {
            //----------------if Canvas Render Mode is Overlay-------------------------------
            //var screenPos = RectTransformUtility.WorldToScreenPoint(Camera.main, worldPos);
            //Vector2 localPos;
            //RectTransformUtility.ScreenPointToLocalPointInRectangle(
            //    (RectTransform)this.canvas.transform, screenPos, this.uiCam, out localPos);
            //Debug.Log(localPos);
            //this.hpBarUIGo.GetComponent<RectTransform>().localPosition = localPos;
            //-------------------------------------------------------------------------------------
            //---------------if world Position (VR always need world Pos)--------------------------
            // this.hpBarUIGo.transform.position = worldPos;
           
            //-------------------------------------------------------------------------------------
        }
        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()
        {
            for (int i = 0; i < this.enemyList.Count; i++)
            {
                this.activeHPBar[i].transform.position = this.enemyList[i].hpBarPoint.position;
                

            }

        this.energyTextUIGo.transform.position = this.uiEnergyCellTransform.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;
        }
    }

   
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnergyCellController : MonoBehaviour
{
    public Transform energyCellPoint;
    public Transform energyCellOriginalPoint;
    public System.Action OnCharge;
    private bool isCharge;
    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {

    }
    public void OnGrab()
    {
        Debug.Log("Grab");

    }


    public void OnUnGrab()
    {
        Debug.Log("unGrab");
        if (this.isCharge)
        {
            this.OnCharge();
            this.transform.SetParent(this.energyCellPoint);
            this.transform.localPosition = Vector3.zero;
            this.transform.localRotation = Quaternion.Euler(0, 0, 90);
            this.isCharge = false;//reset charge state
        }
        else
        {
           
            this.transform.position = this.energyCellOriginalPoint.position;
            this.transform.localRotation = Quaternion.identity;

        }
    }


    private void OnTriggerEnter(Collider other)
    {
        if (other.gameObject.CompareTag("ChargeArea"))
        {
            // Debug.Log("Charge Area");
            this.isCharge = true;
            //this.OnCharge();
        }

    }

    private void OnTriggerExit(Collider other)
    {
        if (other.gameObject.CompareTag("ChargeArea"))
        {
            // Debug.Log("Exit Area");
            this.isCharge = false;

        }

    }
}
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.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 * 10f, Color.red, 0.3f);
            var layerMask = 3 << LayerMask.NameToLayer("Monster");
            RaycastHit hit;

            if (Physics.Raycast(ray.origin, ray.direction, out hit, 10.0f))
            {
                // Debug.Log("Hit Monster!!");
                if (!hit.collider.gameObject.CompareTag("Vehicle"))
                { this.CreateImpactEffect(hit.point); }

                if (hit.collider.gameObject.CompareTag("Enemy"))
                {
                    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 = 5f;
        }
            //-----------------------------------------------------------------------------------
            yield return null;
        }
        private void CreateImpactEffect(Vector3 pos)
        {
            this.laserImpactGo.transform.position = pos;
            this.laserImpactGo.SetActive(true);
        }

    }
myoskin