✍ 아이템 준비
- 아이템을 스프라이트로 배치한 후 , 필요한 컴포넌트를 추가한다.
- 아이템들의 애니메이션 적용과 , tag를 만들어 적용
✍ 아이템 충돌로직
- 아이템을 먹었을 때 아이템의 Type에 따라 작동하는 걸 switch문으로 작성
else if(collision.gameObject.tag == "Item")
{
Item item = collision.gameObject.GetComponent<Item>();
string itemtype = item.type;
switch(itemtype)
{
case "Coin":
score += 1000;
break;
case "Power":
if (power == maxPower)
score += 500;
else
power++;
break;
case "Boom":
if (boom == maxBoom)
score += 500;
else
{
boom++;
gameManager.UpdateBoom(boom);
}
break;
}
Destroy(collision.gameObject);
}
✍ 필살기
- 필살기는 적과 플레이어를 가리면 안되므로 Order in Layer를 적절히 설정
- 필살기 스프라이트를 추가한 후 안보이게 꺼두자. -> 필살기 사용 할 때 SetActive(true)
FindGameObjectsWithTag
- 맞는 태그의 모든 오브젝트를 추출
- GameObject.FindGameObjectsWithTag("Enemy");로 설정해주면 Scene에 존재하는 모든 Enemy 태그가 배열에 저장됨.
- FindGameObjectsWithTag를 이용해 모든 적과 적의 총알을 배열들로 가져온다.
- 가져온 후 , Enemy는 onDamaged함수를 실행시켜 파괴시키고,
EnemyBullet은 Destroy시킨다.
//#1. Effect visible
boomEffect.SetActive(true);
Invoke("OffBoomEffect", 3f);
//#2. Remove Enemy
GameObject[] enemies = GameObject.FindGameObjectsWithTag("Enemy");
for (int i = 0; i < enemies.Length; i++)
{
Enemy enemyLogic = enemies[i].GetComponent<Enemy>();
enemyLogic.onDamaged(1000);
}
//#3. Remove Enemy Bullet
GameObject[] bullets = GameObject.FindGameObjectsWithTag("EnemyBullet");
for (int i = 0; i < bullets.Length; i++)
Destroy(bullets[i]);
- 필살기 스프라이트는 Invoke로 시간차 비활성화
- 필살기도 power와 같이 개수를 정하고, Life처럼 UI로 나타냄.
✍ 아이템 드랍
- 적을 처치했을 때 랜덤한 확률로 아이템이 드랍되게 구현
// # Item Drop
int ran = Random.Range(0, 10);
if (ran < 3) // 30%
Debug.Log("Not Item");
else if (ran < 6) // 30% coin
Instantiate(itemCoin, transform.position, itemCoin.transform.rotation);
else if (ran < 8) // 20% power
Instantiate(itemPower, transform.position, itemPower.transform.rotation);
else if (ran < 10) // 20% boom
Instantiate(itemBoom, transform.position, itemBoom.transform.rotation);
Random.Range()
- int형이면 min에서 max-1값까지
- float형이면 min에서 max값까지 (꼭 숫자옆에f를 붙여주자)
✍ 전체코드
1. Player.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
public bool isTouchTop;
public bool isTouchBottom;
public bool isTouchLeft;
public bool isTouchRight;
public int score;
public int health;
public float speed;
public int boom;
public int maxBoom;
public int power;
public int maxPower;
public float curShotDelay;
public float maxShotDelay;
public bool isHit;
public bool isBoom;
public GameObject boomEffect;
public GameManager gameManager;
public GameObject BulletA;
public GameObject BulletB;
Animator anim;
private void Awake()
{
anim = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
Move();
Fire();
Reload();
Boom();
}
void Boom()
{
if (!Input.GetButton("Fire2"))
return;
if (isBoom)
return;
if (boom == 0)
return;
boom--;
isBoom = true;
gameManager.UpdateBoom(boom);
//#1. Effect visible
boomEffect.SetActive(true);
Invoke("OffBoomEffect", 3f);
//#2. Remove Enemy
GameObject[] enemies = GameObject.FindGameObjectsWithTag("Enemy");
for (int i = 0; i < enemies.Length; i++)
{
Enemy enemyLogic = enemies[i].GetComponent<Enemy>();
enemyLogic.onDamaged(1000);
}
//#3. Remove Enemy Bullet
GameObject[] bullets = GameObject.FindGameObjectsWithTag("EnemyBullet");
for (int i = 0; i < bullets.Length; i++)
Destroy(bullets[i]);
}
void Reload()
{
curShotDelay += Time.deltaTime;
}
void Fire()
{
if (!Input.GetButton("Fire1")) // Fire1은 마우스좌클릭
return;
if (curShotDelay < maxShotDelay)
return;
switch(power)
{
case 1:
// Power 1
GameObject Bullet = Instantiate(BulletA, transform.position, transform.rotation);
Rigidbody2D rigid = Bullet.GetComponent<Rigidbody2D>();
rigid.AddForce(Vector2.up * 10, ForceMode2D.Impulse);
break;
case 2:
// Power 2
GameObject BulletR = Instantiate(BulletA, transform.position + Vector3.right*0.1f, transform.rotation);
GameObject BulletL = Instantiate(BulletA, 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:
// Power 3
GameObject BulletRR = Instantiate(BulletA, transform.position + Vector3.right*0.35f, transform.rotation);
GameObject BulletCC = Instantiate(BulletB, transform.position, transform.rotation);
GameObject BulletLL = Instantiate(BulletA, transform.position + Vector3.left*0.35f, 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;
}
curShotDelay = 0;
}
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 = transform.position;
Vector3 nextPos = new Vector3(h, v, 0) * speed * Time.deltaTime;
transform.position = curPos + nextPos;
// Animation
if (Input.GetButtonUp("Horizontal") || Input.GetButtonDown("Horizontal"))
{
anim.SetInteger("Input", (int)h);
}
}
public 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;
}
}
else if(collision.gameObject.tag == "Enemy" || (collision.gameObject.tag == "EnemyBullet"))
{
if (isHit)
return;
isHit = true;
health--;
gameManager.UpdateLife(health);
if (health == 0)
gameManager.GameOver();
else
gameManager.RespawnPlayer();
gameObject.SetActive(false);
Destroy(collision.gameObject);
}
else if(collision.gameObject.tag == "Item")
{
Item item = collision.gameObject.GetComponent<Item>();
string itemtype = item.type;
switch(itemtype)
{
case "Coin":
score += 1000;
break;
case "Power":
if (power == maxPower)
score += 500;
else
power++;
break;
case "Boom":
if (boom == maxBoom)
score += 500;
else
{
boom++;
gameManager.UpdateBoom(boom);
}
break;
}
Destroy(collision.gameObject);
}
}
void OffBoomEffect()
{
boomEffect.SetActive(false);
isBoom = false;
}
private void OnTriggerExit2D(Collider2D collision)
{
if (collision.gameObject.tag == "Border")
{
switch (collision.gameObject.name)
{
case "Top":
isTouchTop = false;
break;
case "Bottom":
isTouchBottom = false;
break;
case "Left":
isTouchLeft = false;
break;
case "Right":
isTouchRight = false;
break;
}
}
}
}
2. GameManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using UnityEngine;
public class GameManager : MonoBehaviour
{
public GameObject[] enemyObjs;
public Transform[] spawnPoints;
public GameObject player;
public float maxSpawnDelay;
public float curSpawnDelay;
public Text scoreText;
public Image[] lifeImage;
public Image[] boomImage;
public GameObject gameOverSet;
void Update()
{
curSpawnDelay += Time.deltaTime;
if(curSpawnDelay > maxSpawnDelay)
{
SpawnEnemy();
maxSpawnDelay = Random.Range(0.5f, 3f);
curSpawnDelay = 0;
}
// UI Score Update
Player playerLogic = player.GetComponent<Player>();
scoreText.text = string.Format("{0:n0}", playerLogic.score);
}
void SpawnEnemy()
{
int randomEnemy = Random.Range(0, 3);
int spawnPoint = Random.Range(0, 7);
GameObject enemy = Instantiate(enemyObjs[randomEnemy], spawnPoints[spawnPoint].position, spawnPoints[spawnPoint].rotation);
Rigidbody2D rigid = enemy.GetComponent<Rigidbody2D>();
Enemy enemyLogic = enemy.GetComponent<Enemy>();
enemyLogic.player = player;
if(spawnPoint == 5) // Left Spawn
{
enemy.transform.Rotate(Vector3.forward * 90);
rigid.velocity = new Vector2(1, -enemyLogic.speed);
}
else if(spawnPoint == 6) // Right Spawn
{
enemy.transform.Rotate(Vector3.back * 90);
rigid.velocity = new Vector2(-1, -enemyLogic.speed);
}
else // Front Spawn
{
rigid.velocity = new Vector2(0, -enemyLogic.speed);
}
}
public void RespawnPlayer()
{
Invoke("RespawnPlayerExe", 2f);
}
public void RespawnPlayerExe()
{
Player playerLogic = player.GetComponent<Player>();
playerLogic.isHit = false;
player.transform.position = Vector3.down * 4f;
player.SetActive(true);
}
public void UpdateLife(int Life)
{
// #. UI Init Disable
for (int i = 0; i < 3; i++)
lifeImage[i].color = new Color(1, 1, 1, 0);
// #. Life Active
for (int i = 0; i < Life; i++)
lifeImage[i].color = new Color(1, 1, 1, 1);
}
public void UpdateBoom(int boom)
{
// #. UI Init Disable
for (int i = 0; i < 3; i++)
boomImage[i].color = new Color(1, 1, 1, 0);
// #. Life Active
for (int i = 0; i < boom; i++)
boomImage[i].color = new Color(1, 1, 1, 1);
}
public void GameOver()
{
gameOverSet.SetActive(true);
}
public void Retry()
{
SceneManager.LoadScene(0);
}
}
3. Item.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Item : MonoBehaviour
{
public string type;
Rigidbody2D rigid;
void Awake()
{
rigid = GetComponent<Rigidbody2D>();
rigid.velocity = Vector2.down * 1;
}
}
4. Bullet.cs
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);
}
}
}
5. Enemy.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy : MonoBehaviour
{
public string enemyName;
public float speed;
public int enemyScore;
public int health;
public float curShotDelay;
public float maxShotDelay;
public Sprite[] sprites;
public GameObject BulletA;
public GameObject BulletB;
public GameObject itemCoin;
public GameObject itemPower;
public GameObject itemBoom;
public GameObject player;
SpriteRenderer spriteRenderer;
void Awake()
{
spriteRenderer = GetComponent<SpriteRenderer>();
}
void Update()
{
Fire();
Reload();
}
void Reload()
{
curShotDelay += Time.deltaTime;
}
void Fire()
{
if (curShotDelay < maxShotDelay)
return;
if(enemyName == "S")
{
GameObject Bullet = Instantiate(BulletA, transform.position, transform.rotation);
Rigidbody2D rigid = Bullet.GetComponent<Rigidbody2D>();
Vector3 dirVec = player.transform.position - transform.position;
rigid.AddForce(dirVec.normalized * 10, ForceMode2D.Impulse);
}
else if(enemyName == "L")
{
GameObject BulletR = Instantiate(BulletB, transform.position + Vector3.right * 0.3f, transform.rotation);
GameObject BulletL = Instantiate(BulletB, 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);
}
curShotDelay = 0;
}
public void onDamaged(int dmg)
{
if (health <= 0)
return;
health -= dmg;
spriteRenderer.sprite = sprites[1];
Invoke("ReturnSprite", 0.1f);
if (health <= 0)
{
Player playerLogic = player.GetComponent<Player>();
playerLogic.score += enemyScore;
// # Item Drop
int ran = Random.Range(0, 10);
if (ran < 3) // 30%
Debug.Log("Not Item");
else if (ran < 6) // 30% coin
Instantiate(itemCoin, transform.position, itemCoin.transform.rotation);
else if (ran < 8) // 20% power
Instantiate(itemPower, transform.position, itemPower.transform.rotation);
else if (ran < 10) // 20% boom
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>(); // collision.gameObject에서 GetComponent한다
onDamaged(bullet.dmg);
Destroy(collision.gameObject);
}
}
}
출처 - https://www.youtube.com/c/GoldMetal