156 lines
4.3 KiB
C#
156 lines
4.3 KiB
C#
|
|
using JetBrains.Annotations;
|
|||
|
|
using System.Collections;
|
|||
|
|
using System.Diagnostics.Eventing.Reader;
|
|||
|
|
using UnityEngine;
|
|||
|
|
|
|||
|
|
// 총을 구현
|
|||
|
|
public class Gun : MonoBehaviour {
|
|||
|
|
// 총의 상태를 표현하는 데 사용할 타입을 선언
|
|||
|
|
public enum State {
|
|||
|
|
Ready, // 발사 준비됨
|
|||
|
|
Empty, // 탄알집이 빔
|
|||
|
|
Reloading // 재장전 중
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public State state { get; private set; } // 현재 총의 상태
|
|||
|
|
|
|||
|
|
public Transform fireTransform; // 탄알이 발사될 위치
|
|||
|
|
|
|||
|
|
public ParticleSystem muzzleFlashEffect; // 총구 화염 효과
|
|||
|
|
public ParticleSystem shellEjectEffect; // 탄피 배출 효과
|
|||
|
|
|
|||
|
|
private LineRenderer bulletLineRenderer; // 탄알 궤적을 그리기 위한 렌더러
|
|||
|
|
|
|||
|
|
private AudioSource gunAudioPlayer; // 총 소리 재생기
|
|||
|
|
|
|||
|
|
public GunData gunData; // 총의 현재 데이터
|
|||
|
|
|
|||
|
|
private float fireDistance = 50f; // 사정거리
|
|||
|
|
|
|||
|
|
public int ammoRemain = 100; // 남은 전체 탄알
|
|||
|
|
public int magAmmo; // 현재 탄알집에 남아 있는 탄알
|
|||
|
|
|
|||
|
|
private float lastFireTime; // 총을 마지막으로 발사한 시점
|
|||
|
|
|
|||
|
|
private void Awake() {
|
|||
|
|
gunAudioPlayer = GetComponent<AudioSource>();
|
|||
|
|
bulletLineRenderer = GetComponent<LineRenderer>();
|
|||
|
|
|
|||
|
|
bulletLineRenderer.positionCount = 2;
|
|||
|
|
|
|||
|
|
bulletLineRenderer.enabled = false;
|
|||
|
|
// 사용할 컴포넌트의 참조 가져오기
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void OnEnable() {
|
|||
|
|
ammoRemain = gunData.startAmmoRemain;
|
|||
|
|
|
|||
|
|
magAmmo = gunData.magCapacity;
|
|||
|
|
|
|||
|
|
state = State.Ready;
|
|||
|
|
|
|||
|
|
lastFireTime = 0;
|
|||
|
|
// 총 상태 초기화
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 발사 시도
|
|||
|
|
public void Fire() {
|
|||
|
|
if (state == State.Ready && Time.time >= lastFireTime + gunData.timeBetFire)
|
|||
|
|
{
|
|||
|
|
lastFireTime = Time.time;
|
|||
|
|
|
|||
|
|
Shot();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 실제 발사 처리
|
|||
|
|
private void Shot()
|
|||
|
|
{
|
|||
|
|
RaycastHit hit;
|
|||
|
|
|
|||
|
|
Vector3 hitPosition = Vector3.zero;
|
|||
|
|
|
|||
|
|
if (Physics.Raycast(fireTransform.position, fireTransform.forward, out hit, fireDistance))
|
|||
|
|
{
|
|||
|
|
IDamageable target = hit.collider.GetComponent<IDamageable>();
|
|||
|
|
|
|||
|
|
if (target != null)
|
|||
|
|
{
|
|||
|
|
target.OnDamage(gunData.damage, hit.point, hit.normal);
|
|||
|
|
}
|
|||
|
|
hitPosition = hit.point;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
hitPosition = fireTransform.position + fireTransform.forward * fireDistance;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
StartCoroutine(ShotEffect(hitPosition));
|
|||
|
|
|
|||
|
|
magAmmo--;
|
|||
|
|
if (magAmmo <= 0)
|
|||
|
|
{
|
|||
|
|
state = State.Empty;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
// 발사 이펙트와 소리를 재생하고 탄알 궤적을 그림
|
|||
|
|
private IEnumerator ShotEffect(Vector3 hitPosition) {
|
|||
|
|
|
|||
|
|
muzzleFlashEffect.Play();
|
|||
|
|
|
|||
|
|
shellEjectEffect.Play();
|
|||
|
|
|
|||
|
|
gunAudioPlayer.PlayOneShot(gunData.shotClip);
|
|||
|
|
|
|||
|
|
bulletLineRenderer.SetPosition(0, fireTransform.position);
|
|||
|
|
|
|||
|
|
bulletLineRenderer.SetPosition(1, hitPosition);
|
|||
|
|
// 라인 렌더러를 활성화하여 탄알 궤적을 그림
|
|||
|
|
bulletLineRenderer.enabled = true;
|
|||
|
|
|
|||
|
|
// 0.03초 동안 잠시 처리를 대기
|
|||
|
|
yield return new WaitForSeconds(0.03f);
|
|||
|
|
|
|||
|
|
// 라인 렌더러를 비활성화하여 탄알 궤적을 지움
|
|||
|
|
bulletLineRenderer.enabled = false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 재장전 시도
|
|||
|
|
public bool Reload() {
|
|||
|
|
if (state == State.Reloading || ammoRemain <= 0 || magAmmo >= gunData.magCapacity)
|
|||
|
|
{
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
StartCoroutine(ReloadRoutine());
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 실제 재장전 처리를 진행
|
|||
|
|
private IEnumerator ReloadRoutine() {
|
|||
|
|
// 현재 상태를 재장전 중 상태로 전환
|
|||
|
|
state = State.Reloading;
|
|||
|
|
|
|||
|
|
gunAudioPlayer.PlayOneShot(gunData.reloadClip);
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
// 재장전 소요 시간 만큼 처리 쉬기
|
|||
|
|
yield return new WaitForSeconds(gunData.reloadTime);
|
|||
|
|
|
|||
|
|
int ammoTofil = gunData.magCapacity - magAmmo;
|
|||
|
|
|
|||
|
|
if (ammoRemain < ammoTofil)
|
|||
|
|
{
|
|||
|
|
ammoTofil = ammoRemain;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
magAmmo += ammoTofil;
|
|||
|
|
|
|||
|
|
ammoRemain -= ammoTofil;
|
|||
|
|
// 총의 현재 상태를 발사 준비된 상태로 변경
|
|||
|
|
state = State.Ready;
|
|||
|
|
}
|
|||
|
|
}
|