- 플레이어 무기 교체
@ 에러 : 무기 교체를 빠르게 하면서(1,2,3 빠르게 왔다갔다 교체) 총을 발사하면 총알이 안나가는 상태가 발생.
@ 해결 :
무기 교체 중 Shoot 코루틴의 상태 유지: 무기 교체 중에도 코루틴이 진행 중이라면 무기가 바뀌어도 발사 시도가 계속됩니다. 현재 코드에서 Shoot()이 한 번 실행되면 무기 교체 후에도 계속 진행될 수 있습니다. 이를 방지하려면, 무기를 교체할 때 canShoot 상태를 초기화해야 합니다.
// 무기 교체 시 사격 가능 상태 초기화
GetComponentInChildren<RayCast>().canShoot = true;
다른 해결 방법 :
- RayCast(총 쏘는 스크립트)에 스크립트가 활성화 될때 기본 상태가 true로 변경되도록 한다.
- 원인은 총을 쏘고 재장전(코루틴)중에 스크립트가 비활성화 되면서 canShoot = false; 된 상태로 계속 유지되고 다시 스크립트가 활성화(Enable) 됐을 때에도 false로 유지되고 있기 때문.
private void OnEnable()
{
canShoot = true;
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WeaponSwitch : MonoBehaviour
{
[SerializeField] int currentWeapon = 0;
void Start()
{
SetActiveWeapon();
}
void Update()
{
// 이전 무기와 현재 무기가 같은 값을 가진다는 뜻.
int previousWeapon = currentWeapon;
// 키 입력을 받아 currentWeapon을 바꿈
ProcessKeyInput();
if ( previousWeapon != currentWeapon )
{
//무기 교체
SetActiveWeapon();
}
}
private void SetActiveWeapon()
{
int weaponIndex = 0;
foreach (Transform weapon in transform)
{
if (weaponIndex == currentWeapon)
{
weapon.gameObject.SetActive(true);
}
else
{
weapon.gameObject.SetActive(false);
}
weaponIndex++;
}
// 무기 교체 시 사격 가능 상태 초기화
GetComponentInChildren<RayCast>().canShoot = true;
}
private void ProcessKeyInput()
{
if (Input.GetKey(KeyCode.Alpha1))
{
currentWeapon = 0;
}
if (Input.GetKey(KeyCode.Alpha2))
{
currentWeapon = 1;
}
if (Input.GetKey(KeyCode.Alpha3))
{
currentWeapon = 2;
}
}
}
- 총 발사 코드
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RayCast : MonoBehaviour
{
[SerializeField] Camera mainCam;
[SerializeField] float range = 100f;
[SerializeField] float gunDamage = 30f;
[SerializeField] ParticleSystem gunFlash;
[SerializeField] GameObject gunTargetHit;
[SerializeField] Ammo ammo; // 플레이어가 가지고있는 총알 확인
[SerializeField] float weaponDelayTime;
public bool canShoot = true;
void Update()
{
if(Input.GetMouseButtonDown(0) && canShoot == true)
{
if (ammo.GetCurrentAmmo() > 0)
{
StartCoroutine(Shoot());
}
}
}
void GunTargetHit(RaycastHit raycastHit)
{
// 총 맞은 부위에 이펙트 생성
//GameObject hitEffect = Instantiate(gunTargetHit, raycastHit.transform);
GameObject hitEffect = Instantiate(gunTargetHit, raycastHit.point, Quaternion.LookRotation(raycastHit.normal));
// 1초뒤 파티클 삭제
Destroy(hitEffect, 1f);
}
void GunFlash()
{
gunFlash.Play();
}
IEnumerator Shoot()
{
canShoot = false;
GunFlash();
ProcessRayCast();
ammo.ReduceCurrentAmmo();
yield return new WaitForSeconds(weaponDelayTime);
canShoot = true;
}
private void ProcessRayCast()
{
RaycastHit hit;
if (Physics.Raycast(mainCam.transform.position, mainCam.transform.forward, out hit, range))
{
print(" hit : " + hit.transform.name);
// 총 맞은 곳에 파티클 생성
GunTargetHit(hit);
//Raycast로 충돌한 오브젝트에서 EnemyHealth라는 컴포넌트를 찾아서, 그 컴포넌트를 가져옴.
EnemyHealth target = hit.transform.GetComponent<EnemyHealth>();
if (target == null)
{
return;
}
target.TakeDamage(gunDamage);
print(target.Hp);
}
}
}
- 마우스 휠로 무기 교체하기
- 캐릭터가 죽어서 게임오버 상태에서도 무기 변경이 가능하니 Player_Death 스크립트를 수정해준다.
- 캐릭터가 죽으면 WeaponSwitch 스크립트를 찾아서 비활성화 시킨다.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WeaponSwitch : MonoBehaviour
{
[SerializeField] int currentWeapon = 0;
void Start()
{
SetActiveWeapon();
}
void Update()
{
// 이전 무기와 현재 무기가 같은 값을 가진다는 뜻.
int previousWeapon = currentWeapon;
// 키 입력을 받아 currentWeapon을 바꿈
ProcessKeyInput();
// 마우스휠 입력을 받아 currentWeapon을 바꿈
ProcessMouseWheel();
if ( previousWeapon != currentWeapon )
{
//무기 교체
SetActiveWeapon();
}
}
private void ProcessMouseWheel()
{
if (Input.GetAxis("Mouse ScrollWheel") > 0)
{
if (currentWeapon >= transform.childCount - 1)
{
currentWeapon = 0;
}
else
{
currentWeapon++;
}
}
if (Input.GetAxis("Mouse ScrollWheel") < 0)
{
if (currentWeapon <= 0)
{
currentWeapon = transform.childCount - 1;
}
else
{
currentWeapon--;
}
}
}
private void SetActiveWeapon()
{
int weaponIndex = 0;
foreach (Transform weapon in transform)
{
if (weaponIndex == currentWeapon)
{
weapon.gameObject.SetActive(true);
}
else
{
weapon.gameObject.SetActive(false);
}
weaponIndex++;
}
// 무기 교체 시 사격 가능 상태 초기화
GetComponentInChildren<RayCast>().canShoot = true;
}
private void ProcessKeyInput()
{
if (Input.GetKeyDown(KeyCode.Alpha1))
{
currentWeapon = 0;
}
if (Input.GetKeyDown(KeyCode.Alpha2))
{
currentWeapon = 1;
}
if (Input.GetKeyDown(KeyCode.Alpha3))
{
currentWeapon = 2;
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player_Death : MonoBehaviour
{
[SerializeField] Canvas death_UI_Canvas;
void Start()
{
death_UI_Canvas.enabled = false;
}
public void DeathState()
{
death_UI_Canvas.enabled = true;
Time.timeScale = 0;
FindObjectOfType<WeaponSwitch>().enabled = false;
Cursor.lockState = CursorLockMode.None;
Cursor.visible = true;
}
}
유니티 List, 오류 및 해결 (1) | 2024.09.16 |
---|---|
유니티 총 타입 별로 총알 구분하기 (0) | 2024.09.16 |
유니티 총 줌인, 줌아웃, 확대, 축소 만들기 (0) | 2024.09.12 |
유니티 죽었을때 UI 띄우기 (0) | 2024.09.12 |
유니티 레이캐스트로 총 맞은 곳에 이펙트(파티클) 생성하기 (0) | 2024.09.11 |