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

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