게임 개발 공부 기록

56일차 - Abyss_Slayer 최종 팀 프로젝트 6 (투사체 오브젝트 풀링 2, 투사체 증가 버프)

00lwt 2025. 4. 11. 22:02

오늘은 어제 있었던 오브젝트 풀링 관련 문제를 해결하고 각 스킬의 투사체 적용 방식을 변경하였다.

▶▷ 오브젝트 풀링 트러블 슈팅

막히는 점
풀이 정상적으로 생성되지 않아 스킬을 사용하면 null 오류가 발생하는 현상

원인
현재 풀을 만드는 방식이 스크립트 타입을 키로 가져와서 만드는데 팀원께서 미리 만들어두신 보스 관련 풀 중에 스크립트가 잘못 할당되어 겹치는 부분이 있어서 같은 키가 인식되는 바람에 오류가 생겨 밑에 추가한 플레이어 전용 풀이 생성되지 않음

Explosion 중복

해결
중복되는 보스 관련 스크립트를 알맞은 스크립트로 변경

알맞게 변경

 

▶▷ 투사체 적용 방식 변경

기존에는 스킬마다 이펙트가 구분돼야 하기 때문에 이를 나누기 위해 각각의 투사체 프리펩 자체를 다르게 하려고 했다.

그런데 현재 풀에 대한 로직이 프리펩이 나눠지게 되면 해당 프리펩마다 풀을 또 추가해서 사용해야 하는 상태라
비효율적일 것 같다는 생각을 했고 어떻게 하면 하나의 풀에서 각각 다른 투사체처럼 만들까 생각을 해보았다.

생각한 방법은 스킬마다 투사체의 Sprite만 다르면 되고 데미지 같은 경우는 투사체 로직이 아닌 각 스킬의 로직에서 관리를 하는 방법이다.
이렇게 하면 하나의 풀을 사용하면서 투사체의 효과도 각각 다르게 할 수 있다.

 

ArcherSkill_a.cs

[CreateAssetMenu(menuName = "Skill/Archer/Archer_a")]
public class ArcherSkill_a : SkillExecuter
{
    public float arrowSpeed;          // 화살 속도
    public int spriteNum;             // 화살 스프라이트 인덱스
    
    /// <summary>
    /// 아처의 A키 스킬 로직직을 담당하는 메소드
    /// </summary>
    /// <param name="user">스킬 시전자</param>
    /// <param name="target">타겟팅 정보</param>
    /// <param name="skillData">스킬의 공통 데이터</param>
    public override void Execute(Player user, Player target, SkillData skillData)
    {
        //...
        
        // 화살 초기화 데이터 투사체에 전달
        arrow.Init(spawnPos, dir, skillData.targetingData.range, arrowSpeed, spriteNum);
    }
}

ArrowProjectile.cs

public class ArrowProjectile : BasePoolable
{
    // Init으로 전달받은 화살 데이터 저장용 변수
    //...
    [SerializeField] List<Sprite> sprites;
    [SerializeField] SpriteRenderer spriteRenderer;
	
    //...

    /// <summary>
    /// 각 스킬 클래스에서 전달받은 데이터로 화살을 초기화하는 메서드
    /// </summary>
    /// <param name="spawnPos">화살 생성 위치</param>
    /// <param name="dir">화살 이동 방향</param>
    /// <param name="range">화살 최대 이동 거리</param>
    /// <param name="speed">화살 이동 속도</param>
    /// <param name="spriteNum">화살 스프라이트 인덱스</param>
    public void Init(Vector3 spawnPos, Vector3 dir, float range, float speed, int spriteNum)
    {
        transform.position = spawnPos;
        initPos = spawnPos;
        direction = dir.normalized;
        maxRange = range;
        arrowSpeed = speed;
        _spriteRenderer.sprite = _sprites[spriteNum];
    }
    
    //...
}

a스킬 인스펙터
투사체 프리펩 인스펙터

위와 같이 Archer_skill_a에서 설정한 sprite의 인덱스 값을 투사체 쪽 Init에 보내면 ArrowObjectile쪽 sprite 리스트로 생성해둔 이미지들 중 선택해서 변경되는 방식이다.

이렇게 하면 프리펩은 하나만 사용하기 때문에 풀도 하나이면서 이미지와 데미지를 구분할 수 있다.

 

▶▷ 투사체 증가 버프 (d 스킬)

투사체를 일정 시간동안 2배로 증가시켜주는 스킬을 추가하였다.

기존에는 투사체가 두 개가 들어있는 프리펩을 생성하는 방식으로 하려고 했었으나 오브젝트 풀링에서 얘기했듯 풀을 효율적으로 사용하기 위해 사용하지 않았다.

그리고 생각한 방법은 아예 프리펩 Instantiate를 추가로 해주는 방식으로 하였다.

public class Player : MonoBehaviour
{
    //...
    public bool IsDoubleShot { get; private set; } = false;
	
    //...

    /// <summary>
    /// 더블샷 버프 활성화 메서드
    /// </summary>
    /// <param name="value">활성화 여부</param>
    public void SetDoubleShot(bool value)
    {
        IsDoubleShot = value;
    }
}

플레이어에서 버프를 활성화하는 SetDoubleShot()을 작성하고

[CreateAssetMenu(menuName = "Skill/Archer/Archer_d")]
public class ArcherSkill_d : SkillExecuter
{
    public int duration;
    
    /// <summary>
    /// 아처의 D키 스킬 로직을 담당하는 메소드
    /// </summary>
    /// <param name="user">스킬 시전자</param>
    /// <param name="target">타겟팅 정보</param>
    /// <param name="skillData">스킬의 공통 데이터</param>
    public override void Execute(Player user, Player target, SkillData skillData)
    {
        // 버프 활성화
        user.SetDoubleShot(true);
        
        // 버프 지속 시간 후 비활성화
        user.StartCoroutine(DeactivateBuff(user));
    }
    
    private IEnumerator DeactivateBuff(Player user)
    {
        yield return new WaitForSeconds(duration);
        user.SetDoubleShot(false);
    }
}

코루틴을 통해 버프를 duration만큼 유지 후 끄는 ArcherSkill_d 스크립트를 작성한 다음

// 버프 상태일 경우 추가 화살 생성
if (user.IsDoubleShot)
{
    var secondArrow = PoolManager.Instance.Get<ArrowProjectile>();
    Vector3 secondSpawnPos = spawnPos + new Vector3(0, 0.5f, 0);
    secondArrow.Init(secondSpawnPos, dir, skillData.targetingData.range, arrowSpeed, spriteNum);
}

투사체를 발사하는 스킬들의 Execute()에 아래와 같은 로직을 추가하여 버프 상태일 경우 투사체를 추가로 하나 생성하는 로직을 넣어 아래와 같이 만들었다.


남은 부분은 추가로 생성된 투사체가 기존 투사체에 겹치지 않게 하고 원본의 데미지보다 조금 낮게 설정되도록 하는 로직 추가 정도가 될 것 같다.