게임 개발 공부 기록

54일차 - Abyss_Slayer 최종 팀 프로젝트 4 (아처 스킬 구현)

00lwt 2025. 4. 9. 21:24

▶▷ 아처 평타

일반 공격은 어제에 이어서 일부 로직을 추가하였다.

public class Arrow : MonoBehaviour
{
    [SerializeField] private int damage = 50;   // 화살 데미지
    private float maxRange;
    private Vector3 spawnPosition;

    private void Update()
    {
        if (Vector3.Distance(spawnPosition, transform.position) >= maxRange)
        {
            Destroy(gameObject);
        }
    }

    public void SetRange(float range)
    {
        spawnPosition = transform.position;
        maxRange = range;
    }
}

화살이 일정 거리를 날아가면 사라지도록 하는 기능이다. 범위는 타게팅 데이터의 range값을 받아서 설정해주었다.

일단은 테스트 용으로 작성한 내용이라 화살을 쏠 때마다 매번 새로 생성하고 파괴하고 하는 방식인데
이 방식은 성능에 영향을 미칠 수 있을 것 같아 오브젝트 풀링을 사용하는 방식으로 수정이 필요하다고 생각한다.

다른 팀원이 PoolManager를 먼저 제작하고 계셔서 해당 스크립트를 참고해서 추가하면 될 것 같다.

▶▷ 아처 s스킬

아처의 s스킬은 '속사'로 멈춘 상태에서 대량의 화살을 빠르게 쏘는 기술이다.

[CreateAssetMenu(menuName = "Skill/Archer/Archer_s")]
public class ArcherSkill_s : SkillExecuter
{
    public GameObject arrow;         // 발사할 화살 프리팹
    public float arrowSpeed;         // 화살 속도

    /// <summary>
    /// 아처의 S키 스킬 로직을 담당하는 메소드
    /// </summary>
    /// <param name="user">스킬 시전자</param>
    /// <param name="target">타겟팅 정보</param>
    /// <param name="skillData">스킬의 공통 데이터</param>
    public override void Execute(Player user, Player target, SkillData skillData)
    {
        // 플레이어가 바라보는 방향 계산
        Vector2 dir = user.SpriteRenderer.flipX ? Vector2.left : Vector2.right;

        float randomXSpawn;

        // 일정 범위 내에서 화살 랜덤 생성
        if (!user.SpriteRenderer.flipX)
        {
            randomXSpawn = Random.Range(-0.3f, 1.2f);
        }
        else
        {
            randomXSpawn = Random.Range(0.3f, -1.2f);
        }

        float randomYSpawn = Random.Range(-0.3f, 0.5f);

        // 화살 생성 위치 설정
        Vector3 spawnPos = user.transform.position + (Vector3)(dir * 2f) + new Vector3(randomXSpawn, randomYSpawn, 0);

        // 화살 생성
        var arrows = Instantiate(arrow, spawnPos, Quaternion.identity);

        // 화살 속도 적용
        arrows.GetComponent<Rigidbody2D>().velocity = dir * arrowSpeed;

        // Arrow의 SetRange()에 범위 매개변수 전달
        arrows.GetComponent<Arrow>().SetRange(skillData.targetingData.range);
    }
}

// 쿨타임 적용 및 발사 화살 수 별도 지정 필요
// 현재는 플레이어의 update문에서 스킬을 사용중이라 프레임을 60으로 제한하지 않으면 너무 많이 생성

전체적인 로직은 일반 공격과 비슷한데 화살 생성 위치에 대한 차이가 있다.

아무래도 빠르게 발사하는 스킬이다 보니 일자로 날아가도록 했더니 보기에 별로 안좋았기 때문에 Random.Range를 통해
x축과 y축의 일정 범위 내에서 랜덤으로 생성되게 하여 좀 더 느낌을 살렸다.
평타와 마찬가지로 생성되는 위치가 좌우 대칭이어야 하므로 x축 랜덤 생성 위치는 if문을 통해 나눠주었다

아직 쿨타임과 움직임 제한 기능이 연결 안되어서 내일은 이 부분을 플레이어 역할의 팀원과 같이 작업할 예정이다.

그리고 주석으로도 작성해두었듯 현재는 테스트용으로 플레이어의 Update문에서 스킬을 사용하는 메소드를 호출중이라 여러 발을 발사하는 것처럼 보이지만
플레이어 로직과 제대로 연결하면 아마 해당 메소드가 한번만 호출되는 형식이 될거라 이 부분을 어떻게 변경할지 고민중에 있다.

코루틴을 사용해서 처리할지 발사 시간과 투사체의 개수를 대응시켜 발사 시간동안 균등하게 발사하도록 처리할지 발사를 위한 프리펩을 만들어 활성화시 발사하고 끝나면 비활성화 시켜서 처리할지 세가지 정도가 있다.

 

▶▷ 트러블 슈팅

막히는 점
아처의 s 스킬을 사용했을 때 화살은 발사되지만 s 스킬에 해당하는 스크립트를 수정해도 수정 사항이 적용되지 않고 디버그 로그도 찍히지 않는 현상

원인
스킬 데이터를 만들 때 s스킬에 해당하는 ScriptableObject를 생성했어야 했는데 클릭 실수로 인해 x스킬에 해당하는 것을 만든 상태로 s스킬의 데이터를 넣었기 때문에 키 전달에서 꼬였음.

해결
디버그 로그를 여기저기 찍어보면서 x스킬 스크립트에 찍어보니 s키를 눌러도 해당 스크립트에 작성한 디버그 로그가 출력되는 것을 확인하고 ScriptableObject를 확인 후 잘못 생성한 부분을 수정함.

 

ScriptableObject를 사용한다면 직관적이라는 장점이 있지만 오늘 내가 했던 실수와 같이 흔히 발생할 수 있는 부분이 있기 때문에 주의가 필요하다.