Super Kawaii Cute Cat Kaoani
본문 바로가기
🎮 취미/Unity

유니티 스터디 - 게임 개발 속성 강의 (2)

by wonee1 2024. 11. 15.
728x90

✏️이 글은 나도 코딩님의 유니티 무료 강의 5시간 게임 개발 속성 강의를 듣고 내용을 정리한 것입니다. 유니티를 처음 공부하시는 분들이 보기에 좋은 강의라서 추천드려요! 

 

✏️실습을 하면서 기록한 것이라서 내용이 들쭉날쭉할 수 있습니다

 

 

 

출처 🔽

https://www.youtube.com/watch?v=rJE6bhVUNhk&t=9529s

 

 

 

 

 

 

👉적 만들기 

 

더보기

 

장애물 아이템 크기 28 픽셸로 설정

  • Enemy는 바깥쪽에서 밑으로 쭉 떨어지는 동작을 정의하면 된다.
  • 또한 떨어진 오브젝트는 화면상에서 제거해줘야한다

 

✏️코드 작성

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

public class Enemy : MonoBehaviour
{
     [SerializeField]
     private float moveSpeed =10f; 

     private float minY=-7;

    // Update is called once per frame
    void Update()
    {
        transform.position += Vector3.down * moveSpeed * Time.deltaTime;
         if(transform.position.y<minY){
            Destroy(gameObject);
         }// 화면상에 사라졌을 때 오브젝트 제거 

    }
}

 

💠중간 점검 및 설정

 

 

  • Box Colider 2d를 추가해준 다음 영역을 설정해준다.
  • 태그도 새롭게 Enemy를 추가해준다
  • Rigidbody 2d를 추가해준다 (충돌 처리를 위해서 )

 

 

💠Box Collider 설정

 

 

  • Is Trigger 가 체크되지 않으면 물리법칙이 적용되기 때문에 장애물과 플레이어가 서로를 밀어낸다
  • Is Trigger가 체크되어 있으면 물리법칙이 적용되지 않기 때문에 밀어내지 않게 된다.

 

 

  • Prefabs에서 여러가지 장애물을 설정한다
  • 각 장애물마다 충돌 범위를 설정해준다 (Edit Collider를 통해서 충돌 범위 조절)

 

 

 

 

👉랜덤으로 적 만들기 

 

더보기

💠랜덤으로 적 만들기

  • 화면상에 랜덤으로 적이 나오게 설정
  • 장애물 7개 중에서 5개를 랜덤으로 설정하는 스크립트 작성

 

✏️코드 작성

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

public class EnemySpawner : MonoBehaviour
{
    [SerializeField]
    private GameObject[] enemies; 
    private float[] arrPosX = {-2.2f,-1.1f,0f,1,1f,2.2f};
    // Start is called before the first frame update
    void Start()
    {   
        foreach( float posX in arrPosX){ // 배열의 값을 꺼내서 posX에 저장 
            int index = Random.Range(0,enemies.Length);
            SpawEnemy(posX,index);
        }
    }

    void SpawEnemy(float posX, int index){
        Vector3 spawnPos = new Vector3(posX, transform.position.y,transform.position.z);
        Instantiate(enemies[index], spawnPos, Quaternion.identity);

    }
}

 

 

 

 

 

 

👉적 무한 생성하기 

더보기

💠 적 무한 생성 하기 

  • 적을 무한으로 생성하기 위해서 스폰 코드를 작성해준다 

 

✏️코드 작성

 

EnemySpawner.cs

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

public class EnemySpawner : MonoBehaviour
{
    [SerializeField]
    private GameObject[] enemies; 
    private float[] arrPosX = {-2.2f, -1.1f, 0f , 1.1f, 2.2f};

    [SerializeField]
    private float spawnInterval = 1.5f; 

    void Start()
    {   
        StartEnemyRoutine();
    }

    void StartEnemyRoutine(){
        StartCoroutine("EnemyRoutine");
    }

    IEnumerator EnemyRoutine(){
        yield return new WaitForSeconds(3f);// 3초간 대기 후에 밑에 코드 실행 

        int enemyIndex= 0; 
        int spawnCount=0; 

        while(true){
          for (int i = 0; i < 5; i++) { 
            SpawEnemy(arrPosX[i], enemyIndex); // 선택된 위치에 장애물 생성
        }
        spawnCount +=1; 
        if(spawnCount %10==0){
            enemyIndex +=1;

        }
            yield return new WaitForSeconds(spawnInterval);// 1.5초 기다렸다가 반복 
        }//무한 반복 

    }

    void SpawEnemy(float posX, int index){
        Vector3 spawnPos = new Vector3(posX, transform.position.y,transform.position.z);
        
        if(Random.Range(0,5)==0){
            index +=1; 
        }// 0~4사이 숫자 (20%확률)
     
        if(index>=enemies.Length){
            index = enemies.Length-1; 
        }
       
        Instantiate(enemies[index], spawnPos, Quaternion.identity);

    }
}

 

 

Enemy.cs

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

public class Enemy : MonoBehaviour
{
     [SerializeField]
     private float moveSpeed =10f; 

     private float minY=-7;

    // Update is called once per frame
    public void SetMoveSpeed(float moveSpeed){
        this.moveSpeed = moveSpeed; // this는 현재 객체 
    }

    void Update()
    {
        transform.position += Vector3.down * moveSpeed * Time.deltaTime;
         if(transform.position.y<minY){
            Destroy(gameObject);
         }// 화면상에 사라졌을 때 오브젝트 제거 

    }
}

 

 

👉충돌처

더보기

💠 충돌 처리 

 

  • 물체 충돌 처리를  하기 위해서 코드를 수정해준다 

 

 

✏️코드 작성

 

Enemy.cs

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

public class Enemy : MonoBehaviour
{
     [SerializeField]
     private float moveSpeed =10f;

     private float minY=-7f;

    [SerializeField]
     private float hp = 1f; 

    // Update is called once per frame
    public void SetMoveSpeed(float moveSpeed){
        this.moveSpeed = moveSpeed; // this는 현재 객체 
    }

    void Update()
    {
        transform.position += Vector3.down * moveSpeed * Time.deltaTime;
         if(transform.position.y<minY){
            Destroy(gameObject);
         }// 화면상에 사라졌을 때 오브젝트 제거 

    }

    private void OnTriggerEnter2D(Collider2D other) {
         if(other.gameObject.tag == "Weapon"){
            Weapon weapon = other.gameObject.GetComponent<Weapon>(); //충돌한 대상이 weapon일 때만 충돌한 대상의 gameObject로 부터 weapon을 가져옴 
            hp -= weapon.damage;
            if(hp<=0){
                Destroy(gameObject);
            }
            Destroy(other.gameObject);
        }
        
    }

}

 

 

player.cs

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

public class Player : MonoBehaviour
{   [SerializeField] //유니티 상에서 값을 넣어줄 수 있게함 
    private float  moveSpeed;

    [SerializeField]
    private GameObject weapon;

    [SerializeField]
    private Transform shootTransform; //플레이어 머리 위에서 발사되는 예측값 

    [SerializeField]
    private float shootInterval = 0.05f; //미사일을 쏘는 간격 
    private float lastShotTime =0f; 

    void Update() {

    Vector3 mousePos =Camera.main.ScreenToWorldPoint(Input.mousePosition);
    float toX = Mathf.Clamp(mousePos.x,-2.35f,2.35f);
    transform.position = new Vector3(toX,transform.position.y,transform.position.z);  
    Shoot();
    }

    void Shoot(){

        if(Time.time-lastShotTime>shootInterval){

            Instantiate(weapon,shootTransform.position,Quaternion.identity); //게임 오브젝트를 만드는 메소드 
            lastShotTime =Time.time;//현재 시간으로 업데이트 
        
        }  //Time.time 게임이 시작된 이후로 현재까지 흐른 시간 

       
    }
    private void OnTriggerEnter2D(Collider2D other) {
         if(other.gameObject.tag == "Enemy"){
            Debug.Log("GAME OVER");
           Destroy(gameObject);
        }
    }

}

 

 

👉코인 만들기

더보기

 

 

  • Coin 오브젝트 애니메이션으로 만든 후 Prefabs에 등록하기 (isTrigger 설정도 해주기)

 

✏️코드 작성

 

Coin.cs

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

public class Coin : MonoBehaviour
{

    private float minY=-7f;
    // Start is called before the first frame update
    void Start()
    {
        Jump();
    }
    void Jump(){
        Rigidbody2D rigidBody=GetComponent<Rigidbody2D>();
        
        float randomJumpForce = Random.Range(4f, 8f);
        Vector2 jumpVelocity = Vector2.up * randomJumpForce;
        jumpVelocity.x = Random.Range(-2f,2f);
        rigidBody.AddForce(jumpVelocity,ForceMode2D.Impulse);

    }
    // Update is called once per frame
    void Update()
    {
         if(transform.position.y<minY){
            Destroy(gameObject);
         }// 화면상에 사라졌을 때 오브젝트 제거 
    }
}

 

  private void OnTriggerEnter2D(Collider2D other) {
         if(other.gameObject.tag == "Enemy"){
            Debug.Log("GAME OVER");
           Destroy(gameObject);
        }else if (other.gameObject.tag=="Coin"){
            Debug.Log("Coin+1");
            Destroy(other.gameObject);
        }
    }

 

 

 

 

 

👉점수 출력

더보기

 

  • 점수는 먹고 있는 코인 개수로 설정
  • 점수 패널을 새롭게 추가해준다

 

 

 

  • ScorePanel에 이미지와 텍스트를 지정해준다

 

 

 

  • Wrapping 설정은 Disabled로 설정

 

 

  • GameManger 오브젝트 생성 후 스크립트 작성
  • Text 부분에 Text(TMP)를 집어 넣는다

 

✏️코드 작성

 

GameManger.cs

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

public class GameManager : MonoBehaviour
{
   public static GameManager instance = null;
  

    [SerializeField]

    private TextMeshProUGUI text; 

    private int coin = 0; 

   void Awake(){

        if(instance == null){
            instance = this; 
        }

   }

    public void IncreaseCoin(){
        coin +=1; 
        text.SetText(coin.ToString());
    }

}

 

 

👉무기 업그레이드

더보기

 

  • weapon을 배열로 수정한다음 player에 추가해준다

✏️코드 작성

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

public class GameManager : MonoBehaviour
{
   public static GameManager instance = null;
  

    [SerializeField]

    private TextMeshProUGUI text; 

    private int coin = 0; 

   void Awake(){

        if(instance == null){
            instance = this; 
        }

   }

    public void IncreaseCoin(){
        coin +=1; 
        text.SetText(coin.ToString());

        if(coin % 30 ==0){//30의 배수 
            Player player = FindObjectOfType<Player>(); //플레이어를 찾으면 반환 
            if(player !=null){
                player.Upgrade();
            }
        }
    }

}

 

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

public class Player : MonoBehaviour
{   [SerializeField] //유니티 상에서 값을 넣어줄 수 있게함 
    private float  moveSpeed;

    [SerializeField]
    private GameObject[] weapons;
    private int weaponIndex =0; 

    [SerializeField]
    private Transform shootTransform; //플레이어 머리 위에서 발사되는 예측값 

    [SerializeField]
    private float shootInterval = 0.05f; //미사일을 쏘는 간격 
    private float lastShotTime =0f; 

    void Update() {

    Vector3 mousePos =Camera.main.ScreenToWorldPoint(Input.mousePosition);
    float toX = Mathf.Clamp(mousePos.x,-2.35f,2.35f);
    transform.position = new Vector3(toX,transform.position.y,transform.position.z);  
    Shoot();
    }

    void Shoot(){

        if(Time.time-lastShotTime>shootInterval){

            Instantiate(weapons[weaponIndex],shootTransform.position,Quaternion.identity); //게임 오브젝트를 만드는 메소드 
            lastShotTime =Time.time;//현재 시간으로 업데이트 
        
        }  //Time.time 게임이 시작된 이후로 현재까지 흐른 시간 

       
    }
    private void OnTriggerEnter2D(Collider2D other) {
         if(other.gameObject.tag == "Enemy"){
            Debug.Log("GAME OVER");
           Destroy(gameObject);
        }else if (other.gameObject.tag=="Coin"){
            GameManager.instance.IncreaseCoin();
            Destroy(other.gameObject);
        }
    }

    public void Upgrade(){
        weaponIndex +=1;
        if(weaponIndex >= weapons.Length){
            weaponIndex = weapons.Length-1; 
        }
    }
}

 

👉보스 만들기

더보기
  • 보스를 설정한 다음에 충돌처리와 스폰 처리를 해준다

 

✏️코드 작성

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

public class EnemySpawner : MonoBehaviour
{
    [SerializeField]
    private GameObject[] enemies; 
    private float[] arrPosX = {-2.2f, -1.1f, 0f , 1.1f, 2.2f};

    [SerializeField]
    private float spawnInterval = 1.5f; 

    [SerializeField]
    private GameObject boss;

    void Start()
    {   
        StartEnemyRoutine();
    }

    void StartEnemyRoutine(){
        StartCoroutine("EnemyRoutine");
    }

    IEnumerator EnemyRoutine(){
        yield return new WaitForSeconds(3f);// 3초간 대기 후에 밑에 코드 실행 
         
        float moveSpeed = 5f; //이동속도 5 
        int enemyIndex= 0; 
        int spawnCount=0; 

        while(true){
          for (int i = 0; i < 5; i++) { 
            SpawnEnemy(arrPosX[i], enemyIndex, moveSpeed); // 선택된 위치에 장애물 생성
        }

        spawnCount +=1; 
        if(spawnCount %10==0){
            enemyIndex +=1;
            moveSpeed +=2; 

        }

        if(enemyIndex >= enemies.Length){
            SpawnBoss();
            enemyIndex=0;
            moveSpeed =5f; 
        }//보스 등장 후 초기화 

            yield return new WaitForSeconds(spawnInterval);// 1.5초 기다렸다가 반복 
        }//무한 반복 

    }

    void SpawnEnemy(float posX, int index, float moveSpeed){
        Vector3 spawnPos = new Vector3(posX, transform.position.y,transform.position.z);
        
        if(Random.Range(0,5)==0){
            index +=1; 
        }// 0~4사이 숫자 (20%확률)
     
        if(index>=enemies.Length){
            index = enemies.Length-1; 
        }
       
        GameObject enemyObject = Instantiate(enemies[index], spawnPos, Quaternion.identity);
        Enemy enemy = enemyObject.GetComponent<Enemy>(); 
        enemy.SetMoveSpeed(moveSpeed);
    }

    void SpawnBoss(){
        Instantiate(boss, transform.position, Quaternion.identity );
    }

}

    private void OnTriggerEnter2D(Collider2D other) {
         if(other.gameObject.tag == "Enemy"|| other.gameObject.tag =="Boss"){
            Debug.Log("GAME OVER");
           Destroy(gameObject);
        }else if (other.gameObject.tag=="Coin"){
            GameManager.instance.IncreaseCoin();
            Destroy(other.gameObject);
        }
    }

 

👉게임 오버 처리

더보기

💠게임 오버 처리

  •  hp가 0 이하일 때, 보스를 잡을 때, 플레이어가 게임 오브젝트에 충돌했을 때 게임 오버가 되게 처리

 

   public void SetGameOver(){
        EnemySpawner enemySpawner = FindObjectOfType<EnemySpawner>();
        if(enemySpawner!= null){
            enemySpawner.StopEnemyRoutine();
        }
    }

    private void OnTriggerEnter2D(Collider2D other) {
         if(other.gameObject.tag == "Enemy"|| other.gameObject.tag =="Boss"){
            GameManager.instance.SetGameOver();
           Destroy(gameObject);
        }else if (other.gameObject.tag=="Coin"){
            GameManager.instance.IncreaseCoin();
            Destroy(other.gameObject);
        }
    }
    private void OnTriggerEnter2D(Collider2D other) {
         if(other.gameObject.tag == "Weapon"){
            Weapon weapon = other.gameObject.GetComponent<Weapon>(); //충돌한 대상이 weapon일 때만 충돌한 대상의 gameObject로 부터 weapon을 가져옴 
            hp -= weapon.damage;
            if(hp<=0){
                if(gameObject.tag == "Boss"){
                    GameManager.instance.SetGameOver();
                }
                Destroy(gameObject);
                Instantiate(coin, transform.position, Quaternion.identity);
            }
            Destroy(other.gameObject);
        }//충돌처리 
        

 

 

 

 


 

 

 

👉결과 화면  및 실행 

 

 

실행 결과

 

 

 

728x90