피격 애니메이션
1. 애니메이터에 Hit 애니메이션 추가
2. Hit Trigger 추가
3. 아래와 같은 트랜지션 흐름
4. Hit 시 트리거 값 변경
void Hit(float damage)
{
anim.SetTrigger("Hit"); // 애니메이션 실행
}
피격 시 이동 멈추기
isMove값을 이용하여 움직이는 상태인지 아닌지 체크한다.
Hit 시 isMove가 true가 되지만 일정 시간 이후 다시 풀려야하므로 코루틴 함수를 사용한다.
void Move()
{
if (isMove == false)
return;
}
void OnMouseDown()
{
StartCoroutine(Hit(1)); // 코루틴 실행 메소드로 변경
}
IEnumerator Hit(float damage)
{
hp -= damage;
isMove = false;
anim.SetTrigger("Hit");
if (hp <= 0)
{
Debug.Log($"몬스터 사망 : {gameObject.name}");
Destroy(gameObject);
}
yield return new WaitForSeconds(0.5f); // 0.5초 대기
isMove = true;
}
문제점
여러번 클릭하면 코루틴이 여러개 실행되기 때문에 움직여버리게 된다.
bool isHit = false;
IEnumerator Hit(float damage)
{
if (isHit)
yield break;
isHit = true;
// Hit 기능
isHit = false;
}
Hit 코루틴이 실행되고 있는지 확인하는 bool 값을 추가해 코루틴 실행 중에는 다음 Hit 코루틴이 실행되지 않도록 했다.
죽음 애니메이션
- 애니메이터에 애니메이션과 트랜지션 추가
- 트리거 추가
- 스크립트 추가
IEnumerator Hit(float damage)
{
if (isHit)
yield break;
isHit = true;
hp -= damage;
isMove = false;
anim.SetTrigger("Hit");
if (hp <= 0)
{
anim.SetTrigger("Death");
yield return new WaitForSeconds(3.0f); // 3초 뒤 파괴
Destroy(gameObject);
yield break; // 죽으면 isMove가 true가 되지 않음
}
yield return new WaitForSeconds(0.5f);
isMove = true;
isHit = false;
}
결과
몬스터 스폰
일정 시간에 따라 랜덤한 지점에 몬스터를 스폰하는 코루틴 함수를 작성하였다.
[SerializeField] GameObject[] monsters;
IEnumerator SpawnRoutine()
{
while (true)
{
var randomIndex = Random.Range(0, monsters.Length);
var randomX = Random.Range(-8, 9);
var randomY = Random.Range(-3, 6);
var createPos = new Vector2(randomX, randomY);
Instantiate(monsters[randomIndex], createPos, Quaternion.identity);
yield return new WaitForSeconds(1f);
}
}
public void OnSpawnMonster()
{
StartCoroutine(SpawnRoutine());
}
결과
코인 스폰
몬스터가 죽었을 때 코인을 스폰하는 기능을 만들었다.
// SpawnManager
public void DropCoin(Vector3 dropPos)
{
Instantiate(coinPrefab, dropPos, Quaternion.identity);
}
몬스터 사망을 처리하는 부분에 코인 스폰 메소드를 실행한다.
// Monster
public SpawnManager spawner;
void Start()
{
spawner = FindFirstObjectByType<SpawnManager>(); // 스폰매니저 컴포넌트를 가지고 있는 첫번째 오브젝트를 찾아서 반환
}
IEnumerator Hit(float damage)
{
// 사망 시 코인 드롭 추가
if (hp <= 0)
{
anim.SetTrigger("Death");
spawner.DropCoin(gameObject.transform.position); // 코인 드롭
yield return new WaitForSeconds(3.0f);
Destroy(gameObject);
yield break;
}
}
레이어 처리
코인이 생성되었을 때, 몬스터들과 부딪혀서 튕겨나가는 문제가 있다. 이를 해결하기 위해 레이어를 사용하였다.
- Add Layer로 Monster, Coin 레이어를 만들어 준 후 몬스터와 코인에 각각 지정해준다.
- Project Settings - Physics 2D - Layer Collision Matrix에서 Monster와 Coin 사이의 물리 작용을 해제해준다.
만약 코인끼리도 부딪히지 않길 원한다면, Coin과 Coin의 체크박스도 해제해주면 된다.
아이템 랜덤 생성
코인 생성 부분을 몬스터와 같이 랜덤하게 아이템 배열에서 추출해서 생성하게 변경한다.
아이템이 떨어질 때 위로 튀어오르며 떨어지도록 AddForce도 추가해주었다.
// Spawner
[SerializeField] GameObject[] items;
public void DropItem(Vector3 dropPos)
{
var randomIndex = Random.Range(0, items.Length);
GameObject item = Instantiate(items[randomIndex], dropPos, Quaternion.identity);
Rigidbody2D itemRb = item.GetComponent<Rigidbody2D>();
itemRb.AddForceX(Random.Range(-2f,2f), ForceMode2D.Impulse);
itemRb.AddForceY(3.0f, ForceMode2D.Impulse);
itemRb.AddTorque(Random.Range(-1.5f,1.5f), ForceMode2D.Impulse);
}
아이템 회전 조절
아이템이 굴러떨어지며 너무 오래 굴러가는 문제가 있다. 이는 RigidBody의 Damping 값을 변경해서 해결할 수 있다.
- Linear Damping : position 관련 제동
- Angular Damping : rotation 관련 제동