인프런 커뮤니티 질문&답변

coffeecat0213님의 프로필 이미지
coffeecat0213

작성한 질문수

[유니티 레벨 업!] 모듈식으로 개발하는 스킬 시스템

스킬 구현 질문입니다

작성

·

103

·

수정됨

0

현재 제가 인벤토리를 만들어 사용할 스킬을 등록하는 스킬창과 획득한 스킬을 보관하는 스킬보관창을 만들었습니다
스킬창에 있는 스킬은 활성화되고 보관창에 있는것은 비활성화되게 할려는 의도입니다.
액티브 스킬의 경우 키를 눌러 발동하기 때문에 문제가 없는데
패시브 스킬의 경우 스킬보관창에 있어도 계속해서 발동됩니다.
그래서 패시브 타입인 경우 스킬보관창에 있을 경우 비활성화되게 하기 위해
skill 스크립트와 skillsystem 스크립트에 비활성화 변수를 추가하여 의도한 목적을 제작할려고 하였는데
어디에서 제어해야 하는지 감이 안잡혀 이 부분에 대해 어딜 수정해야 되는지에 대한 조언을 부탁드립니다...

답변 1

1

Developer G님의 프로필 이미지
Developer G
지식공유자

수강해주셔서 감사합니다.

너무 어렵게 생각하실 필요 없습니다.
현재 SkillSystem의 UpdateSkills 함수에서 ownSkills를 for문으로 돌며 Skill들을 Update하고 있죠? List<Skill> skillsInStorage와 List<Skill> activatedSkills 두 목록을 만드셔서 UpdateSkills 함수에서 activatedSkills가 ownSkills 대신에 for문을 돌게 만드시고, Skill이 Register될 때 skillsInStorage 목록에도 넣어주시고, Skill을 보관함에서 Skill 창으로 옮기면 해당 Skill을 activatedSkills 목록으로 옮겨주시면 됩니다.

기존에 ownSkills가 하던 동작들은 activatedSkills가 하고 ownSkills는 내가 소유한 Skill이 무엇인지 확인하는 용도로만 사용하는겁니다.

반대로 Skill 창에서 보관함에 넣을 때는 해당 Skill을 Cancel 시키고 activatedSkills에서 skillsInStorage 목록에 넣어주시면 되겠죠.

감사합니다.

coffeecat0213님의 프로필 이미지
coffeecat0213
질문자

아 간단하네요 제가 너무 복잡하게 생각했나 봅니다
감사합니다!

coffeecat0213님의 프로필 이미지
coffeecat0213
질문자

다른 부분 해보면서 중간중간 테스트해봤는데 생각처럼 잘되질않네요...
public void OnChangeClick()

{

if(skill != null)

{

bool storedSkill = skill.Owner.SkillSystem.StoredSkills.Any(s => s.ID == skill.ID);

if(storedSkill)

{

Debug.Log(skill.Owner.Stats.GetValue(skill.Owner.Stats.MoveSpeedStat));

skill.Owner.SkillSystem.ActivateSkills.Add(skill);

skill.Owner.SkillSystem.StoredSkills.Remove(skill);

Debug.Log(skill.Owner.Stats.GetValue(skill.Owner.Stats.MoveSpeedStat));

}

else

{

Debug.Log(skill.Owner.Stats.GetValue(skill.Owner.Stats.MoveSpeedStat));

skill.Owner.SkillSystem.StoredSkills.Add(skill);

skill.Owner.SkillSystem.ActivateSkills.Remove(skill);

Debug.Log(skill.Owner.Stats.GetValue(skill.Owner.Stats.MoveSpeedStat));

}

}

}

UI에서 클릭시 리스트에 있는 요소를 옮기는 방식으로 해봤는데
저장된 스킬을 클릭하면 debuglog로 확인했을때 10,10 으로 변동없이 나오고
activateskills를 클릭하면 NaN으로 값이 나옵니다....
리스트에 직접 옮기는 방식말고 register나 다른 부분도 손대서 시도해봤는데 잘되질 않았습니다..
private void UpdateSkills()

{

foreach (var skill in activateSkills)

skill.Update();

}

처음에 말씀해주신 updateskills는 조언해주신대로 고쳐봤습니다
패시브를 storedskills에 있을때는 비활성화, activateskills에 있을때는 활성화 시킬려는데 잘되질 않습니다..

Developer G님의 프로필 이미지
Developer G
지식공유자

올려주신 코드로만 봤을 때는 문제가 없어보이구요, Log로 Stat을 확인하고 계신데 Store에 있는 Skill을 Activate로 옮겼다고해서 Skill이 바로 실행되는게 아니라 UpdateSkills 함수가 실행되야 Skill이 적용되는 것이기 때문에 연속적인 Log가 10, 10으로 나오는건 당연합니다.

NaN이 나온다는건 else 부분의 Log에서 그 값이 찍히신다는건가요? 보여주신 Code로는 ActivatedSkills에서 Skill을 제거하실 때 따로 Skill을 Cancel 시키지 않으시는 것으로 보이는데 NaN가 된다는건 이해하기 힘든 동작입니다. NaN가 나오나는건 어디서 Stat 연산이 잘못됐다는 말이므로(0으로 나누기 등) 연산 부분도 확인을 해보셔야할 것 같습니다.

coffeecat0213님의 프로필 이미지
coffeecat0213
질문자

아 cancel은 테스트하면서 코드수정하다가 생략되었습니다.
skill.Cancel();

skill.Owner.SkillSystem.StoredSkills.Add(skill);

skill.Owner.SkillSystem.ActivateSkills.Remove(skill);
이런식으로 사용중입니다.

이동속도를 올려주는 패시브스킬을 stored 에서 activate로 옮길때부터 PlayerStat GUI에서 이동속도 : 10(NaN) 이렇게 나옵니다.
기존의 코드에서 패시브스킬은
Debug.Assert(!IsPassive, "Skill::Cancel - Passive Skill은 Cancel 할 수 없습니다.");
로 해놓으셨는데 이부분을 지우고 사용하고 있는데 문제는 없을까요?

Developer G님의 프로필 이미지
Developer G
지식공유자

PassiveStateMachine에 Cancel Transition을 추가하셨다면 해당 부분은 문제가 없을 것 같습니다.

혹시 Stat class의 87번째 줄 else문을

// SetBonusValue 함수
else if (bonusValuesByKey[key].ContainsKey(subKey))

이렇게 수정해보시겠어요?

coffeecat0213님의 프로필 이미지
coffeecat0213
질문자

public void SetBonusValue(object key, object subKey, float value)

{

if (!bonusValuesByKey.ContainsKey(key))

bonusValuesByKey[key] = new Dictionary<object, float>();

else if (bonusValuesByKey[key].ContainsKey(subKey))

BonusValue -= bonusValuesByKey[key][subKey];

float prevValue = Value;

bonusValuesByKey[key][subKey] = value;

BonusValue += value;

TryInvokeValueChangedEvent(Value, prevValue);

}

사용하던 setbonusvalue 함수 입니다
수정된 상태로 사용하고 있었어요

Developer G님의 프로필 이미지
Developer G
지식공유자

Stored에서 Activate로 옮겼을 때 문제가 발생한다는건 Passive가 실행된다는 소리이니 Passive의 Effect가 의도대로 적용되고 있는지 봐야할 것 같습니다. 이동속도 증가는 강의 내용 그대로 적용하고 계신건가요?

coffeecat0213님의 프로필 이미지
coffeecat0213
질문자

네 기존이랑 거의 다를게 없습니다..
한번 다시 봐보면서 오류 찾아보겟습니다

coffeecat0213님의 프로필 이미지
coffeecat0213
질문자

어디서 NaN 이 나오는지 어느정도 찾은거같은데 원인을 정확히 모르겠습니다

public void Apply(Effect effect)

{

var runningEffect = Find(effect);

// 새로운 Effect거나 Effect의 중복 적용이 허용된다면 Effect를 적용함

if (runningEffect == null || effect.IsAllowDuplicate)

{

Debug.Log("SkillSystem - Apply:Effect : " + effect);

Debug.Log("SkillSystem - Apply:Effect:scale : " + effect.Scale);

ApplyNewEffect(effect);

}

SkillSystem의 Apply(Effect effect)함수에서
디버그 로그를 찍었을때
SkillSystem - Apply:Effect : EFFECT_TEST_BUFF(Clone) (Effect)
SkillSystem - Apply:Effect:scale : NaN
이펙트는 가져오는데 이펙트의 스케일 값은 NaN이 나옵니다.

그래서 강사님의 코드로 테스트 해봤을때는 NaN 이 아닌 1이 잘나옵니다

effect 자체는 잘 가져오는데 값을 못가져와서 어디가 문제인지 감을 못 잡겠습니다..

Developer G님의 프로필 이미지
Developer G
지식공유자

레퍼런스 검색으로 Effect의 Scale을 건드는 곳을 찾아보셔야할 것 같습니다.
Setup을 안하고 있거나 이러면 값이 0이 나오던가 해야하는데 NaN가 나온다면 명백히 어디선가 건드리고 있다는 얘기입니다.
Effect의 Scale 값을 수동으로 바꾸고 계시다면 계산식을 점검해보셔야할거구요, Skill Script에서는 CurrentChargePower가 바뀔 때 Effect의 Scale을 건드리는데 value 값으로 NaN가 들어갔을 수도 있구요, 아니면 CurrentChargePower와 연관된 CurrentChargeDuration에 NaN 값이 들어갔을 수도 있습니다.

coffeecat0213님의 프로필 이미지
coffeecat0213
질문자

해결했습니다!
public float CurrentChargeDuration

{

get => currentChargeDuration;

set

{

currentChargeDuration = Mathf.Clamp(value, 0f, ChargeDuration);

CurrentChargePower = !IsUseCharge ? 1f :

Mathf.Lerp(StartChargePower, 1f, currentChargeDuration / ChargeTime);

}

}

말씀하신대로 charge 부분에서 scale이 nan이 입력되고 있었습니다.

public float CurrentChargeDuration

{

get => currentChargeDuration;

set

{

currentChargeDuration = Mathf.Clamp(value, 0f, ChargeDuration);

if (ChargeTime > 0)

{

CurrentChargePower = !IsUseCharge ? 1f :

Mathf.Lerp(StartChargePower, 1f, currentChargeDuration / ChargeTime);

}

else

{

CurrentChargePower = 1f;

}

}

이렇게 수정하니 nan이 아닌 1로 입력되고 잘 작동합니다
감사합니다!

coffeecat0213님의 프로필 이미지
coffeecat0213
질문자

일단 눈에 보이는대로 해결하고 오류가 생길 부분이 아니라고 생각해 다시 천천히 살펴보니

혹시나 passive인데 isUseCharge 가 체크 되있나 확인하기 위해
active로 타입을 바꿔보니 isUseCharge가 체크 되있더군요..
안된다는거에 너무 눈이 멀어 간단한 해결방법을 크게 돌아서 간거 같고
오류에 눈 멀지 말고 천천히 생각하도록 노력해야겠습니다

coffeecat0213님의 프로필 이미지
coffeecat0213

작성한 질문수

질문하기