일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 드로잉
- 개발
- 모작
- 서포터즈
- layer
- 애니메이션
- menu
- 스마일게이트
- photoshop
- 인디게임 개발
- 자원순환보증금관리센터
- 노하우
- 포토샵
- COSMO
- pixel art
- 연습
- Pixelart
- TOOL
- 반환원정대
- 에이세프라이트
- Aseprite
- 기초
- 도트공부
- 픽셀 아트
- 멋쟁이사자처럼
- 장학팀
- 도트
- 채색
- 드로잉 연습
- 픽셀아트
- Today
- Total
소소한 나의 하루들
2d 종스크롤 슈팅(3) - 적 비행기 만들기 본문
출처: https://youtube.com/playlist?list=PLO-mt5Iu5TeYI4dbYwWP8JqZMC9iuUIW2&feature=shared
이전에는 플레이어 비행기가 총알을 쏘는 것을 구현했는데, 이번에는 총알을 맞아주는 적 비행기 시스템을 구현해본다.
#1. 준비하기
제공받은 에셋의 sprite 설정을 해본다. 2d 도트그래픽이니까 Pixels per Units은 기준 크기에 맞게 24, Filter Mode는 Point (no filter), Compression은 None으로 설정한다. 그리고 sprite 크기가 다 다르므로 Sprite Editor에서 slice는 Automatic으로 설정하고 slice해준다. 설정이 끝나면 Apply까지 꼭 한다.
적용까지 끝났으면 에셋의 적 비행기 sprite를 찾아서 Scene에 배치해본다. 플레이어가 쏜 총알에 맞았을 때 트리거 이벤트를 위해서 콜라이더 컴포넌트를 생성한다.
적 비행기 sprite 중 세모 모양의 날렵한 비행기는 Box Collider 2D 컴포넌트를 적용하면, 앞쪽에 남는 빈 공간이 생겨버린다. 그래서 우리가 원하는 모양을 만들기 위한 콜라이더인 Polygon Collider 2D 컴포넌트를 적용한다. 그리고 살짝 큰 히트박스를 Sprite Editor에서 조절해준다.
Sprite Editor에서 Custom Physics Shape를 선택해주고, 조정해주고자하는 sprite를 선택한 뒤 Generate를 클릭한다.
*Sprite Editor창에서 Generate 버튼이 안보이면 창 크기를 키워준다.
*스프라이트는 기본적으로 Physics Shape를 가지고 있다. 폴리곤 콜라이더 모양은 Physics Shape를 따라간다.
스프라이트 히트박스를 조절해줬으면 Apply 한 다음, 기존에 있던 해당 오브젝트를 지운 뒤 다시 수정한 sprite를 Scene에 추가해주고 Polygon Collider 2D 컴포넌트도 추가해주면 수정된 히트박스가 새로 적용된다.
적 비행들도 움직이는 속도가 있으니까 Rigidbody 2D 컴포넌트를 추가하고 Gravity Scale을 0으로 설정한다. Tag도 추가해준다. (Enemy)
#2. 적 기체 프리펩
적 비행기의 행동을 관리해줄 수 있게 Enemy 스크립트도 생성하고 적 비행기 오브젝트들에 컴포넌트로 추가해준다.
public class Enemy : MonoBehaviour
{
public float speed;
public int health;
public Sprite[] sprites;
SpriteRenderer spriteRenderer;
Rigidbody2D rigid;
}
적 비행기에게 필요한 것은 무엇일까? 우선 speed도 필요하고, 몇번을 맞아야 죽는지 health도 필요할 것이다. 속력도 바꿔야하기 때문에 Rigidbody 2D도 추가하고, 죽을 때 모습도 바꿀 것이기 때문에 SpriteRender 컴포넌트도 추가한다. SpriteRenderer에서 Sprite도 바꾸려면 sprite도 바꿀 것이기 때문에 Sprite도 있어야한다.
: 적 비행기의 구성 요소를 변수로 구체화한다.
rigidbody.AddForce() 와 rigidbody.velocity 차이
https://unitybeginner.tistory.com/24
rigidbody.AddForce()는 같은 힘을 연속해서 가하면 점점 가속도가 붙는다. [등가속 운동]
rigidbody.velocity는 같은 힘을 가해도 동일한 속도로 달릴 수 있도록 물리엔진이 자동으로 계산해준다. [등속운동]
private void Awake()
{
spriteRenderer = GetComponent<SpriteRenderer>();
rigid = GetComponent<Rigidbody2D>();
rigid.velocity = Vector3.down * speed;
}
초기화까지 해줬으면, 적 비행기들이 할 일은 플레이어의 총알을 맞아주는 역할이다.
private void OnHit(int damage)
{
health -= damage;
if (health <= 0)
Destroy(gameObject);
}
플레이어 총알의 데미지만큼 피가 깎이는 함수 OnHit()을 만들어준다. 적 비행기의 피(health)가 0보다 작거나 같게되면 = 파괴된다.
이제 적 비행기가 플레이어 총알에 피격당했을 때의 상태를 색상으로 표현한다. 보통 게임에서 피격당했을 때 순간적으로 색상이 살짝 불투명해지거나 하얀색으로 바뀐다. 그것을 구현해본다.
평소 스프라이트는 0, 피격 시 스프라이트는 1로 바꿔준다.
private void OnHit(int damage)
{
health -= damage;
spriteRenderer.sprite = sprites[1];
//ReturnSprite(); //이렇게 하면 1프레임 내에서 즉시 다시 원래 sprite[0]으로 바꾸기 때문에 실제로 바뀌지 않은 것처럼 보인다
Invoke("ReturnSprite", 0.1f);
if (health <= 0)
Destroy(gameObject);
}
void ReturnSprite()
{
spriteRenderer.sprite = sprites[0];
}
※이렇게 코드를 작성하게되면 1프레임 내에 피격당해 sprite[1]로 바뀌었다가 다시 sprite[0]으로 돌아오기 때문에 게임 내에서는 피격당했을 때에 이미지가 그대로 유지되는 것처럼 보인다.
따라서 바꾼 스프라이트를 돌리기 위해 시간차 함수를 호출한다.
//Enemy
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.damage);
}
}
//Bullet
public class Bullet : MonoBehaviour
{
public int damage;
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.tag == "BorderBullet")
{
Destroy(gameObject);
}
}
}
이제 OnTriggerEnter2D()를 통해 이벤트 로직을 작성한다. 적 비행기가 플레이어를 지나가서 (총알과 마찬가지로) 바깥으로 나간 후에는 (총알 경계지점을 만나면) 삭제한다.
그리고 적 비행기가 플레이어가 쏜 총알을 맞았을 때의 이벤트를 구현하기 위해 우선 총알 프리펩에는 "PlayerBullet" 태그를 달아준다. 적 비행기가 아직 총알 경계지점을 만나지 않았을 때 적 비행기가 총알에 맞으면 피가 닳고, 체력이 0 이하면 제거되는 OnHit() 함수를 실행시켜준다.
호출하면서 OnHit()에 총알의 데미지를 전달해줘야한다.
스크립트 작성이 끝나면, 이제 실행하기 전에 적 비행기의 체력(health)과 속도(speed), 총알의 데미지(프리펩 A/B) 값을 입력해줘야한다. 그리고 피격당했을 때 sprite와 피격당하지 않을 때 sprite도 적용시켜준다.
: public으로 설정한 변수들의 초기값을 잊지말고 꼭 작성해줘야한다.
※적끼리 충돌을 막기위해 콜라이더의 Is Trigger 옵션을 체크해준다.
*이번 프로젝트는 Dynamic 물리 충돌을 거의 활용하지 않는다.
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.damage);
//collision.gameObject.SetActive(false);
Destroy(collision.gameObject);
}
}
적 비행기가 피격 시 플레이어 총알을 삭제하는 로직을 추가한다.
스크립트 작성이 다 끝났으면, 적 비행기 오브젝트들을 프리펩으로 저장한다. 그리고 저장이 끝나면 Scene에서 적 비행기 오브젝트들은 삭제해준다.
*프리펩으로 저장한 후에는 Transform이 Scene에 배치했던 좌표로 저장되기 때문에 Transform을 0으로 초기화해준다.
#3. 적 비행기 생성
플레이어로부터 총알이 발사된 것처럼 적 비행기 프리펩도 생성해줘야하는데, 어디서 관리해줄까?
이러한 적 생성은 GameManager에서 생성하고 관리해준다. GameManager 오브젝트와 스크립트를 생성해준다.
GameManager에게 필요한 것은 무엇일까?
public class GameManager : MonoBehaviour
{
public GameObject[] ememyObjs;
public Transform[] spawnPoints;
public float maxSpawnDelay;
public float curSpawnDelay;
}
일단 적 비행기 프리펩 3개를 만들었기 때문에, 그것들을 변수화시켜야한다. : 프리펩 변수화
적 비행기 프리펩 오브젝트가 3개이니까 배열로 만들어서 관리해주도록 한다.
그리고 적 비행기 프리펩을 생성시켜줄 위치가 있어야하는데, 5개의 좌표를 잡아서 랜덤하게 소환하도록 한다.
생성 위치 배열 변수를 선언한다. 위치의 타입은 Transform이다. 그리고 처음 총알 발사할때처럼 1초에 60번씩 소환시키면 안된다. 앞에서 총알 발사 시 딜레이를 구현해줬던 것처럼 적 생성 딜레이 변수를 선언해준다. 참고
private void Update()
{
curSpawnDelay += Time.deltaTime;
if (curSpawnDelay > maxSpawnDelay)
{
SpawnEnemy();
maxSpawnDelay = Random.Range(0.5f, 3f);
curSpawnDelay = 0;
}
}
curSpawnDelay에는 항상 Time.DeltaTime을 가산한다. 만약 curSpawnDelay > maxSpawnDelay도바 크다면, 적을 소환한다. 적 생성 후에는 꼭 딜레이 변수를 0으로 초기화한다.
생성 주기를 랜덤하게 잡기 위해 Random 클래스의 Range() 함수를 사용한다.
※RandomRange()는 현재 사용하지 않는 함수이다.
Range() : 정해진 범위 내의 랜덤한 숫자를 반환한다.
*인수로 float형 또는 int형을 받음
void SpawnEnemy()
{
int ranEnemy = Random.Range(0, 3);
int ranPoint = Random.Range(0, 5);
Instantiate(ememyObjs[ranEnemy], spawnPoints[ranPoint].position, spawnPoints[ranPoint].rotation);
}
그리고 소환될 적과 소환될 위치도 랜덤하게 소환한다. 랜덤으로 정해진 적 프리펩과 생성위치로 생성로직을 작성한다.
실행시키기 전에 GameManger에 적 프리펩을 적용시켜주고, Scene에서 빈 오브젝트로 생성위치를 생성한다. 그리고 Scene에서 총알 경계박스 안쪽으로 전체 위치를 y축 방향으로 높여주고, 각 좌표값을 조절해준다.
*이때 빈 오브젝트는 태그 아이콘으로 Scene에서 위치를 확인할 수 있다.
MaxSpawnDelay에 초기값을 넣어주고 실행시키면, 그 이후부터는 랜덤으로 값이 설정되어서 랜덤한 주기로 랜덤한 위치에서 랜덤한 적 비행기가 생성되는 것을 확인할 수 있다.
'개발 > 유니티' 카테고리의 다른 글
2d 종스크롤 슈팅(5) - UI 간단하게 완성하기 (0) | 2024.02.18 |
---|---|
2d 종스크롤 슈팅(4) - 적 전투와 피격 이벤트 만들기 (0) | 2024.02.17 |
2d 종스크롤 슈팅(2) - 총알발사 구현하기 (0) | 2024.02.13 |
2d 종스크롤 슈팅(1) - 플레이어 이동 구현하기 (0) | 2024.02.12 |
탑다운 2d RPG(최종) - 피드백 추가 및 개선사항 (0) | 2024.02.08 |