호우동의 개발일지

Today :

article thumbnail

구현 목표

보스 패턴 중 부채꼴로 불을 뿜는 보스 패턴을 만들려고 한다.

플레이어의 위치를 인식하고, 일정 시간 동안 부채꼴로 불꽃을 방사한다.
불꽃에 닿은 플레이어는 대미지를 입는다.

목표를 확실히 하기 위해 그림으로 나타내겠다.

기획도
구현할 기획도

위 그림과 같이 불꽃을 부채꼴로 쏜다.
구체적으로 구현해야 하는 것을 생각해 보면

1. 플레이어를 인식
2. 플레이어 방향으로 보스 회전
3. 파티클 활성화하여 충돌 시스템을 이용하여 플레이어에게 대미지
4. 일정 시간 이후 파티클 종료

기존에  있던 파티클 에셋을 약간 변형하는 과정 덕에
파티클 시스템을 조금 공부하는데 도움이 됐다.

 

 


구현 과정

1. 파티클

불 파티클
불 파티클

왼쪽의 이펙트가 내가 사용한 이펙트인데,
최대한 불을 발사하는 것과 최대한 비슷한 것을 이용했다.

파티클 인스펙터
파티클 인스펙터 조절

그리고 위에 있는 수치들은 파티클 시스템에서 내가 조정한 것들만 찍었다.

우선 Duration은 지속시간으로 해당 파티클의 지속시간이다. 
5초간 지속되게 할 것이기 때문에 5초로 잡았다.

Start Speed가 높으면 날아가는 거리가 멀어지기 때문에  적절히 조절해 줬다.

emission에서 방사 조절
불 효과를 주기 위해서 emission을 적절히 조절해줘야한다.

Emission은 여기서 제일 중요한 방사이다. Rate over Time은 초당 나가는 입자 수 이므로
높을수록 입자가 많이 나가 가시성이 높아진다.
그래서 500으로 잡아 프레임 저하가 일어나지 않을 정도로 적절히 잡아줬다.

shape는 부채꼴로 해줄 것이기 때문에 콘 모양으로 잡아주고
 angle은 30으로 일단 대충 잡아줬다.

일단 이렇게 파티클 준비는 끝냈다.

 


2. 오브젝트 세팅

하이어라키를 적절히 배치
하이어라키를 적절히 배치해줘야한다.

만들었던 파티클을 FlameEffect라는 이름으로 변경하여 BlackKnight의 하위 객체로 두었다.
그리고 입에서 발사하는 효과를 주기 위해 위치와 회전을 위와 같이 조절해 주었다.

collision 컴포넌트
파티클 충돌이 가능케함

 Particle System에서 충돌을 가능케 하는 것이다.

Collides With는 어떤 레이어와 충돌할지를 정하는 것인데,
원하는 레이어를 중복해서 체크할 수 있다.
Player와만 충돌할 것이기 때문에 이렇게 설정했다.

그리고 Collider Force는 충돌했을 때의 물리작용인데,
밀려나게는 안 할 것이기에  0으로 설정했다.

Send Collision Messages를 체크해야 OnParticleCollision()으로 충돌이 알려진다.
즉, 체크하지 않으면 스크립트로 제어할 수 없다.

 


3. 스크립트

private IEnumerator Flame(Vector3 location)
    {
        bossState = BossState.attack;
        Vector3 dir = (location - transform.position).normalized;
        Quaternion newRot = Quaternion.LookRotation(dir);
        flameEffect.Play();
        anim.enabled = false;
        while (flameEffect.isPlaying)
        {
            transform.rotation = Quaternion.Slerp(transform.rotation, newRot, Time.deltaTime * speed);
            yield return null;
        }
        anim.enabled = true;
        bossState = BossState.idle;
        Invoke("OnAction", 3);
    }

해당 보스 패턴의 이름은 Flame으로 지었다.
보스 오브젝트에 부착되는 스크립트에 포함되는 핵심 코드이다.

코루틴으로 작성했는데,
파티클 실행 종료 후에 다음 패턴이 실행되어야 하기 때문이다.

그래서 파티클 실행 종료까지 대기할 수 있도록 코루틴을 통해 작성하였다.

매개변수로 플레이어의 위치를 받는다.

이후 (플레이어 위치 - 자기 자신의 위치)를 정규화하여 방향벡터를 구한다.
굳이 정규화해 주는 이유는 동일한 속도로 돌기 위해서이다.

그 방향을 향해 설정해 뒀다 파티클을 재생하여 불꽃을 발사한다.


파티클이 재생되는 동안 방향이 회전시키는데 Slerp를 쓰는 이유는
부드럽게 돌아가는 효과를 주기 위해서이다.

anim.enable = true , false로 애니메이션을 껐다 키는 이유는,
이렇게 안 해주면 회전이 되지 않아서
오류를 해결해 주기 위한 나만의 방법이다.

난 이 방법 말고 다른 방법은 안되더라.

여기 나온 bossState는 현재 보스의 상태를 의미하는 것인데,
해당 스크립트에서는 크게 상관할 필요가 없다.

public class Damagable : MonoBehaviour
{
    private void OnParticleCollision(GameObject other)
    {
        PlayerControl player = other.GetComponent<PlayerControl>();
        if(player != null && player.gameObject.layer == 10)
        {
            player.OnDamaged();
        }
    }
}

해당 클래스는 FlameEffect
즉, 불꽃 파티클 오브젝트에 부착되는 스크립트인데,
아까 말했듯 OnParticleCollision() 파티클과 플레이어가 충돌될 때 호출되는 함수이다.

충돌되는 other 게임오브젝트가 PlayerControl 클래스를 가지고 있고,
그 layer가 10번(Player)이라면 PlayerControl 클래스 안에 있는 OnDamaged라는 함수를 호출한다는 뜻이다.

OnDamaged라는 함수는 그냥 플레이어가 대미지를 받는 함수이다.

 

 


구현 결과

최종 결과
최종 결과

정상적으로 플레이어를 바라보며 불을 뿜고,
불에 닿으면 대미지를 입는 모습을 확인할 수 있다.