반응형

하이 라키 뷰에서 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++; 를 추가합니다 

 

 

 

 

 

 

 

 

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

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

감사해요 ㅎㅎ

 

반응형
반응형

하이 라키 뷰에 오른쪽 마우스를 누르고 3D object -> Cylinder를 만듭니다

 

그리고 스케일을 조정하여 1, 0.02, 1 을 값을 넣습니다 

 

그림과 같이 납작한 접시 모양이 됩니다 

 

하이라키 뷰에 Cylinder의 CrayCtrl 스크립트를 만들어 붙입니다 

ClayCtrl 스크립트작성

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

public class ClayCtrl : MonoBehaviour
{

    float speed; //접시 속도
    float rotZ; //접시 각도
    float gravity; // 추락속도

    int[] dir = { -1, 1 };
    int dirX; // 이동방향
    void Start()
    {
        SetPosition();
    }

    // Update is called once per frame
    void Update()
    {
        //접시의 이동속도를 감속한다
        gravity -= 1.3f * Time.deltaTime;
        //접시의 이동방향과 속도를 설정

        //접시를 회전을 주어 월드좌표로 이동
        Vector3 move = new Vector3(speed * dirX, gravity, 0) * Time.deltaTime;
        transform.Translate(move, Space.World);


        //화면에 접시가 벗어 나면 제거 한다
        if (Mathf.Abs(transform.position.x)>8 || transform.position.y < -3)
        {
           // GunCtrl.miss++;
            Destroy(gameObject);
        }
        
    }

    void SetPosition()
    {
     // 랜덤으로 접시속도 설정
        speed = Random.Range(3, 5f);

        //추락속도 설정
        gravity = 2f;

        //이동 방향 설정
        dirX = dir[Random.Range(0, 2)];

        //화면 의 좌우 위치
        float posX = -8 * dirX;

        //접시의 높이 및 회전설정
        float posY = Random.Range(2.5f, 4);
        transform.position = new Vector3(posX, posY, 9);
        transform.eulerAngles = new Vector3(-50, 0, Random.Range(10, 20f) * dirX);
    }
}

 

 

에셋에 Prefabs 폴더를 만들고 Clay 오브젝트를 드래그하여 프리 팹을 만들고 하이 라키 뷰에 있는 Clay는 삭제합니다 

 

 

참새가 죽을 때 나오는 꽥 오브젝트를 만들겠습니다.

Texture 폴더에 있는 꽥 그림파일을 하이 라키 뷰에 드래그하여 올려놓습니다 

 

OCtrl 스크립트를 만들고 꽥 오브젝트에 붙입니다 

 

OCtrl 스크립트 작성

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

public class OCtrl : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        Destroy(gameObject, 1.5f);
    }


}

 

 

 

하이 라키뷰에 있는 꽥 오브젝트를 Prefabs 폴더에 드래그 하여 프리팹을 만듬니다 

하이라키뷰에 꽥 오브젝트는 삭제합니다 

 

 

 

하이라키 뷰에 Cube 오브젝트를 생성하여 스케일을 1, 0.02, 1을 맞춥니다 

 

Cube의 이름을 FireBullet으로 바꾸고 FireBullet 스크립트를 생성하여 붙입니다 

 

 

FireBullet 스크립트 작성

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

public class FireBulletCtrl : MonoBehaviour
{

    //속도
    float speed = 60f;

    // 총알 삭제 시간
    float delay = 0.5f;
    void Update()
    {
        // 총알 속도 설정
        float Move = speed * Time.deltaTime;

        //총알의 이동 방향 설정
        transform.Translate(Vector3.forward * Move);

        // 총알 삭제를 설정한다 
        delay -= Time.deltaTime;
        if (delay <= 0)
        {
            Destroy(gameObject);
        }
    }
}

 

 하이 라키 뷰에 FireBullet 오브젝트를 드래그 하여 Prefabs 폴더에 생성합니다 

그리고 하이 라키뷰에 있는 오브젝트는 삭제 합니다  

 

하이라키 뷰에  Quad를 생성하여 스케일을  0.8, 0.8 ,1로 맞춥니다 

 

 

 

Materials 폴더에 메터리얼을 생성하고 이름을 Bird 라하고 Shader -> Unlit/Transfarent를 하고 Sparrow그림파일을 선택하여 나타나게 합니다 

 

Materials파일에 있는 Bird 메터리얼을 Bird 오브젝트에 드래그하여 붙입니다 

 

Scripts폴더에  BirdCtrl 스크립트를 만들고 BirdCtrl 스크립트를 작성합니다 그리고 Bird 오브젝트에 붙임니다

 

 

BirdCtrl  스크립트 작성

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

public class BirdCtrl : MonoBehaviour
{
    //사망시 프리팹 연결 오브젝트
    public Transform oCtrl;


    //참새 이동 속도
    float speed;

    //죽었는지? 아닌지?
    bool isDead = false;

    void Start()
    {
        SetPosition();
        
    }


    void Update()
    {
        //속도 설정
        float Move = speed * Time.smoothDeltaTime;

        
        if (!isDead)
        {
            //날아갈때 오른쪽으로 이동
            transform.Translate(Vector3.right * Move, Space.World);
        }
        else
        {
            //떨어질대 아래로 이동
            transform.Translate(Vector3.down * Move, Space.World);
        }

        //화면을 벗어나면 제거
        if (transform.position.x > 7 || transform.position.y < -3)
        {
            Destroy(gameObject);
        }
    }

    //참새 사망시
    void DeadBird()
    {
        isDead = true;

        //참새사망시 180도 회전 설정
        transform.eulerAngles = new Vector3(0, 0, 180);

        //참새 위치 계산를 계산하여 꽥 오브젝트 생성할 위치을 설정하고 참새가 죽으면 생성한다
        Vector3 pos = new Vector3(transform.position.x, transform.position.y + 0.2f, 8);
        Quaternion rot = Quaternion.identity;

        rot.eulerAngles = new Vector3(0, 0, 0);
        Instantiate(oCtrl, pos, rot);
    }

    void SetPosition()
    {
        //참새의 속도 설정
        speed = Random.Range(2, 3f);

        //참새의  랜덤 위치설정
        transform.position = new Vector3(-7, Random.Range(1.4f, 4.7f), 8);
    }
}

 

 

Bird 오브젝트를 Prefabs폴더에 드래그하여 프리 팹을 만들고 Bird 프리팹을 선택하여 O Ctrl  자리에  꽥 프리팹을 연결합니다 

그리고 하이 라키 뷰에 있는  Bird오브젝트는 삭제합니다 

 

Biird 오브젝트를 선택하고 Tag에 Bird를 생성하여 태그 합니다 

 

Clay 프리 팹을 선택하여 Tag Clay를 선택하여 태그 합니다 

반응형
반응형

하이 라키 뷰에 빈 오브젝트를 만들고 이름을 Gun으로 하고 Transform position과 Rotation을 0으로 맞춥니다

 

 

FBX 파일에서 M4A1_FBX_2 오브젝트를 드래그하여 하이 라키 뷰의 Gun 오브젝트의 자식으로 놓습니다 

그리고 Position 값을 0으로 맞춥니다

 

그림과 같이 총의 위치가 되면 됨니다

 

GunCtrl 스크립트 작성

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

public class GunCtrl : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
      
    }
    private void Update()
    {
        RotateGun();
    }

    //총회전 
    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);

    }

}

 

 

 

작성한 스크립트를 Gun 오브젝트에 드래그하여 붙입니다 

 

영상과 같이 마우스를 움직였을 때 총이 회전하면 됩니다 

 

반응형
반응형

 

유니티 엔진으로 3D 오브젝트와 2D오브젝트를 활용하여 게임을 만들어 보겠습니다 

간단한 총쏘기 게임을 만들건대 게임을 좋아하는 분들이 쉽게 만들 수 있도록 설명하도록 노력하겠습니다

 

 

 

총쏘기게임만들기

 

www.youtube.com

 

 

 

source.unitypackage
3.00MB

유니티 엔진을 열고 Scenes 파일에 있는 씬의 이름을 MainGame으로 바꿉니다 

 

 

그리고  source파일을 다운로드하여  클릭하여 파일을 엽니다 

 

 

 

 

 

 

게임 소스를 확인하고 임포트 합니다 

 

 

에셋에 파일을 임포트 한 모습을 확인할 수 있습니다 

 

 

하이 라키 신에서  Main Camera를 선택하여 아래 그림과 같이   Transform Position 값을 0, 1.6 , -6.2로 바꾸고 카메라의 각도 Field of View를 30으로 바꿉니다  

 

 

 

 

 

하이 라키 뷰에서 오른쪽 마우스 버튼을 누르고 Quad를 선택하여 생성합니다 

 

그리고 이름을 BackGround라고 바꾸고 Transform  Position 값을 0, 2.3, 9.5   Scale 값을 17, 10 , 1로 바꿉니다 

 

그리고  프로젝트 뷰에서  Materials 빈 파일을 만들고 마우스 오른쪽 버튼을 누르고 Material을 생성합니다

 

 

 

 

 

 

material의 이름을 background 라바꾸고 속성에 들어가서 Shader -> Unlit/Transparent로 바꾸고 그림 초원 2를 선택하여 넣습니다 

 

 

 

 

 속성을 바꾼 메터리얼을 선택하여  하이 라키뷰의 BackGround 오브젝트를 선택하고 메터리얼을 드래그하여 붙혀 넣습니다

 

 

그리고 다시 하이라키 뷰의 Quad를 만들고 이름을 Sky 라 바꾼 다음 BackGround를 만든 것과 같이 Material를 생성하여 Shader를 Unlit/Transparent 토하고 그림을 sky1을 붙입니다 그리고 메터 리어를 Sky 오브젝트에 연결합니다 

그리고 Transform을 0, 2.6, 10   Scale 17, 10,  1 롤 변경합니다 

 

 

 

 

 

 

Texture 폴더의 sky1 그림파일에서  Wrap Mode -> Repeat로 바꿉니다 

 

 

 

 

Scripts 폴더에서 Sky 스크립트를 생성하여 스크립트를 작성합니다 

 

Sky 스크립트 작성

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

public class Sky : MonoBehaviour
{

    float speed = 0.02f;
    // Update is called once per frame
    void Update()
    {
        float ofs = speed * Time.time;
        transform.GetComponent<Renderer>().material.mainTextureOffset = new Vector2(ofs, -1);
    }
}

 

 

 

 

 

 

 

 

 

하이 라키 뷰에서 Sky를 선택하고 Sky 스크립트를 연결합니다 

 

게임 뷰에서 화면을 16 : 9로 맞춥니다 

 

 

 

 

 

 

 

 

아래 동영상과 같이 화면이 연속적으로 움직이면 됩니다 

 

 

반응형

+ Recent posts