게시글
질문&답변
2024.10.03
Getcomponent 호출 빈도에 관하여 질문이 있습니다.
수강해주셔서 감사합니다. GetComponent 함수를 for문 호출로 한번에 10만번씩 사용하는게 아니라면 함수 하나 때문에 프레임 드랍이 생길 걱정은 안하셔도 됩니다. 최적화라는건 AI, 아트, 물리, 코드, 사운드 모든 것들이 복합적으로 작용해서 이루어지는 것이지 단순히 코드를 잘 짜거나 못 짰다고 어떻게 되는 것은 아닙니다. 감사합니다.
- 0
- 1
- 11
질문&답변
2024.10.01
TargetSearcher없이 어떻게 해야하는지 질문이 있습니다.
프로그래밍은 시험 문제가 아니기 때문에 기능 구현에 맞고 틀리고는 없으므로 제가 맞다 틀리다 함부로 말씀 드릴 수 없습니다. 특히나 상대방이 왜 이렇게 설계 했는지 설계의 의도를 자세히 모르는 상태에서는 더더욱 그렇구요. 굳이 얘기드리자면 구현한 코드가 생각하신 결과를 낸다면 맞는거고 아니라면 틀렸다고 볼 수 있겠죠. 강의에서도 말씀드렸듯 이 강의의 스킬 시스템 역시 하나의 가이드일뿐 정답이 아니며, 수강생분들이 어떻게 강의의 시스템을 수정하시든 본인이 의도한대로 동작한다면 그게 맞는 겁니다. TargetSearcher를 뺀다는건 강의에서 학습한 스킬 시스템 구조 자체를 바꾸는 것이기 때문에 구조를 바꾼 독자적인 시스템에 추가적인 기능을 어떻게 만드냐고 물어보시면 대답드리기가 좀 곤란합니다. 저에게 만드신 독자적인 시스템을 이해하고 해당 기능까지 추가해달라는 얘기와 마찬가지니까요. TargetSearcher를 제거하시겠다면 원래 TargetSearcher가 하던 기능들을 어떻게 구현할 것인가를 먼저 생각해야하구요, 일단 제거해버리고 그 다음은 어떻게 해야하지 고민하는 것은 매우 안좋은 코딩 습관입니다. 하드 코딩을 하게 만드니까요. 현재 상태에서 어떻게 기능을 구현해야할지 모르시겠다면 TargetSearcher를 제거하기 보다는 무기에 // WeaponCollider.cs List objects = new(); List Objects => objects; void OnCollisionEnter(Collision col) => objects.Add(col.transform.gameObject); void OnCollisionExit(Collision col) => objects.Remove(col.transform.gameObject); 이런 Script를 달아두고, TargetSearchAction으로 // SearchWeaponTargetAction.cs TargetSearchResult Search(...) => new (requesterEntity.Weapon.GetComponent ().Objects.ToArray()); 이런 식으로 WeaponCollider가 보관하고 있는 Object들을 return하는 Action을 만드는 것도 한 방법입니다. 한 가지 조언을 더 드리자면, 만들려고 하는 시스템이 만들기 버겁거나 복잡하다면 무작정 만들기 보다는 이전에 말씀드렸듯 관련 튜토리얼을 보거나 다른 에셋을 분석 하는 과정이 필요합니다. 저도 지금도 뭔가를 만들 때 무작정 만들고 보는 경우는 거의 없구요, 거의 항상 다른 게임, 다른 시스템, 다른 에셋, 오픈 소스들을 분석하고 진행합니다. 현업에서 활동하시는 다른 개발자분들도 다 마찬가지구요. 몇 줄 코딩하고 막히고, 몇 줄 코딩하고 문제 생기고를 개발 내내 반복하실게 아니라면 좀 천천히 돌아가시는걸 추천드리겠습니다.
- 0
- 2
- 18
질문&답변
2024.10.01
전투시스템과 결합하려고 합니다.
수강해주셔서 감사합니다. 비효율적인지는 실제 코드를 보지 않는 이상 알 수 없는지라 지금 말씀드릴 수 있는건 아니구요, 조언 드릴 수 있는 부분은 일단 만드시고 문제가 생기면 그때 생각하시라는겁니다. 개발 경험이 적으면 아무리 고민해도 만들어낼 수 있는 결과물에 한계가 존재합니다. 그렇기 때문에 더 나은게 있지 않을까 끝 없이 고민하기 보다는 어느 정도 구상이 되면 만들고, 결과물에서 문제점을 파악하고, 개선하고, 다시 문제점을 파악하고, 개선하고 이 루틴을 반복하며 경험을 쌓는게 중요합니다. 말씀해주신 내용은 전투 시스템의 개발을 시작하는 초기 단계의 아이디어로써 나쁘지 않다고 보구요, 에셋스토어에서 잘 팔리는 전투 시스템 에셋을 구매해서 로직을 분석하거나 유튜브에서 관련 강좌를 보는 것도 고민 해결에 큰 도움이 되실겁니다. 요즘은 좀 덜하지만 저도 옛날엔 오픈소스나 에셋들을 엄청 많이 분석했었습니다. 감사합니다.
- 0
- 2
- 24
질문&답변
2024.09.28
uphandcast만 트리거를 쓰는건지 궁금합니다.
수강해주셔서 감사합니다. (사진) upHandCast가 Trigger Type인건 해당 Animation을 쓰는 Skill에서 Trigger Type으로 설정해서 그렇구요, 혹시 왜 다른 Animation들은 Bool형으로 만들고 upHandCast만 Trigger 형태로 만들었는지 물어보시는거라면 예제를 보여드리기 위한 것일 뿐 다른 이유는 없습니다. Code를 보면 Trigger Type일 경우 Entity가 DefaultState로 전이되기 때문에 DefaultState의 규칙을 따르므로 행동에 아무런 제약이 없습니다. 감사합니다.
- 0
- 2
- 24
질문&답변
2024.09.17
다른형식의 근접공격에 대해 질문할것이 있습니다.
수강해주셔서 감사합니다. 몬스터 헌터나 다크 소울의 근접 액션은 정교하게 만들어져있기 때문에 제가 확답 드리긴 어렵구요, 간단하게는 무기에 Collider를 넣고 TargetSearcher가 무기 Collider에 닿은 Target들을 가져오게 만들면 되지만, 몬스터 헌터나 다크 소울처럼 정교하게 만들어진 전투는 단순한 Skill System만으로는 무리고 함께 전투를 제어할 Combat System이 만들어져 있어야합니다. 물론 Skill System만으로도 만들려면 만들 순 있겠지만 좀 하드 코딩이 되겠죠. 감사합니다.
- 0
- 2
- 54
질문&답변
2024.09.13
Input 스킬 구현 질문
수강해주셔서 감사합니다. 해당 기능은 ApplyCount마다 Effect와 TargetSearcher, Animation을 따로 지정할 수 있게 확장해주시면 됩니다. 강의에서 여러 Data들을 Level로 묶었듯이 여러 정보들을 ApplyCount로 묶는겁니다. (사진) 이게 강의에서 만든 단일 설정의 Skill이구요, (사진) 이런 식으로 Action과 관련된 설정을 묶어서 현재 ApplyCount에 해당하는 설정을 가져와서 사용해주면 됩니다. ApplyCount가 많을 시에는 Level처럼 새로운 ApplyCount 설정이 있을 때까지 이전 ApplyCount 설정을 사용하는 형태로 만들어주시면 됩니다. 이미지에는 없지만 PrecedingAction과 Action도 추가해주시면 ApplyCount에 따라서 완전히 다른 형태의 공격이 나가는 Skill도 만들 수 있습니다.(ex.리신 음파-1타 투사체-2타 돌진) 이 이외의 방법으로는 Input마다 Skill들을 아예 따로 만들어서 Link 시켜두고 Skill을 사용할 때마다 Skill이 Link된 다른 Skill로 교체되게 만드는 방법이 있습니다. 방법은 여러가지가 될 수 있기 때문에 조언드린 얘기를 토대로 해당 기능 구현을 시도해보시면 될 것 같습니다. 감사합니다.
- 0
- 3
- 64
질문&답변
2024.09.07
텍스트 변환 Mark에 대하여 질문이 있습니다.
수강해주셔서 감사합니다. stack이 0(=기본 Action)일 때는 '$[effectAction.keyword.effectIndex]' 이 형식의 Mark를 쓰게 되구요, stack이 0 보다 클 때는 '$[effectAction.keyword.stackActionIndex.stack.effectIndex]' 형식의 Mark를 씁니다. Mark를 이런 식으로 정한건 한 눈에 봤을 때 '기본 Action의 Mark다', '~ Stack의 ~ Index의 Action의 Mark다'라는걸 알아보기 위해서입니다. if (stack == 0) 이 부분을 없애고 '$[effectAction.keyword.stackActionIndex.stack.effectIndex]' Mark만 쓰도록 통일해도 되지만, 이럴 경우 기본 Action의 Mark도 '적에게 $[effectAction.defaultDamage.0.0.0] 피해를 줍니다.' 이런 식으로 길게 작성해줘야합니다. 개인적으로 이게 싫어서 구분을 해준 것일 뿐 큰 의미는 없습니다. Mark의 형태와 Mark를 Replace하는 방식은 제 취향에 맞춘 것이기 때문에 강의에서 말씀드렸다싶이 'Mark를 Replace해서 Description을 만드는 방법'만 숙지하신다면 세부적인 부분은 개인 취향에 맞게, 더 낫다고 생각하시면 방향으로 수정하시면되므로 너무 얽매이실 필요는 없습니다. 감사합니다.
- 0
- 1
- 27
질문&답변
2024.09.05
Destroy() 지연 파괴에 관하여
수강해주셔서 감사합니다. 지연 파괴를 해주는 이유는 다른 Script에서 null check를 통과하여 Quest의 Cancel 상태를 확인할 시간을 주기 위해서입니다. 보통은 Cancel을 onQuestCanceled event나 onQuestStateChanged event로 확인하겠지만 그럴 수 없는 경우를 대비한 작업입니다. 강의에서는 이번 Frame에서만 상태를 확인할 수 있게 한 Frame만 쉬어줬는데 짧다고 여겨질 경우 여유를 두고 2~3 Frame 정도를 쉬어줘도 됩니다. 물론 이런 대비가 불필요하다고 여겨지시면 지연 파괴 부분을 없애셔도 아무 문제 없습니다. 감사합니다.
- 0
- 1
- 29
질문&답변
2024.09.04
스킬 구현 질문
수강해주셔서 감사합니다. 만들고자하는 스킬의 Reference가 있을 땐 그 Reference를 Frame 단위로 면밀히 관찰하시는게 좋구요, 그레이브즈 Q의 경우 Skill 사용 모습을 보면 1. 탄환이 날아감(=Projectile) (사진) 2. 탄환이 사라짐 (사진) 3. 탄환이 사라졌던 위치에서 범위 공격을 가하는 탄환이 새로 나타남(=SkillObject) (사진) 4. SkillObject가 사라지면서 반대 방향으로 날아가는 Projectile을 쏴 닿는 모든 적에게 Damage를 줌 (사진) Frame 단위로 봤을 때 처음 발사하는 총알은 닿는 적에게 Damage를 주는 Projectile이고, Projectile이 끝 사거리에 도달하거나 벽에 부딪히면 주변에 Damage를 주는 SkillObject를 Spawn하고, SkillObject가 사라질 때 반대 방향으로 날아가는 Projectile을 쏜다는걸 유추할 수 있습니다. 그레이브즈의 Q Skill은 3개의 Action이 결합된 형태인거죠. Skill Particle도 언뜻보면 하나인 것처럼 보이지만 면밀히보면 동작에 따른 여러가지 Particle들이 마치 하나인 것처럼 자연스럽게 이어진 형태입니다. 이를 구현하기 위해서는 SpawnProjectileAction과 SpawnSkillObjectAction의 내용을 결합할 필요가 있구요(=SpawnProejctileAction에 SpawnSkillObjectAction을 변수로 추가하거나 아예 새로운 Action을 만드는 등), Projectile의 동작을 모듈화해서 사거리 끝에 닿거나 방해 물체에 닿았을 때 SkillObject를 Spawn하게 만들어주면 됩니다. SkillObject에도 Projectile 변수를 추가해서 SkillObject의 동작이 종료되는 시점에 Projectile을 Spawn하게 만들어주면되구요, Projectile의 이동 동작으로 Spawner 반대 방향으로 날아가도록 지정해주면 될겁니다.(=이동 Logic에 대한 모듈화) 강의에서 만든 칼날비 Skill이 칼날이 닿을 때마다가 아닌, 주기적으로 Damage를 주는 눈속임 Skill이였듯 면밀히 보지 않으면 알 수 없는 부분도 있고, 이런 부분 때문에 쉬운 것도 어렵게 만드는 상황이 생길 수 있으니 뭔가를 모방하고자 할 때는 항상 면밀히 관찰하시는걸 잊으시면 안됩니다. 감사합니다.
- 0
- 2
- 76
질문&답변
2024.09.01
Action & Delegate
수강해주셔서 감사합니다. 저는 일단 함수의 인자로 사용할 땐 Action을, event를 만들 땐 delegate를 사용합니다. 강의에서 UnityAction을 사용한 이유는 UnityEvent에 등록해줄 것이라 사용한거구요, 보통은 그냥 Action을 사용합니다. 저는 Type에 대해 명시적인걸 좋아해서 delegate를 정의하는걸 선호하는데, 다른 프로그래머분 중에는 불필요한 정의 작성이라고 Action을 선호하는 등 delegate를 정의하냐, Action을 사용하냐는 순전히 프로그래머의 취향 차이입니다. 다만 event와 UnityEvent는 좀 다릅니다. UnityEvent를 사용하게되면 Inspector 창에서 함수를 등록받을 수 있게 되는데요, 이 방식은 Code 작성 없이 간편하게 함수를 등록할 수 있다는 장점이 있지만 어떤 함수가 event에 등록됐는지 알게 어렵게 만들어 디버깅과 로직 파악을 힘들게 만든다는 단점이 있습니다. 개발에 있어서 디버깅을 힘들게 만드는건 굉장히 큰 단점이구요, Rider IDE를 쓰면 UnityEvent에 등록된 함수들을 추적해주긴 하는데, 그건 유로 IDE 기능이니까 논외로 치겠습니다. 그래서 UnityEvent는 명확한 기준을 가지고 사용하는게 좋습니다. 저도 실제 프로젝트를 진행할 때 UnityEvent를 많이 사용하지 않구요, 사용할만 상황이 없어서 아예 사용하지 않을 때도 있습니다. 다만, 이 기준이라는게 어떻게 정의해서 말씀드리기가 좀 애매한데 보통 UI Event, Animation Event에 주로 사용하고 그 외의 경우에는 그때 그때 상황을 봐서 사용합니다. 이는 수강생분이 앞으로 프로그래밍을 하시면서 "UnityEvent를 남용하면 이런 문제가 생기는구나", "이런 구조는 좋지 않구나", "사람들은 주로 이런 때에 UnityEvent를 사용하는구나"라고 경험을 쌓으시면서 스스로 기준을 잡으셔야하는 부분입니다. 감사합니다.
- 0
- 2
- 22