적 비행기가 피격시 스프라이트 랜더러를 사용해
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
해결 방법으로 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);
}
}