[Unity] 1인칭 FPS 게임 - 4. Gun

홍예주·2021년 7월 7일
0

1. Gun

- Unity Gun Object

SA_Wep_SMG는 Simple Apocalypse 에셋에서 가져온 모델링이다.
Projectile Spawn에서 총알이 발사된다.


- C# Code

using UnityEngine;

public class Gun : MonoBehaviour
{
    public Transform muzzle;
    public Projectile projectile;

    public float msBetweenShots = 100; //연사력
    public float muzzleVeloctiy = 35; //발사 순간 총알 속력

    float nextShotTime;

    public void Shoot()
    {
        //현재 시간이 nextShotTime보다 클 때만 총 쏨
        if (Time.time > nextShotTime)
        {

            nextShotTime = Time.time + msBetweenShots / 1000; //밀리초를 초로 바꾼거라 100으로 나눠서

            //발사체 instantiate(muzzle 위치에서)
            Projectile newProjectile = Instantiate(projectile, muzzle.position, muzzle.rotation) as Projectile;

            newProjectile.SetSpeed(muzzleVeloctiy);


        }
    }
}

2. Gun Controller

플레이어에 부착되는 스크립트로, 무기를 갈아끼는 용도로 사용된다.
원래 계획은 무기를 바꿔낄 수 있게 하는 것이었기 때문에 들어간 코드지만, 최종적으로는 별로 쓸모 없게 되었다.

- C# Code

using UnityEngine;

//무기 장비 등 기능 관리
public class GunController : MonoBehaviour
{

    Gun equippedGun;

    public Transform weaponHold;
    public Gun startingGun;

    private void Start()
    {
        if (startingGun != null)
        {
            //EquipGun(startingGun);
            equippedGun = startingGun;
        }
    }

    public void EquipGun(Gun gunToEquip)
    {
        if(equippedGun != null)
        {
            Destroy(equippedGun.gameObject);
        }
        equippedGun = Instantiate(gunToEquip, weaponHold.position,weaponHold.rotation) as Gun;

        //equippedGun.transform.SetParent(weaponHold, false);
        equippedGun.transform.parent = weaponHold;
        
    }

    public void Shoot()
    {
        if(equippedGun != null)
        {
            equippedGun.Shoot();
        }
    }
}

3. Projectile

Gun에서 발사될 총알이다.
3가지의 충돌 체크가 이루어진다

  • 적 : 적과 충돌 시 적에게 데미지 부여 후 총알 삭제
  • 장애물 : 총알 충돌 이펙트 발생 후 총알 삭제
  • 땅 : 총알 충돌 이펙트 발생 후 총알 삭제

- Unity Object

- C# Code

using UnityEngine;

public class Projectile : MonoBehaviour
{

    float speed = 10;
    float damage = 1;
    float skinWidth = 0.1f;

    public LayerMask EnemyMask;
    public LayerMask ObstacleMask;
    public LayerMask GroundMask;

    public GameObject shootImpact;
    

    public void SetSpeed(float newSpeed)
    {
        speed = newSpeed;
    }

    // Update is called once per frame
    void Update()
    {
        float moveDistance = speed * Time.deltaTime; //현재 프레임에서 이동할 거리

        CheckCollision(moveDistance);

        transform.Translate(Vector3.forward * moveDistance);

    }

    void CheckCollision(float moveDistance)
    {
        Ray ray = new Ray(transform.position, transform.forward);
        RaycastHit hit;


        //QueryTriggerInteraction.collide -> 트리거 콜라이더와 충돌하고 싶을 경우 지정
        if(Physics.Raycast(ray,out hit, moveDistance+skinWidth, EnemyMask, QueryTriggerInteraction.Collide)){
            OnHitObject(hit);
            GameObject impact = Instantiate(shootImpact, hit.point, Quaternion.LookRotation(hit.normal));
            Destroy(impact, 2f);
        }

        //총알이 장애물에 부딪히면 없어지게
        if(Physics.Raycast(ray,out hit, moveDistance, ObstacleMask))
        {
            Debug.Log("Hit obstacle");
            GameObject impact = Instantiate(shootImpact, hit.point, Quaternion.LookRotation(hit.normal));
            Destroy(impact, 2f);
            Destroy(this.gameObject);
        }

        if (Physics.Raycast(ray, out hit, moveDistance, GroundMask))
        {
            Debug.Log("Hit obstacle");
            GameObject impact = Instantiate(shootImpact, hit.point, Quaternion.LookRotation(hit.normal));
            Destroy(impact, 2f);
            Destroy(this.gameObject);
        }

    }

    //물체랑 부딪히는 경우
    void OnHitObject(RaycastHit hit)
    {
        IDamageble damagebleObject = hit.collider.GetComponent<IDamageble>();

        if(damagebleObject != null)
        {
            damagebleObject.TakeHit(damage);
            Destroy(this.gameObject);
        }

    
    }

    
}
profile
기록용.

0개의 댓글