반응형

하이 라키 뷰에서 Gun 오브젝트를 선택하여 AddComponent -> Animation을 생성합니다 

 

 

하이 라키 뷰에 Gun 오브젝트를 선택하고  Window -> Animaton -> Animaton을 클릭합니다 

 

 

Animation 타임라인에서 Create 를 누르고  Assets에 Animation 폴더를 생성하고  파일 이름을 ChargeBullet으로 하여  저장합니다 

 

 

 

아래 동영상과 같이 타임 라인에 왼쪽 위에 빨간 버튼을 누르고 총이 왼쪽으로 회전 하는 애니메이션을 만듭니다

각각 타임라인에  라인 바를 갖다 놓고 총의 움직임을 주면선 애니메이션을 만듭니다

 

하이 라키 뷰에 Gun 오브젝트를 선택하고 자식으로 Cyilnder를 생성하고 position 0, 0.04, 0.251

Rotation 90, 0, 0   Scale 0.1, 0.15, 0.1로 맞춥니다 

총을 쏘았을 때 탄피가 튕겨 나오는 애니메이션을 할 수 있게 총안쪽에  보이지 않는 위치에 놓습니다 

 

 

 

Gun오브젝트의 Cylinder를 선택하고 window -> Animation -> Animation을 선택하여 빨간 버튼 아래에 있는 애니메이션 선택 바를 누르고 Create new Clip을 선택하여 애니메이션 이름을 Fire 하고 저장합니다 

 

 

 

 

 

그림과 같이 탄피가 나오는 애니메이션을 Cylinder를 타임라인에 움직이며 애니메이션을 줍니다 

 

Gun 오브젝트를 선택하고 Animation에 그림과 같이 애니메이션을 연결합니다 

Gun 오브젝트를 선택하고 자식으로 빈 오브젝트를 만들어 그림과 같이 총끝머리에 위치시키고 이름을 spPoint라고 합니다 차후에 총알 발사 위치와 총알 화염 이팩트가 터지는 위치입니다 

 

 

Gun 오브젝트를 선택하고 Gun Tag를 만들어서 Tag를 Gun으로 합니다  

 

 

 

source_effect.unitypackage
0.01MB

 

이팩트 소스를 다운로드하여 그림과 같이 Prefabs 폴더에 이팩트 파일을 저장합니다 

 

 

 

 

 

GunCtrl 스크립트 수정

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

public class GunCtrl : MonoBehaviour
{
    //총 발사음
    public AudioClip sndFire;
    //실탄 장전음
    public AudioClip sndCocking;
    //배경음악
    public AudioClip sndStage;
    //게임 오버음
    public AudioClip sndOver;

    //프리팹 접시,참새, 폭파화염,총구화염, 총알
    public Transform clay, bird, exp, gunFire, fireBullet;

    //탄피,총구위치
    Transform bulletCase, spPoint;

    //실패 횟수
    static public int miss;

    //성공횟수
    int hit;

    //남은 총알
    int bulletCnt;

    //시작시간, 종료시간
    float startTime, overTime;
    bool gameOver = false;

    //화면폭과높이
    int width, height;

    void Start()
    {
        Screen.orientation = ScreenOrientation.Landscape;
        Screen.sleepTimeout = SleepTimeout.NeverSleep;

        Cursor.visible = false;

        SetStage();
    }
    private void Update()
    {
        // 10번 미스 되면 게임 오버
        if (miss >= 10)
        {
            gameOver = true;
            overTime = Time.time;
        }

        if (gameOver)
        {
            return;
        }

        // Esc 누르면 게임종료
        if (Input.GetKeyDown(KeyCode.Escape))
        {
            EditorApplication.isPlaying = false;
        }

        MakeClay();
        RotateGun();

        if (Input.GetMouseButtonDown(0))
        {
            FireGun();
        }
        if (bulletCnt < 5 && Input.GetMouseButtonDown(1))
        {
            StartCoroutine(ChargeGun());
        }

    }

    //총회전 
    void RotateGun()
    {
        //카메라부터 거리를 설정
        Vector3 pos = Input.mousePosition;

        //화면의 기준으로 총의 움직임을 제한한다
        pos.x = Mathf.Clamp(pos.x, 0, Screen.width);
        pos.y = Mathf.Clamp(pos.y, 0, Screen.height);

        //카메라로 부터의 거리
        pos.z = 13.2f;
        //마우스 위치를 월드 좌표로 변환
        Vector3 view = Camera.main.ScreenToWorldPoint(pos);

        //총의 회전
        transform.LookAt(view);

    }

    void FireGun()
    {
        //실탄 장전 애니메이션이 진행중이면 발사금지
        if (GetComponent<Animation>().isPlaying)
        {
            return;
        }

        RaycastHit hit;

        //카메라 시점에서 커서 위치 계산
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        Physics.Raycast(ray, out hit, Mathf.Infinity);

        //총을 클릭하면 실탄 재장전
        if (hit.transform.tag == "Gun" && bulletCnt < 5)
        {
            StartCoroutine(ChargeGun());
            return;
        }

        //총구 앞에 화면
        Instantiate(gunFire, spPoint.position, Quaternion.identity);
        //총탄 발사 
        Instantiate(fireBullet, spPoint.position, spPoint.rotation);
        //탄피 배출 애니메이션
        GetComponent<Animation>().Play("Fire");

        CheckTarget(hit);

        //남은 실탄 수 처리
        bulletCnt--;
        if (bulletCnt<= 0)
        {
            StartCoroutine(ChargeGun());
        }
    }

    //목표물 적중여부 판정
    void CheckTarget(RaycastHit hit)
    {
        switch (hit.transform.tag)
        {
            //접시 명중되었을 때 점수 처리및 폭발이팩트 생성및 제거
            case "Clay":
                this.hit++;
                Instantiate(exp, hit.transform.position, Quaternion.identity);
                Destroy(hit.transform.gameObject);
                break;

                // 참새 사망시 미스 처리및 참새연결 스크립트의 DeadBird 함수 와 통신 
            case "Bird":
                Instantiate(gunFire, hit.transform.position, Quaternion.identity);
                miss++;
                hit.transform.SendMessage("DeadBird", SendMessageOptions.DontRequireReceiver);
                break;

        }
    }

    //장전 애니메이션 
    IEnumerator ChargeGun()
    {
        while (GetComponent<Animation>().isPlaying)
        {
            yield return 0;
        }

        GetComponent<Animation>().Play("ChargeBullet");
        yield return new WaitForSeconds(0.5f);
        bulletCnt = 5;
    }

    //접시 생성
    void MakeClay()
    {
        if (Random.Range(0, 1000) > 970 && !GetComponent<Animation>().isPlaying)
        {
            if (Random.Range(0,100)< 70)
            {
                Instantiate(clay);
            }
            else
            {
                Instantiate(bird);
            }
        }
    }

    //장전 음악 
    void SoundClick()
    {
        bulletCase.gameObject.GetComponent<Renderer>().enabled = true;
        AudioSource.PlayClipAtPoint(sndCocking, Vector3.zero);
    }

    //탄발사음 
    void SoundFire()
    {
        bulletCase.gameObject.GetComponent<Renderer>().enabled = true;
        AudioSource.PlayClipAtPoint(sndFire, Vector3.zero);
    }

    //탄피 감추기 애니메이션
    void HideBullet()
    {
        bulletCase.gameObject.GetComponent<Renderer>().enabled = false;
    }
    void SetStage()
    {
        width = Screen.width;
        height = Screen.height;

        spPoint = GameObject.Find("spPoint").transform;

        bulletCase = transform.Find("Cylinder");

        bulletCase.gameObject.GetComponent<Renderer>().enabled = false;

        startTime = Time.time;
        hit = miss = 0;
        bulletCnt = 5;
        gameOver = false;

        GetComponent<AudioSource>().loop = true;
        GetComponent<AudioSource>().Play();
    }

    void OnGUI()
    {
        // GUI.skin = skin;

        //게임진행시간 
        float time = Time.time - startTime;

        if (!gameOver)
        {
            //커서위치에 조준점 표시
            GUI.DrawTexture(new Rect(Input.mousePosition.x - 24, height - Input.mousePosition.y - 24, 48, 48),
                            Resources.Load("crossHair") as Texture2D);
        }
        else
        {
            time = overTime - startTime;
        }

        //남은 실탄수 표시
        for (int i = 1; i <= bulletCnt; i++)
        {
            GUI.DrawTexture(new Rect(i * 12, height - 20, 8, 16), Resources.Load("bullet") as Texture2D);
        }

        //점수 등 표시
        string sHit = "<size='30'>HIT : " + hit + "</size>";
        string sMiss = "<size='30'>MISS : " + miss + "</size>";
        string sTime = "<color='yellow'><size='30'>Time : " + (int)time + "</size></color>";

        GUI.Label(new Rect(30, 20, 120, 40), sHit);
        GUI.Label(new Rect(width / 2 - 40, 20, 160, 40), sTime);
        GUI.Label(new Rect(width - 120, 20, 120, 40), sMiss);

        string msg = "Shoot : Left Btn  Charge : Gun Click";
        GUI.Label(new Rect(width - 380, height - 40, 380, 40), msg);

        //게임오버 처리
        if (gameOver)
        {
            Cursor.visible = true;
            if (GetComponent<AudioSource>().clip != sndOver)
            {
                GetComponent<AudioSource>().clip = sndOver;
                GetComponent<AudioSource>().loop = false;
                GetComponent<AudioSource>().Play();
            }

            //Play Game 버튼 생성 및 버튼On 시 게임다시 진행
            if (GUI.Button(new Rect(width / 2 - 70, height / 2 - 50, 140, 60), "Play Game"))
            {
                Application.LoadLevel("MainGame");
            }

            //게임에서 나옴
            if (GUI.Button(new Rect(width / 2 - 70, height / 2 + 50, 140, 60), "Quit Game"))
            {
                EditorApplication.isPlaying = false;
            }
        }
    }
}

 

 

 

 

 

 

 

 

GunCtrl 스크립트를 작성하고   Sound 파일에 있는 음악 소스 파일을 그림과 같이 연결합니다 

 

Prefabs파일에 있는 프리 팹을 GunCtrl 스크립트에 연결합니다 

 

 

Gun 오브젝트를 선택하고  AudioSource를 만들어서 AudioClip에 Stage 파일을 연결합니다

 

 

 

 

 

 

 

Gun오브젝트를 선택하고 애니메이션 타임라인을 열고 애니메이션 타임라인 3/2 되는 지점에 애니메이션 이벤트를 만들어서 Function을 SoundClick() 함수에 연결합니다 

 

Fire 애니메이션을 선택하고 첫 타임라인에 SoundFire() 함수를 연결하는 애니메이션 이벤트를 만듭니다 

 

Fire 애니메이션 마지막 타임 라인에 HideBullet() 함수를 연결하는 애니메이션 이벤트를 만듬니다 

 

ClayCtrl 스크립트를 열고 아래 그림과 같이 GunCtrl.miss++; 를 추가합니다 

 

 

 

 

 

 

 

 

아래 동영상과 같이 총쏘는 게임을 만들어 보았습니다 

여기까지 따라 오신분들 너무 수고 많으셨습니다

감사해요 ㅎㅎ

 

반응형

+ Recent posts