[Unity 강의] 뱀서라이크 강의 - 보스 스킬 개선

업데이트:

카테고리:

태그: , ,




1. 스킬 개선

✔ Sequence 스킬 - Move, Dash 추가
   BossController에서 Move를 제거하고 Skill로 통합





2. 수정 코드

🔹 SequenceSkill - 추상 클래스, DoSkill 추상메서드
🔹 Move - Target을 향해 X 초 움직이는 코드
🔹 Dash - Target을 향해 돌진
🔹 SkillBook - SequenceSkill 순차적 실행
✅ BossController - 이동 부분 없애고 -> SequenceSkill로


SequenceSkill

✔ SequenceSkill을 만들 때 SkillType을 설정
✔ Doskill() 추상메서드 -> 자식 클래스에 반드시 구현
✔ CallBack으로 스킬이 끝나면 추가 작업을 실행.

SequenceSkill
public abstract class SequenceSkill : SkillBase
{
    public SequenceSkill() : base(SkillType.Sequence) { } 
    public abstract void DoSkill(Action callback = null); 
}


Move

✔ 이동을 SequenceSkill로
✔ elapsed가 데이터 시트에 있으면 그 데이터를 사용
✔ CoMove() elapsed 초 동안 Target을 향해 이동

Move
public class Move : SequenceSkill
{
    Rigidbody2D _rb;
    Coroutine _coroutine;

    public override void DoSkill(Action callback = null)
    {
        if (_coroutine != null)
            StopCoroutine(_coroutine);

        _coroutine = StartCoroutine(CoMove(callback));

    }

    float Speed { get; } = 2.0f;
    string AnimationName { get; } = "Moving";

    IEnumerator CoMove(Action callback = null)
    {
        _rb = GetComponent<Rigidbody2D>();
        GetComponent<Animator>().Play(AnimationName);
        float elapsed = 0; // Move 시간

        while (true)
        {
            elapsed += Time.deltaTime;
            if (elapsed > 3.0f)
                break;

            Vector3 dir = ((Vector2)Managers.Game.Player.transform.position - _rb.position).normalized;
            Vector2 targetPosition = Managers.Game.Player.transform.position + dir * UnityEngine.Random.Range(1, 4);

            if (Vector3.Distance(_rb.position, targetPosition) <= 0.2f)
                continue;
                
            
            Vector2 dirvec = (targetPosition - _rb.position).normalized;
            Vector2 nextVec = dirvec * Speed * Time.fixedDeltaTime;
            _rb.MovePosition(_rb.position + nextVec);

            yield return null;
        }

        callback?.Invoke();
    }
}


Dash

✔ Move와 유사
✔ Target을 향해 Speed 만큼 돌진

Dash
public class Dash : SequenceSkill
{
    Rigidbody2D _rb;
    Coroutine _coroutine;

    public override void DoSkill(Action callback = null)
    {
        if (_coroutine != null)
            StopCoroutine(_coroutine);

        _coroutine = StartCoroutine(CoDash(callback));
        
    }

    float WaitTime { get; } = 1.0f;
    float Speed { get; } = 10.0f;
    string AnimationName { get; } = "Charge";

    IEnumerator CoDash(Action callback = null) 
    {
        _rb = GetComponent<Rigidbody2D>();

        yield return new WaitForSeconds(WaitTime);

        GetComponent<Animator>().Play(AnimationName);

        Vector3 dir = ((Vector2)Managers.Game.Player.transform.position - _rb.position).normalized;
        Vector2 targetPosition = Managers.Game.Player.transform.position + dir * UnityEngine.Random.Range(1, 5);


        while (Vector3.Distance(_rb.position, targetPosition) > 0.2f)
        {
            Vector2 dirvec = (targetPosition - _rb.position).normalized;
            Vector2 nextVec = dirvec * Speed * Time.fixedDeltaTime;
            _rb.MovePosition(_rb.position + nextVec);

            yield return null;
        }

        callback?.Invoke();
    }
}


SkillBook

✔ SequenceSkill AddSkill 추가
✔ Sequence스킬 목록을 순서대로 발동
✅ StartNextSequenceSkill() 현재 스킬 발동
✅ OnFinishedSequenceSkill 다음 스킬 Index로 변경
✅ StopSkills() 모든 RepeatSkill 멈춤

SkillBook
public class SkillBook : MonoBehaviour
{
    // 스킬 매니저.
    public List<SkillBase> Skills { get; } = new List<SkillBase>();
    public List<SkillBase> RepeatedSkills { get; } = new List<SkillBase>();
    public List<SequenceSkill> SequenceSkills { get; } = new List<SequenceSkill>();

    public T AddSkill<T>(Vector3 position, Transform parent = null) where T : SkillBase 
    {
        System.Type type = typeof(T);

        else if (type.IsSubclassOf(typeof(SequenceSkill)))
        {
            var skill = gameObject.GetOrAddComponent<T>();
            Skills.Add(skill);
            SequenceSkills.Add(skill as SequenceSkill);

            return skill as T;
        }

        return null;
    }

    int _sequenceIndex = 0;
    //✅ StartNextSequenceSkill() 현재 스킬 발동  
    public void StartNextSequenceSkill() 
    {
        if (_stopped)
            return;
        if (SequenceSkills.Count == 0)
            return;

        SequenceSkills[_sequenceIndex].DoSkill(OnFinishedSequenceSkill);
    }
    //✅ OnFinishedSequenceSkill  다음스킬Index로 변경  

    void OnFinishedSequenceSkill() 
    {
        _sequenceIndex = (_sequenceIndex + 1) % SequenceSkills.Count;
        StartNextSequenceSkill();
    }


    bool _stopped = false;
    //✅ StopSkills() 모든 RepeatSkill 멈춤  
    public void StopSkills() 
    {
        _stopped = true;

        foreach (var skill in RepeatedSkills)
        {
            skill.StopAllCoroutines();
        }
    }
}


BossController

✔ SequenceSkill Move - Dash - Dash - Dash 순서로 추가
✔ 스킬 상태로 들어가면 StartNextSequenceSkill를 하면 순차적으로 실행

BossController
public class BossController : MonsterController
{
    public override bool Init()
    {
        base.Init();

        _animator = GetComponent<Animator>();
        //CreatureState = CreatureState.Moving;
        Hp = 1000000;

        CreatureState = CreatureState.Skill;

        Skills.AddSkill<Move>(transform.position);
        Skills.AddSkill<Dash>(transform.position);
        Skills.AddSkill<Dash>(transform.position);
        Skills.AddSkill<Dash>(transform.position);
        //Skills.StartNextSequenceSkill();

        return true;
    }
}





이것저것 메모

공통적인 부분 -> 데이터

여러 스킬 만들다 보면 공통적인 부분 => 통합해서 데이터시트로

카메라 시점 변환

카메라 시점 변환도 데이터 시트로?





잡담, 일기?

보스 스킬 추가.




📔

댓글남기기