공식 예제 중 Space Shooter를 만들어보았다.

사이트 → https://unity3d.com/kr/learn/tutorials/s/space-shooter-tutorial


2D 슈팅게임이지만 완전 2D로 만든건 아니고 3D방식으로 제작하더라.

에셋스토어로 들어가서 Space Shooter Tutorial을 다운로드받고 순서따라 영상보면서 만들면 된다.



PlayerController 스크립트 -> 플레이어에서 플레이어의 이동, 탄발사를 관리

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
[System.Serializable]
// 게임화면 경계선을 지정
public class Boundary
{
    public float xMin, xMax, zMin, zMax;
}
 
// 플레이어의 동작을 관리하는 스크립트
public class PlayerController : MonoBehaviour {
    
    // 속도와 회전수치를 받음
    public float speed;
    public float tilt;
    public Boundary boundary;
 
    // 탄과 탄 발사위치를 받음
    public GameObject shot;
    public Transform shotSpawn;
 
    // 탄 발사주기 조정
    public float fireRate;
    private float nextFire;
 
    // Use this for initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void Update () {
        // Input.GetAxis를 이용하면 좌우나 상하 이동시 0~1값을 리턴해준다.
        float moveHorizontal = Input.GetAxis("Horizontal");
        float moveVertical = Input.GetAxis("Vertical");
 
        // 수치만큼 벡터를 생성해서 그만큼의 속도(벡터)를 줌.
        Vector3 movemont = new Vector3(moveHorizontal, 0.0f, moveVertical);
        this.GetComponent<Rigidbody>().velocity = movemont * speed;
 
        // position의 x값과 z값이 min~max를 넘어가면 Mathf.Clamp 함수를 이용해서 안으로 넣어줌
        this.GetComponent<Rigidbody>().position = new Vector3
            (
            Mathf.Clamp(this.GetComponent<Rigidbody>().position.x, boundary.xMin, boundary.xMax),
            0.0f,
            Mathf.Clamp(this.GetComponent<Rigidbody>().position.z, boundary.zMin, boundary.zMax)
            );
 
        // 플레이어를 회전
        this.GetComponent<Rigidbody>().rotation = Quaternion.Euler(0.0f, 0.0f, this.GetComponent<Rigidbody>().velocity.x * -tilt);
 
        // 스페이스바를 누르고 있을때. 현재시간이 다음발사시간을 넘어서면 탄이 발사됨
        if (Input.GetKey(KeyCode.Space) && Time.time > nextFire)
        {
            // 발사 후 다음 발사시간을 조정
            nextFire = Time.time + fireRate;
            // 발사위치에서 탄을 
            Instantiate(shot, shotSpawn.position, shotSpawn.rotation);
        }
    }
}
 
cs



Mover 스크립트 -> 탄에 적용되어서 탄이 생성되면 알아서 앞으로 나가게한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class Mover : MonoBehaviour {
 
    public float speed;
    // Use this for initialization
    void Start () {
        // 발사된 탄은 스스로 
        this.GetComponent<Rigidbody>().velocity = transform.forward * speed;
    }
    
    // Update is called once per frame
    void Update () {
        
    }
}
 
cs



DestroyByBoundary -> 빈 오브젝트를 화면 경계선 크기만큼 설정한 후 Collider를 넣어서 

탄이 이 경계선에서 나가면 죽게 만듬.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class DestroyByBoundary : MonoBehaviour {
 
    // Use this for initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void Update () {
            
    }
 
    private void OnTriggerExit(Collider other)
    {
        Destroy(other.gameObject);
    }
}
cs



DestroyByTime -> 생성한 후 시간이 지나면 알아서 삭제되도록 함. 이펙트에 넣어서 이펙트가 끝나면 죽도록

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class DestroyByTime : MonoBehaviour {
 
    public float lifetime;
    // Use this for initialization
    void Start () {
        // 생성후 lifetime 후에 알아서 
        Destroy(gameObject, lifetime);
    }
    
    // Update is called once per frame
    void Update () {
        
    }
}
cs



DestroyByContact -> 행성(장애물)에 들어가는 스크립트로 다른 무언가와 충돌하면 반응하고 삭제하게 만듬

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
// 행성에 들어감
public class DestroyByContact : MonoBehaviour {
 
    public GameObject explosion;
    public GameObject playerexplosion;
    public int scoreValue;
    private GameController gamecontroller;
    // Use this for initialization
    void Start () {
        // 게임컨트롤러를 찾아줌
        GameObject gameControllerObject = GameObject.FindWithTag("GameController");
        if(gameControllerObject != null)
        {
            gamecontroller = gameControllerObject.GetComponent<GameController>();
        }
    }
    
    // Update is called once per frame
    void Update () {
        
    }
 
    private void OnTriggerEnter(Collider other)
    {
        // Boundary 오브젝트와 충돌하면 아무것도 아님
        if (other.tag == "Boundary")
        {
            return;
        }
 
        // 다른것과 충돌하면 현재위치에 폭발 이펙트를 생성
        Instantiate(explosion, transform.position, transform.rotation);
 
        // 캐릭터와 충돌하면
        if (other.tag == "Player")
        {
            // 캐릭터폭발 이펙트 생성하고, 컨트롤러에서 게임오버함수 실행
            Instantiate(playerexplosion, other.transform.position, other.transform.rotation);
            gamecontroller.GameOver();
        }
 
        // 컨트롤러에서 점수를 올려주고
        gamecontroller.AddScore(scoreValue);
 
        // 자기 자신(행성)과 충돌한 적(탄 or 캐릭터)을 둘다 삭제
        Destroy(other.gameObject);
        Destroy(gameObject);
    }
}
cs



GameController -> 게임 컨트롤러에 들어가 점수, 게임오버, UI등을 관리

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
 
public class GameController : MonoBehaviour {
 
    public GameObject hazard;
    public Vector3 spawnValue;
    public int hazardCount;
    public float spawnWait;
    public float startWait;
    public float waveWait;
 
    public Text scoreText;
    public Text restartText;
    public Text gameOverText;
 
    private bool gameOver;
    private bool restart;
    private int score;
 
    // 코루틴으로 적 생성
    IEnumerator SpawnWaves()
    {
        yield return new WaitForSeconds(startWait);
        while (true)
        {
            for (int i = 0; i < hazardCount; i++)
            {
                Vector3 spawnPosition = new Vector3(Random.Range(-spawnValue.x, spawnValue.x), spawnValue.y, spawnValue.z);
                Quaternion spawnRotation = Quaternion.identity;
                Instantiate(hazard, spawnPosition, spawnRotation);
                // spawnWait마다 주기적으로 적생성
                yield return new WaitForSeconds(spawnWait);
            }
            // 한 웨이브가 끝나면 waveWait 후에 적을 생성
            yield return new WaitForSeconds(waveWait);
 
            // gameover 변수가 true가되면 재시작 text를 출력
            if(gameOver)
            {
                restartText.text = "Press 'R' for Restart";
                restart = true;
                break;
            }
        }
    }
 
    // 스코어를 출력하는 함수
    void UpdateScore()
    {
        scoreText.text = "score: " + score;
    }
 
    // 스코어를 증가시키는 함수
    public void AddScore(int newScoreValue)
    {
        score += newScoreValue;
        UpdateScore();
    }
 
    // 게임오버시 게임오버를 출력하고 변수를 true로 활성화
    public void GameOver()
    {
        gameOverText.text = "Game Over!";
        gameOver = true;
    }
 
    // Use this for initialization
    void Start ()
    {
        // 기본 변수 및 텍스트 초기화
        gameOver = false;
        restart = false;
        gameOverText.text = "";
        restartText.text = "";
 
        // 초기점수 세팅 및 출력
        score = 0;
        UpdateScore();
 
        // 코루틴 시작하여 적 생성
        StartCoroutine(SpawnWaves());
    }
    
    // Update is called once per frame
    void Update () {
        // restart가 true가 됐을시 R키를 누르면 main씬을 새로 Load해줌.
        if(restart)
        {
            if(Input.GetKeyDown (KeyCode.R))
            {
                //Application.LoadLevel(Application.loadedLevel);
                SceneManager.LoadScene("Main", LoadSceneMode.Single);
            }
        }
    }
}
cs



실행화면



만든 게임은 분할압축하여 업로드하였다. 

예제랑 똑같은데 더 허접한 듯

Build.z01

Build.zip


Posted by misty_
,