-현재 플레이어는 아무 제한없이 쏘고 싶은대로 총을 쏠 수 있다.
-탄창 부착 기능을 추가하였으니, 레이저 빔을 한번에 쏠 수 있는 개수를 제한하여 다 소진한 경우에는 탄창을 부착해야만 총을 쏠 수 있도록 해야한다.
-먼저 오른손에 있는 총에 UI를 달아 현재 남은 총 발사 갯수를 표시할것이다.
- WorldCanvas의 자식으로 TextMeshPro를 생성하여 GunEnergyText라 하자.
-이 UI는 총에 달려있으므로 총에 UI가 들어갈 위치를 빈 오브젝트로 생성하여 EnergyTextPos라 하였다.
-GameMain에 EnergyTextPos를 할당해주고, UI의 위치에 넣어주도록 코드를 작성하였다.
-gunData에서 energyCell의 최댓값을 받아와 start함수에서 초기화할 수 있도록 변수에 저장하였다.
-저장한 변수값을 UI의 text값에 표시되도록 하였다.
-이제 총을 쏠 때마다 텍스트값이 감소되도록 해야한다.
=> 총을 쏠때마다 값을 감소시키고, 이를 update되도록 하면된다.
-start에서 작성했던 텍스트 변경하는 코드를 upate문 내로 이동시켜 감소될때 텍스트가 변경되도록하였다.
- 이제 energyCell이 start될때는 총에 부착되어있고, energyCell이 다 소진되면 탄창을 총에서 사라지도록 할 것이다.
-총의 자식으로 새로운 energyCell을 붙여주었다. 이 cell은 energy가 남아있으면 총에 붙어있고, 소진되면 사라진다.
-즉, 박스 위에 올려져있는 energyCell 로 탄창을 충전하여 energy가 다시 충전되면 이 새로운 energyCell이 활성화된다.
-충전이 될 때 OnCharge 대리자를 통해 이벤트가 발생함을 GameMain 스크립트에서 알 수 있도록했다.
- OnCharge는 총에 붙어있는 energyCell을 다시 활성화 시키고, 총의 energy를 충전시켜 초기값으로 reset한다.
- 이 코루틴 함수를 통해 박스위에 올려져있는 energyCell 아이템이 충전 후 일정시간이 지나면 다시 제자리에 스폰된다.
-현재에는 energy가 0보다 작아지더라도 총을 계속 쏠수 있으므로 이를 불가하게 해야한다. 따라서 코드 수정이 필요하다.
- main에서 energy가 0보다 작아지면 rightHand의 isAttack을 false로 만들어준다.
- 따라서 더 이상 현재 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);
}
}
'[VR] GroundZero 개발' 카테고리의 다른 글
[4Idle - Gazzlers] 인게임 UI 정리 - 기존 UI 정리 및 타 UI 오브젝트 생성 (0) | 2023.12.14 |
---|---|
[4Idle - Gazzlers] 인게임 UI position 수정 - setparent 사용 (0) | 2023.12.13 |
[4Idle - Gazzlers] 손에 탄창 충전 기능 - GameScene으로 확장 (0) | 2023.12.06 |
[4Idle - Gazzlers] 손에 탄창 충전 기능 추가 (1) | 2023.12.05 |
[4Idle - Gazzlers] Player 이동 기능 + 손 기능 합치기 (0) | 2023.12.01 |