게임오브젝트 3개를 생성해서 각각 배경을 넣어주는데

order in layer로 계층구조를 잡아줄것이다

a부터 c까지 각각 -3, -4, -5

게임 오브젝트의 좌표는 모두 0 0 0

복사를 해서 각각 3개로 만들어주고

0의 Y좌표는 0

1의 Y좌표는 -10

2의 Y좌표는 10

카메라는 그대로

배경은 뒤로 옮겨 눈속임을 할것이다.

 

스크립트 생성후 배경이 움직이는 로직 작성

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

public class Background : MonoBehaviour
{
    public float speed;
    void Start()
    {
        
    }

    void Update()
    {
        Vector3 curPos = transform.position;
        Vector3 nextPos = Vector3.down * speed * Time.deltaTime;
        transform.position = curPos + nextPos;
    }
}

그런데 이렇게 하면 맨뒤에 아무것도 없는 배경이 보인다.

따라서 배경을 무한으로 만들어 주어야한다.

 

카메라의 시점

카메라를 잡을때 메인카메라의 시점 * 2를해서 화면이 짤리기전에 한번 더 보여주게  하였고

y좌표가 -1일때 시작점을 바꾸어 연속적으로 보이게 하였다.

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

public class Background : MonoBehaviour
{
    public float speed;
    public int startIndex;
    public int endIndex;
    public Transform[] sprites;

    float viewHeight;
    
    void Start()
    {
        viewHeight = Camera.main.orthographicSize * 2; // 카메라
    }

    void Update()
    {
        Vector3 curPos = transform.position;
        Vector3 nextPos = Vector3.down * speed * Time.deltaTime;
        transform.position = curPos + nextPos;

        if (sprites[endIndex].position.y < viewHeight * (-1))
        {
            //#.Sprite ReUse
            Vector3 backSpritePos = sprites[startIndex].localPosition;
            Vector3 frontSpritePos = sprites[endIndex].localPosition;

            sprites[endIndex].transform.localPosition = backSpritePos + Vector3.up * viewHeight;

            //이동이 완료되면 EndIndex, StartIndex 갱신
            //#.Cursor Index Change
            int startIndexSave = startIndex;
            startIndex = endIndex;
            endIndex = (startIndexSave -1 == -1) ? sprites.Length-1 : startIndexSave-1;
        }

    }
}

A, B, C를 나눈 이유는 원근감을 주기 위해서이다.

 

Parallax: 거리에 따른 상대적 속도를 활용한 기술

C는 속도1 B는2 A는4

 

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

public class Background : MonoBehaviour
{
    public float speed;
    public int startIndex;
    public int endIndex;
    public Transform[] sprites;

    float viewHeight;
    
    void Start()
    {
        viewHeight = Camera.main.orthographicSize * 2; // 카메라
    }

    void Update()
    {
        

        if (sprites[endIndex].position.y < viewHeight * (-1))
        {
            Move();
            Scrolling();
        }

        void Move()
        {
            Vector3 curPos = transform.position;
            Vector3 nextPos = Vector3.down * speed * Time.deltaTime;
            transform.position = curPos + nextPos;
        }

        void Scrolling()
        {
            //#.Sprite ReUse
            Vector3 backSpritePos = sprites[startIndex].localPosition;
            Vector3 frontSpritePos = sprites[endIndex].localPosition;

            sprites[endIndex].transform.localPosition = backSpritePos + Vector3.up * viewHeight;

            //이동이 완료되면 EndIndex, StartIndex 갱신
            //#.Cursor Index Change
            int startIndexSave = startIndex;
            startIndex = endIndex;
            endIndex = (startIndexSave - 1 == -1) ? sprites.Length - 1 : startIndexSave - 1;
        }
    }
}

'산대특' 카테고리의 다른 글

2D Vertical Shooting Game 모작 최종  (0) 2024.04.08
팬텀로즈스칼렛 모작 최종  (0) 2024.04.08
2D Airplane - 5  (1) 2024.03.14
2D Airplane - 4  (0) 2024.03.12
2D Airplane - 3  (0) 2024.03.12

 

 

 

 

아이템을 만들것이다.

스프라이트를 나눠서 가져온다.

총알처럼 콜라이더와 리지드바디 추가 + 이즈트리거 체

이때 중력은 0

아이템 스크립트 생성후 3개에 부착

item 스크립트에 퍼블릭으로 string으로 선언하고 각 아이템의 이름을 직접 적어줄 것이다.

물체가 잘 내려오는지 확인

이제 애니메이션을 넣어줄것이다.

다른 오브젝트들도 똑같이 애니메이션을 만든다.

테스트

아이템 태그 부착

 

플레이어가 아이템을 먹어야하기에 onTriggerEnter2D를 사용할 것이다.

그런데 파워는 이미 선언되어 있고

파워 아이템을 먹으면 공격력이 증가되어야 하기에 변수를 따로 하나 더 선언

파워가 맥스 파워보다 증가되면 안되므로 조건을 걸어주고

맥스파워가 되면 보통 슈팅게임처럼 점수만 올려줄 것이다.

이제 Boom을 만들 것이다.

 

붐스킬 이미지를 가져오면 다른 오브젝트를 덮어버리는데

이는 order in layer로 층을 바꾸면 된다

현재 모두 0 이고 배경은 -1 이므로

배경은 -2로 붐스킬은 -1로 변경

 

그 후 붐스킬도 똑같이 애니메이션을 만들어 준다.

 

나중에 아이템 먹을 시 활성화 할것이므로 현재는 비활성화

 

그럼 플레이에게 따로 값을 주면된다.

 

플레이에게 퍼블릭으로 인스턴스를 만들어주고 어싸인

Boom을 먹으면 스킬을 활성화 하고 평상시에는 4초후 이펙트가 꺼지게 설정

적들은 배열로 관리하여 배열에서 찾아서 제거해준다.

퍼블릭으로 변경

플레이어의 파워와 맥스파워 설정

 보통 슈팅게임에서 아이템을 먹으면 저장을 하고

원하는 시기에 폭탄을 쏠 수 있도록 조정해야 한다.

그러므로 폭탄 개수를 저장할 변수 선언

폭탄도 파워와 같이 한계를 정할 것이므로 maxBoom까지 두개를 만들 것이다.

이제 Boom메소드를 만들것인데

아까 구현해던

이것을 다 긁어서 붐 메소드 안에 넣어줄 것이다.

붐 메서드에 기능은 이제 따로 빼두었는데

붐도 파워처럼 먹었을때에 대한 설정을 다시 지정해준다.

 

초기화

붐 아이콘도 라이프 아이콘을 복사해서 앵커의 위치를 바꾸어 준다.

게임 매니저에서 라이프 아이콘을 관리했던 것 처럼 복사해서

붐으로 만든 메소드에 집어 넣는다.

플레이어에서 게임매니저를 가져오고 업데이트하기 위해 메소드를 넣어준다.

알베도의 값을 0으로 줄인다.

만들어진 아이템 프리팹화

에너미가 사라진 곳에 아이템이 생성될 것이다.

어싸인

플레이 해보면 하나에서 아이템 2개가 나오는 오류?가 생긴다.

따라서 예외처리해야하는데

코드를 잘 살펴보면 디스트로이 되기 전에 온히트가 2번이라는 것을 알 수 있다.

이 코드만 추가해주면 예외처리가 된다.

 

using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Net.Http.Headers;
using UnityEngine;

public class Player : MonoBehaviour
{
    public bool isTouchTop;
    public bool isTouchBottom;
    public bool isTouchRight;
    public bool isTouchLeft;

    public int life;
    public int score;
    public int speed;
    public int power;
    public int boom;
    public int maxBoom;
    public float maxPower;
    public float maxShotDelay; //실제 딜레이
    public float curShorDelay; //한발 쏜 후 딜레이
    
    public GameObject bulletObjA;
    public GameObject bulletObjB;
    public GameObject boomSkill;

    public GameManager manager;
    public bool isHit;
    public bool isBoomTime;

    private Animator anim;

    private void Awake()
    {
        anim = GetComponent<Animator>();
    }

    void Move()
    {
        float h = Input.GetAxisRaw("Horizontal");
        if ((isTouchRight && h == 1) || (isTouchLeft && h == -1))
            h = 0;
        float v = Input.GetAxisRaw("Vertical");
        if ((isTouchTop && v == 1) || (isTouchBottom && v == -1))
            v = 0;
        Vector3 curPos = this.transform.position;
        Vector3 nextPos = new Vector3(h, v, 0) * speed * Time.deltaTime;
        transform.position = curPos + nextPos;

        if (Input.GetButtonDown("Horizontal") ||
            Input.GetButtonDown("Vertical"))
        {
            anim.SetInteger("Input", (int)h);
        }
    }

    private void Update()
    {
        Move();
        Fire();
        Boom();
        Reload();
    }

    void Fire()
    {
        if (!Input.GetButton("Fire1"))
            return;
        if (curShorDelay < maxShotDelay)
            return;

        switch (power)
        {

            case 1://Power One
                GameObject bullet = Instantiate(bulletObjA, transform.position, transform.rotation);
                Rigidbody2D rigid = bullet.GetComponent<Rigidbody2D>();
                rigid.AddForce(Vector2.up * 10, ForceMode2D.Impulse);
                break;
            case 2:
                GameObject bulletR = Instantiate(bulletObjA, transform.position + Vector3.right * 0.1f, transform.rotation);
                GameObject bulletL = Instantiate(bulletObjA, transform.position + Vector3.left * 0.1f, transform.rotation);
                Rigidbody2D rigidR = bulletR.GetComponent<Rigidbody2D>();
                Rigidbody2D rigidL = bulletL.GetComponent<Rigidbody2D>();
                rigidR.AddForce(Vector2.up * 10, ForceMode2D.Impulse);
                rigidL.AddForce(Vector2.up * 10, ForceMode2D.Impulse);

                break;
            case 3:
                GameObject bulletRR = Instantiate(bulletObjA, transform.position + Vector3.right * 0.3f, transform.rotation);
                GameObject bulletCC = Instantiate(bulletObjB, transform.position, transform.rotation);
                GameObject bulletLL = Instantiate(bulletObjA, transform.position + Vector3.left * 0.3f, transform.rotation);
                Rigidbody2D rigidRR = bulletRR.GetComponent<Rigidbody2D>();
                Rigidbody2D rigidCC = bulletCC.GetComponent<Rigidbody2D>();
                Rigidbody2D rigidLL = bulletLL.GetComponent<Rigidbody2D>();
                rigidRR.AddForce(Vector2.up * 10, ForceMode2D.Impulse);
                rigidCC.AddForce(Vector2.up * 10, ForceMode2D.Impulse);
                rigidLL.AddForce(Vector2.up * 10, ForceMode2D.Impulse);

                break;
        }
                curShorDelay = 0;
    }

    void Reload()
    {
        curShorDelay += Time.deltaTime;

    }
    
    void Boom()
    {
        if (!Input.GetKeyDown(KeyCode.Space))
            return;
        if (boom == 0)
            return;
        boom--;
        isBoomTime = true;
        manager.UpdateBoomIcon(boom);

        if (isBoomTime)
        {
            boomSkill.SetActive(true);
            Invoke("OffBoomSkill", 4f);
            GameObject[] enemies = GameObject.FindGameObjectsWithTag("Enemy");
            for (int index = 0; index < enemies.Length; index++)
            {
                Enemy enemyLogic = enemies[index].GetComponent<Enemy>();
                enemyLogic.OnHit(1000);
            }
            GameObject[] bullets = GameObject.FindGameObjectsWithTag("EnemyBullet");
            for (int index = 0; index < bullets.Length; index++)
            {
                Destroy(bullets[index]);
            }
        }
    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if(collision.gameObject.tag == "Border")
        {
            switch(collision.gameObject.name)
            {
                case "Top":
                    isTouchTop = true;
                    break;
                case "Bottom":
                    isTouchBottom = true;
                    break;
                case "Right":
                    isTouchRight = true;
                    break;
                case "Left":
                    isTouchLeft = true;
                    break;
            }
        }
        else if(collision.gameObject.tag == "Enemy" || collision.gameObject.tag == "EnemyBullet")
        {
            if (isHit)
            {
                return;
            }
            isHit = true;
            life--;
            manager.UpdateLifeIcon(life);

            if(life == 0)
            {
                manager.GameOver();
            }
            else
            {
                manager.RespawnPlayer();
            }
            gameObject.SetActive(false);
        }
        else if(collision.gameObject.tag == "Item")
        {
            Item item = collision.gameObject.GetComponent<Item>();
            switch(item.type)
            {
                case "Coin":
                    score += 1000;
                    break;
                case "Power":
                    if(power == maxPower)
                    {
                        score += 500;
                    }
                    else
                    {
                        power++;
                    }
                    break;
                case "Boom":
                    if (boom == maxBoom)
                    {
                        score += 500;
                        
                    }
                    else
                        boom++;
                        manager.UpdateBoomIcon(boom);
                    break;
            }
            Destroy(collision.gameObject);
        }
    }

    void OffBoomSkill()
    {
        boomSkill.SetActive(false);
        isBoomTime = false;
    }

    private void OnTriggerExit2D(Collider2D collision)
    {
        switch (collision.gameObject.name)
        {
            case "Top":
                isTouchTop = false;
                break;
            case "Bottom":
                isTouchBottom = false;
                break;
            case "Right":
                isTouchRight = false;
                break;
            case "Left":
                isTouchLeft = false;
                break;
        }
    }
}

 

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

public class Bullet : MonoBehaviour
{
    public int dmg;
    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.gameObject.tag == "BorderBullet")
        Destroy(gameObject); //모노비헤이어에 들어 있는 자체 함수 => 매개변수 오브젝트를 삭제하는 함수
    }
}

 

using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.Design;
using UnityEngine;

public class Enemy : MonoBehaviour
{
    public string enemyName;
    public int enemyScore;
    public float speed;
    public int health;
    public Sprite[] sprites;

    public float maxShotDelay; //실제 딜레이
    public float curShorDelay; //한발 쏜 후 딜레이

    public GameObject bulletObjA;
    public GameObject bulletObjB;
    public GameObject itemCoin;
    public GameObject itemPower;
    public GameObject itemBoom;
    public GameObject player;

    SpriteRenderer spriteRenderer;
    Rigidbody2D rigid;

    private void Awake()
    {
        spriteRenderer = GetComponent<SpriteRenderer>();
        rigid = GetComponent<Rigidbody2D>();
        rigid.velocity = Vector2.down * speed;
    }
    private void Update()
    {
        Fire();
        Reload();
    }
    void Fire()
    {
        if (curShorDelay < maxShotDelay)
            return;

        if (enemyName == "S")
        {
            GameObject bullet = Instantiate(bulletObjA, transform.position, transform.rotation);
            Rigidbody2D rigid = bullet.GetComponent<Rigidbody2D>();
            Vector3 dirVec = player.transform.position - transform.position;
            rigid.AddForce(dirVec.normalized * 3, ForceMode2D.Impulse);  // 방향 벡터를 정규화하여 힘을 가하는 부분 수정
        }
        else if (enemyName == "L")
        {
            GameObject bulletR = Instantiate(bulletObjB, transform.position + Vector3.right * 0.3f, transform.rotation);
            GameObject bulletL = Instantiate(bulletObjB, transform.position + Vector3.left * 0.3f, transform.rotation);
            Rigidbody2D rigidR = bulletR.GetComponent<Rigidbody2D>();
            Rigidbody2D rigidL = bulletL.GetComponent<Rigidbody2D>();
            Vector3 dirVecR = player.transform.position - (transform.position + Vector3.right * 0.3f);
            Vector3 dirVecL = player.transform.position - (transform.position + Vector3.left * 0.3f);
            rigidR.AddForce(dirVecR.normalized * 4, ForceMode2D.Impulse);  // 방향 벡터를 정규화하여 힘을 가하는 부분 수정
            rigidL.AddForce(dirVecL.normalized * 4, ForceMode2D.Impulse);  // 방향 벡터를 정규화하여 힘을 가하는 부분 수정
        }

        curShorDelay = 0;  // 발사 후 딜레이 초기화는 발사 이후에 처리되도록 이동
    }

    void Reload()
    {
        curShorDelay += Time.deltaTime;

    }
    public void OnHit(int dmg)
    {
        if (health <= 0)
            return;
        health -= dmg;
        spriteRenderer.sprite = sprites[1]; //피격시 1번
        Invoke("ReturnSprite", 0.1f);
        if (health <= 0)
        {
            Player playerLogic = player.GetComponent<Player>();
            playerLogic.score += enemyScore;

            //#.Random.Ratio Item Drop
            int ran = Random.Range(0, 10);
            if (ran < 3)
            {
                Debug.Log("No Item");
            }
            else if (ran < 6) { //Coin 30%
                Instantiate(itemCoin, transform.position, itemCoin.transform.rotation);
            }else if (ran < 8) { //Power 20%
                Instantiate(itemPower, transform.position, itemPower.transform.rotation);
            }else if(ran < 10) { //Boom 20%
                Instantiate(itemBoom, transform.position, itemBoom.transform.rotation);
            }



            Destroy(gameObject);
        }
    }

    void ReturnSprite()
    {
        spriteRenderer.sprite = sprites[0];
    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if(collision.gameObject.tag == "BorderBullet")
        {
            Destroy(gameObject );
        }
        else if(collision.gameObject.tag == "PlayerBullet")
        {
            Bullet bullet = collision.gameObject.GetComponent<Bullet>();
            OnHit(bullet.dmg);
            Destroy(collision.gameObject);
        }
    }

}

 

using JetBrains.Annotations;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class GameManager : MonoBehaviour
{
    public GameObject[] enemyObjs;
    public Transform[] spawnPoints;

    public float maxSpawnDelay;
    public float curSpawnDelay;

    public GameObject player;
    public Text scoreText;
    public Image[] lifeImage;
    public Image[] boomImage;
    public GameObject gameOverSet;
    private void Update()
    {
        curSpawnDelay += Time.deltaTime;

        if (curSpawnDelay > maxSpawnDelay)
        {
            SpawnEnemy();
            maxSpawnDelay = Random.Range(0.5f, 3f);
            curSpawnDelay = 0;
        }

        //UI Score

        Player playerLogic = player.GetComponent<Player>();
        scoreText.text = string.Format("{0:n0}", playerLogic.score);



    }
    void SpawnEnemy()
    {
        int ranEnemy = Random.Range(0, 3); //소환될 적
        int ranPoint = Random.Range(0, 9); //소환될 위치
        GameObject enemy = Instantiate(enemyObjs[ranEnemy],
                                        spawnPoints[ranPoint].position,
                                        spawnPoints[ranPoint].rotation);
        Rigidbody2D rigid = enemy.GetComponent<Rigidbody2D>();
        //스피드도 가지고 와야한다.
        Enemy enemyLogic = enemy.GetComponent<Enemy>();
        //적비행기 생성 직후 플레이에 변수를 넘겨준다.
        enemyLogic.player = player;
        if (ranPoint == 5 || ranPoint == 6)
        {
            enemy.transform.Rotate(Vector3.back * 90); //z축으로 90도
            rigid.velocity = new Vector2(enemyLogic.speed * (-1), -1);
        }else if(ranPoint == 7 || ranPoint == 8)
        {
            enemy.transform.Rotate(Vector3.forward * 90); //z축으로 90도
            rigid.velocity = new Vector2(enemyLogic.speed, -1);
        }
        else
        {
            rigid.velocity = new Vector2(0, enemyLogic.speed * (-1));
        }
    }

    public void UpdateLifeIcon(int life)
    {
        //UI Init Disable
        for (int index = 0; index < 3; index++)
        {
            lifeImage[index].color = new Color(1, 1, 1, 0);
        }
        //UI Life Active
        for (int index = 0; index < life; index++)
        {
            lifeImage[index].color = new Color(1, 1, 1, 1);
        }
    }


    public void UpdateBoomIcon(int boom)
    {
        //UI Init Disable
        for (int index = 0; index < 3; index++)
        {
            boomImage[index].color = new Color(1, 1, 1, 0);
        }
        //UI Life Active
        for (int index = 0; index < boom; index++)
        {
            boomImage[index].color = new Color(1, 1, 1, 1);
        }
    }

    public void RespawnPlayer()
    {
        Invoke("RespawnPlayerExe", 2f);
        
    }
    private void RespawnPlayerExe()
    {
        player.transform.position = Vector3.down * 3.5f;
        player.SetActive(true);

        Player playerLogic = player.GetComponent<Player>();
        playerLogic.isHit = false;
    }
    public void GameOver()
    {
        gameOverSet.SetActive(true);
    }

    public void GameRetry()
    {
        SceneManager.LoadScene(0);
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Item : MonoBehaviour
{
    public string type;
    private Rigidbody2D rigid;


    void Start()
    {
        rigid = GetComponent<Rigidbody2D>();
        rigid.velocity = Vector3.down * 3f; //아이템이 떨어지는 속도
    }

    void Update()
    {
        
    }
}

적 비행기가 피격시 스프라이트 랜더러를 사용해

2가지 이미지로

피격시 화면이 바뀌고 정해진 시간후에 다시 원래모습으로 돌아오게 한다.

 

애니메이션을 추가하여 적비행기가 체력이 다 닳을시 폭파하는 애니메이션을 추가하였다.

폭발 애니메이션은 구현하였지만

스프라이트 렌더러에 저장했던 이미지는 불러와지지 않는다.

 

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

public class Enemy : MonoBehaviour
{
    public float speed;
    public int health;
    public Sprite[] sprites;
    private Animator anim;

    SpriteRenderer spriteRenderer;
    Rigidbody2D rigid;

    void Start()
    {
        spriteRenderer = GetComponent<SpriteRenderer>();
        rigid = GetComponent<Rigidbody2D>();
        rigid.velocity = Vector2.down * speed;

        anim = GetComponent<Animator>();
    }

    void ReturnSprite()
    {
        spriteRenderer.sprite = sprites[0];
    }

    public void OnHit(int dmg)
    {
        health -= dmg;
        spriteRenderer.sprite = sprites[1];
        Invoke("ReturnSprite", 0.1f);

        if (health <= 0)
        {
            anim.SetBool("EnemyDie", true);

            Destroy(gameObject, 0.2f);
        }
    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.gameObject.tag == "BorderBullet")
        {
            Destroy(gameObject);
        }
        else if (collision.gameObject.tag == "Bullet")
        {
            Bullet bullet = collision.gameObject.GetComponent<Bullet>();
            OnHit(bullet.dmg);
            Destroy(collision.gameObject);
        }
    }
}

 

Enemy컨트롤러를 체크한 후 auto live link로 실행이 잘 되는지 확인했다.

죽었을때 폭발 애니메이션은 정상적으로 진행하고 있었다.

 

실행 순서에 문제가 있나 확인하기 위해 Unity LifeCycle을 찾아보았다.

https://docs.unity3d.com/kr/current/Manual/ExecutionOrder.html

 

이벤트 함수의 실행 순서 - Unity 매뉴얼

Unity 스크립트를 실행하면 사전에 지정한 순서대로 여러 개의 이벤트 함수가 실행됩니다. 이 페이지에서는 이러한 이벤트 함수를 소개하고 실행 시퀀스에 어떻게 포함되는지 설명합니다.

docs.unity3d.com

 

해결 방법으로 Explosion 자체를 프리팹으로 만들어서 프리팹을 불러오며

그 프리팹이 실행되고 나서 비행기를 파괴시켰다.

 

폭발 애니메이션

 

빈 오브젝트에 스크립트와 애니메이션 컨트롤러를 넣고 프리팹화를 진행하였다.

 

폭발 스크립트에 코루틴이 돌아가게 했고 0.5초 후에 폭발(게임오브젝트) 파괴

 

적 스크립트

우선 폭발 프리팹을 가지고 있어야 하므로 선언

public GameObject explosionPrefab;

 

체력이 0이하 일시 폭발을 만들어주었고 폭발 효과 시간을 지정하였다.

 

완성된 모습

 

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

public class PlayerController : MonoBehaviour
{
    public float speed = 3f;
    public bool isTouchTop;
    public bool isTouchLeft;
    public bool isTouchRight;
    public bool isTouchBottom;

    public float maxShortDelay = 0.1f;//실제 딜레이
    public float curShortDelay;//한발 쏜 딜레이
    
    public GameObject bulletObjA;
    private Animator anim;
    void Start()
    {
        anim = GetComponent<Animator>();
    }

    void Update()
    {
        Move();
        Fire();
        Reload();
    }

    void Move()
    {
        Vector3 curPos = this.transform.position;
        float h = Input.GetAxisRaw("Horizontal");
        if ((isTouchRight && h == 1) || (isTouchLeft && h == -1))
            h = 0;
        float v = Input.GetAxisRaw("Vertical");
        if ((isTouchTop && v == 1) || (isTouchBottom && v == -1))
            v = 0;
        Vector3 nextPos = new Vector3(h, v, 0) * speed * Time.deltaTime;
        this.transform.position = curPos + nextPos;

        if(Input.GetButtonDown("Horizontal") || Input.GetButtonDown("Vertical"))
        {
            anim.SetInteger("Input", (int)h);
        } 
    }

    void Fire()
    {   
        if (curShortDelay < maxShortDelay)
            return;
        if (Input.GetKey(KeyCode.Space))
        {
           
            GameObject bullet = Instantiate(bulletObjA, transform.position, transform.rotation);
            Rigidbody2D rigid = bullet.GetComponent<Rigidbody2D>();
            rigid.AddForce(Vector2.up * 10, ForceMode2D.Impulse);

            curShortDelay = 0f;
        }
    }
    
    void Reload()
    {
        curShortDelay += Time.deltaTime;
    }


    private void OnTriggerEnter2D(Collider2D collision)
    {
        if(collision.gameObject.tag == "Border")
        {
            switch (collision.gameObject.name)
            {
                case "Top":
                    isTouchTop = true;
                    break;
                case "Bottom":
                    isTouchBottom = true;
                    break;
                case "Left":
                    isTouchLeft = true;
                    break;
                case "Right":
                    isTouchRight = true;
                    break;
            }
        }
    }

    private void OnTriggerExit2D(Collider2D collision)
    {
        switch (collision.gameObject.name)
        {
            case "Top":
                isTouchTop = false;
                break;
            case "Bottom":
                isTouchBottom = false;
                break;
            case "Left":
                isTouchLeft = false;
                break;
            case "Right":
                isTouchRight = false;
                break;
        }
    }
}

 

 

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

public class Bullet : MonoBehaviour
{
    public int dmg;
    private void OnTriggerEnter2D(Collider2D collision)
    {
        if(collision.tag == "BorderBullet")
        {
            Destroy(gameObject);
        }
    }
}

 

 

 

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

public class Enemy : MonoBehaviour
{
    public float speed;
    public int health;
    public Sprite[] sprites;

    SpriteRenderer spriteRenderer;
    Rigidbody2D rigid;
    public GameObject explosionPrefab;
    void Start()
    {
        spriteRenderer = GetComponent<SpriteRenderer>();
        rigid = GetComponent<Rigidbody2D>();
        rigid.velocity = Vector2.down * speed;

    }

    void ReturnSprite()
    {
        spriteRenderer.sprite = sprites[0];
    }

    public void OnHit(int dmg)
    {
        health -= dmg;
        spriteRenderer.sprite = sprites[1];
        Invoke("ReturnSprite", 0.1f);
        if (health <= 0)
        {
            GameObject explosion = Instantiate(explosionPrefab, transform.position, Quaternion.identity);
            Destroy(explosion, 1.0f); // 폭발 효과는 1초 후에 파괴
            Destroy(gameObject); // 적도 파괴
            //Destroy(gameObject, 0.2f);
        }
    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.gameObject.tag == "BorderBullet")
        {
            Destroy(gameObject);
        }
        else if (collision.gameObject.tag == "Bullet")
        {
            Bullet bullet = collision.gameObject.GetComponent<Bullet>();
            OnHit(bullet.dmg);
            Destroy(collision.gameObject);
        }
    }
}

 

 

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

public class GameManager : MonoBehaviour
{
    public GameObject[] enemyObjs;
    public Transform[] spawnPoints;

    public float maxSpawnDelay;
    public float curSpawnDelay;

    void Update()
    {
        curSpawnDelay += Time.deltaTime;

        if(curSpawnDelay > maxSpawnDelay)
        {
            SpawnEnemy();
            maxSpawnDelay = Random.Range(0.5f, 3f);
            curSpawnDelay = 0;
        }
    }

    void SpawnEnemy()
    {
        int ranEnemy = Random.Range(0, 3);
        int ranPoint = Random.Range(0, 5);

        Instantiate(enemyObjs[ranEnemy],
            spawnPoints[ranPoint].position,
            spawnPoints[ranPoint].rotation);
    }
}

 

 

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

public class Explosion : MonoBehaviour
{
    private Animator anim;


    public void OnEnable()
    {
        anim = GetComponent<Animator>();
        StartCoroutine(CoExplosion());
    }

    IEnumerator CoExplosion()
    {
        yield return new WaitForSeconds(0.5f);
        Destroy(gameObject);
    }
}

+ Recent posts