묻고 답해요
138만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결[유니티 레벨 업!] 모듈식으로 개발하는 스킬 시스템
object 형의 박싱 언박싱에 관련해서 궁금합니다.
안녕하세요. 강습 잘 시청하고 있는데 궁금한 부분이 생겨서요.object 형을 많이 쓰던데, 실제 게임을 이 상태로 스킬을 구현해서 출시한다고 한다면 박싱 언박싱에 관련해서 성능 이슈는 없을까요? (ex : Stat.cs Dictionary<object, Dictionary<object, float>> bonusValuesByKey .. ) IdentifiedObject.cs 에서 object Clone() => Instantiate(this); 무시할 만한 수준일지 , 코드가 더 복잡하게 구현될 요지가 있어서 강의용으로 범용적으로 작업하셨는지 해서요.아님 object 형이 아닌 좀 더 나은 방향이 있다면 의견 듣고 싶습니다. 감사합니다.
-
미해결[유니티 레벨 업!] 모듈식으로 개발하는 스킬 시스템
Getcomponent 호출 빈도에 관하여 질문이 있습니다.
저번에 조언해주신것을 통해서 다른 에셋들과 오픈소스들을 뜯어가면서 저만의 프레임워크를 설계중입니다.그런데 다른 객체의 스텟을 가져와서 영향을 주려면 Getcomponent종류를 사용 할 수밖에 없는 것 같아 보이고 강의에서도 Getcomponent스킬의 대상을 지정할때 사용되는것을 보고 질문을 드립니다.Getcomponent가 프레임 단위로 실행되는 수준만 아니면 되는건가요?그러면 혹시 다른 게임에서의 예시로 버그, 해킹 툴의 요소로 공격속도를 비정상적으로 올라간상태로 공격시 프레임드랍이 걸리는 이유가 이때 Getcomponent같은게 실행이 많이 되어서 그런걸까요? ex)다크소울이었는지 엘든링이었는지 기억이 나질 않지만 버그로 인해 프레임단위로 공격하고 렉을 유발시켰던걸로 기억합니다.public void SearchTargets(){var result = TargetSearcher.SearchTargets(Owner, Owner.gameObject);Targets = result.targets.Select(x => x.GetComponent<Entity>()).ToArray();TargetPositions = result.positions;}
-
미해결[유니티 레벨 업!] 모듈식으로 개발하는 스킬 시스템
TargetSearcher없이 어떻게 해야하는지 질문이 있습니다.
콜라이더를 이용해서 하는 공격은무기 콜라이더 액션을 만든다음에public class WeaponColliderAction : SkillAction{ [SerializeField] private string weaponSocketName; public override void Apply(Skill skill) { var socket = skill.Owner.GetTransformSocket(weaponSocketName); socket.AddComponent<SkillCollider>(); } public override object Clone() { return new WeaponColliderAction() { weaponSocketName = weaponSocketName }; }}무기에 해당하는 오브젝트를 찾아서 스킬 콜라이더 스크립트를 추가하고public class SkillCollider : MonoBehaviour{ private Entity owner; private Skill skill; public void Setup(Entity owner, Skill skill) { this.owner = owner; // 현재 Skill의 Level 정보를 저장하기 위해 Clone을 보관 this.skill = skill.Clone() as Skill; } private void OnTriggerEnter(Collider other) { if (other.GetComponent<Entity>() == owner) return; var entity = other.GetComponent<Entity>(); if (entity) entity.SkillSystem.Apply(skill); Destroy(gameObject); }}해당 스킬이 적용되게 구현을 하였는데 이런식으로 구현하는지 맞는지와 TargetSearcher없이 자기 자신에게 사용하는 스킬을 Skill스크립트에 있는 public Entity Owner { get; private set; }와 public IReadOnlyList<Entity> Targets { get; private set; }을 활용하면 될것같은데 어떻게 구현하는지 모르겠어서 질문드립니다. 너무 많은 질문을 드리는것같아 죄송합니다.
-
미해결[유니티 레벨 업!] 모듈식으로 개발하는 스킬 시스템
Retrieving array size but no array was provided 오류가 발생합니다.
property.arraySize이 문제인것 같은데private void DrawSkillDatas(){// Skill의 Data가 아무것도 존재하지 않으면 1개를 자동적으로 만들어줌if (skillDatasProperty.arraySize == 0){// 배열 길이를 늘려서 새로운 Element를 생성skillDatasProperty.arraySize++;// 추가한 Data의 Level을 1로 설정skillDatasProperty.GetArrayElementAtIndex(0).FindPropertyRelative("level").intValue = 1;}if (!DrawFoldoutTitle("Data"))return;EditorGUILayout.PropertyField(isAllowLevelExceedDatasProperty);// Level 상한 제한이 없다면 MaxLevel을 그대로 그려주고,// 상한 제한이 있다면 MaxLevel을 상한으로 고정 시키는 작업을 함if (isAllowLevelExceedDatasProperty.boolValue)EditorGUILayout.PropertyField(maxLevelProperty);else{// Property를 수정하지 못하게 GUI Enable의 false로 바꿈GUI.enabled = false;var lastIndex = skillDatasProperty.arraySize - 1;// 마지막 SkillData(= 가장 높은 Level의 Data)를 가져옴var lastSkillData = skillDatasProperty.GetArrayElementAtIndex(lastIndex);// maxLevel을 마지막 Data의 Level로 고정maxLevelProperty.intValue = lastSkillData.FindPropertyRelative("level").intValue;// maxLevel Property를 그려줌EditorGUILayout.PropertyField(maxLevelProperty);GUI.enabled = true;}EditorGUILayout.PropertyField(defaultLevelProperty); for (int i = 0; i < skillDatasProperty.arraySize; i++){var property = skillDatasProperty.GetArrayElementAtIndex(i);var isUseCastProperty = property.FindPropertyRelative("isUseCast");var isUseConcentrateProperty = property.FindPropertyRelative("isUseConcentration");var chargeDurationProperty = property.FindPropertyRelative("chargeDuration");var chargeTimeProperty = property.FindPropertyRelative("chargeTime");var needChargeTimeToUseProperty = property.FindPropertyRelative("needLeastChargeTime");var perfectDamageChargeTimeProperty = property.FindPropertyRelative("perfectDamageChargeTime");var perfectDamageChargeTimeDetectionProperty = property.FindPropertyRelative("perfectDamageTimeDetection");EditorGUILayout.BeginVertical("HelpBox");{// Data의 Level과 Data 삭제를 위한 X Button을 그려주는 Foldout Title을 그려줌// 단, 첫번째 Data(= index 0) 지우면 안되기 때문에 X Button을 그려주지 않음// X Button을 눌러서 Data가 지워지면 true를 return함if (DrawRemovableLevelFoldout(skillDatasProperty, property, i, i != 0)){// Data가 삭제되었으며 더 이상 GUI를 그리지 않고 바로 빠져나감// 다음 Frame에 처음부터 다시 그리기 위함EditorGUILayout.EndVertical();break;}EditorGUI.indentLevel += 1;if (property.isExpanded){// SkillData Property 내부로 들어감 -> Property == level field;property.NextVisible(true);DrawAutoSortLevelProperty(skillDatasProperty, property, i, i != 0);// Level Upfor (int j = 0; j < 2; j++){property.NextVisible(false);EditorGUILayout.PropertyField(property);}// PrecedingAction// Toggle Type일 때는 PrecedingAction을 사용하지 않을 것이므로,// Instant Type일 때만 PrecedingAction 변수를 보여줌property.NextVisible(false);if (useTypeProperty.enumValueIndex == (int)SkillUseType.Instant)EditorGUILayout.PropertyField(property);// Action And Settingfor (int j = 0; j < 8; j++){// 다음 변수의 Property로 이동하면서 그려줌property.NextVisible(false);EditorGUILayout.PropertyField(property);}// Castproperty.NextVisible(false);if (IsDrawPropertyAll && !isUseConcentrateProperty.boolValue)EditorGUILayout.PropertyField(property);elseproperty.boolValue = false;property.NextVisible(false);if (isUseCastProperty.boolValue)EditorGUILayout.PropertyField(property);// Chargeproperty.NextVisible(false);if (IsDrawPropertyAll && !isUseCastProperty.boolValue)EditorGUILayout.PropertyField(property);for (int j = 0; j < 5; j++){property.NextVisible(false);if (isUseConcentrateProperty.boolValue)EditorGUILayout.PropertyField(property);}// 최대 chargeTime 값을 chargeDuration 값으로 제한chargeTimeProperty.floatValue = Mathf.Min(chargeTimeProperty.floatValue, chargeDurationProperty.floatValue);// 최대 needChargeTime 값을 chargeTime 값으로 제한needChargeTimeToUseProperty.floatValue = Mathf.Min(chargeTimeProperty.floatValue, needChargeTimeToUseProperty.floatValue);perfectDamageChargeTimeProperty.floatValue = Mathf.Clamp(perfectDamageChargeTimeProperty.floatValue,needChargeTimeToUseProperty.floatValue,chargeTimeProperty.floatValue);// Effectproperty.NextVisible(false);EditorGUILayout.PropertyField(property); //// EffectSelector의 level 변수를 effect의 최대 level 제한함for (int j = 0; j < property.arraySize; j++){var effectSelectorProperty = property.GetArrayElementAtIndex(j);// Selector의 level Property를 가져옴var levelProperty = effectSelectorProperty.FindPropertyRelative("level");// Selector가 가진 effect를 가져옴var effect = effectSelectorProperty.FindPropertyRelative("effect").objectReferenceValue as Effect;var maxLevel = effect != null ? effect.MaxLevel : 0;var minLevel = maxLevel == 0 ? 0 : 1;levelProperty.intValue = Mathf.Clamp(levelProperty.intValue, minLevel, maxLevel);}}파란색인 부분에서 계속 걸리는데 무슨 문제인지 모르겠습니다. 파란색 뒷부분은 너무 길어져서 잘랐습니다.skillDatasProperty를 가져오는거라 Skill의 skillDatas가[SerializeField]private SkillData[] skillDatas;배열인것도 확인을 하였지만if (property.isArray){int size = property.arraySize;Debug.Log("사이즈 :" + size);}else{Debug.LogError("이 속성은 배열 또는 리스트가 아닙니다.");}이걸로 확인하니 배열이 아니라고 오는데 어떻게 배열이 아니게 된건지 모르겠습니다.
-
미해결[유니티 레벨 업!] 모듈식으로 개발하는 스킬 시스템
전투시스템과 결합하려고 합니다.
현재 강의에서는 탑뷰 형식의 AOS와 적합한 스킬 사용 방식이기에 제가 개발하려는 전투시스템에 맞춰서 공격 판정을 콜라이더를 주로 사용하려고 합니다.공격을 실행하면 애니메이션 시작과 동시에 스킬이 발동되게 하고 애니메이션 이벤트를 활용해서 특정 구간에 콜라이더를 활성화 해준 다음 비 활성화해주고 애니메이션이 끝나면 스킬이 종료되는 방식으로 공격을 구현하려고 하는데 많이 비효율적일까요. 학습한 내용을 이해한거로는 투사체 스킬은 Targetsearcher은 연관이 없고 인디케이터가 공격할 좌표만 정해주고 캐릭터를 해당 좌표를 향해 회전해주고 발사하는 것이기에 Targetsearcher와 인디케이터를 전부 없애버리고 투사체 스킬의 투사체 생성 대신에 소켓을 이용해서 공격판정 무기를 찾은 다음 해당 스킬 스크립트를 생성시켜준 다음에 애니메이션 이벤트로 콜라이더를 활성화 비 활성화로 공격 판정을 구현하고 공격 애니메이션이 끝나면 해당 스크립트를 삭제시켜주는 방식으로 구현을 생각중입니다.혼자서 독학 중이라 다른 사람들의 개발 방식을 볼 때마다 제 방식에 대한 확신을 가지지 못하는 것 같습니다.
-
미해결[유니티 레벨 업!] 모듈식으로 개발하는 스킬 시스템
uphandcast만 트리거를 쓰는건지 궁금합니다.
// 인자로 받은 animatorParameter가 bool Type이면 owner의 StateMachine으로 인자로 받은 command를 보냄// Transition이 Command를 받아들였으면, State로 UsingSKill Message와 Skill 정보를 보냄if (animatorParameter.type == AnimatorParameterType.Bool && ownerStateMachine.ExecuteCommand(command)) ownerStateMachine.SendMessage(EntityStateMessage.UsingSkill, (skill, animatorParameter));// 인자로 받은 animatorParameter가 trigger Type이면 행동에 제약을 주지 않을 것이므로 ToDefaultState Command를 보내고// Transition이 받아들였는지와 상관없이, State로 UsingSkill Message와 skill 정보를 보냄else if (animatorParameter.type == AnimatorParameterType.Trigger){ ownerStateMachine.ExecuteCommand(EntityStateCommand.ToDefaultState); ownerStateMachine.SendMessage(EntityStateMessage.UsingSkill, (skill, animatorParameter));} 왜 Uphandcast만 트리거 타입이 되는지와 행동에 제약을 받지않는건지 궁금합니다.
-
미해결[유니티 레벨 업!] 모듈식으로 개발하는 스킬 시스템
다른형식의 근접공격에 대해 질문할것이 있습니다.
다크소울과 몬스터헌터 같은 게임의 근접공격 구현은 스킬의 액션에 새로운 액션을 만든 다음 피격 판정이 있는 무기에 콜라이더를 넣어준 다음 기존의 투사체 공격에 있는 소켓을 이용해서 구현하면 될까요
-
미해결[유니티 레벨 업!] 모듈식으로 개발하는 스킬 시스템
Input 스킬 구현 질문
안녕하세요! 좋은 강의 감사합니다. 리븐 Q와 아트록스 Q와 같이 Input형 스킬이면서 n번째 사용 스킬이 다른 경우(ex) 리븐 Q 3타 에어본) 어떻게 구현하면 좋을 지 질문 드립니다!
-
미해결[유니티 레벨 업!] 모듈식으로 개발하는 스킬 시스템
스텟 연동 관련해서 질문이 있습니다.
제가 기존에 개발해둔 아이템 시스템을 연동시키면서 아이템의 스텟을 정할때 Resources/Stat폴더를 참조하고 그걸 기반으로 Enum으로 해당 스텟들이 있는 스크립트 파일을 만든 다음에 아래에 있는 버튼을 눌러서 일일히 Enum 파일을 동기화시켰는데 너무 번거로운것 같습니다. 생성, 삭제, 수정할때마다 동기화시키면 작업할때마다 딜레이가 너무 커지는데 다른 방법이 있을까요if (dataType == typeof(Stat)){GUI.color = Color.yellow;// Data를 이름 순으로 정렬하는 Button을 그림if (GUILayout.Button($"Press it after you finish editing")){StatEnumSynchronizer.SyncStatEnum();EditorUtility.SetDirty(database);AssetDatabase.SaveAssets();}}아래는 해당 enum파일을 만드는 스크립트입니다.using System;using System.IO;using System.Linq;using UnityEditor;using UnityEngine;public static class StatEnumSynchronizer{private const string StatFolderPath = "Assets/Resources/Stat";[MenuItem("Tools/Sync Stat Enum")]public static void SyncStatEnum(){if (!Directory.Exists(StatFolderPath)){Debug.LogError($"Directory does not exist: {StatFolderPath}");return;}var statFiles = Directory.GetFiles(StatFolderPath, "*.asset", SearchOption.TopDirectoryOnly);var statCodeNames = statFiles.Select(file => AssetDatabase.LoadAssetAtPath<Stat>(file)).Where(stat => stat != null).Select(stat => stat.CodeName).Distinct().OrderBy(name => name).ToList();string enumPath = "Assets/Scripts/Enum/ItemStatusAttribute.cs";using (var writer = new StreamWriter(enumPath, false)){writer.WriteLine("public enum ItemStatusAttribute");writer.WriteLine("{");writer.WriteLine(" Default,");foreach (var codeName in statCodeNames){string enumName = SanitizeEnumName(codeName);writer.WriteLine($" {enumName},");}writer.WriteLine("}");}AssetDatabase.Refresh();Debug.Log("Stat Enum synchronized.");}private static string SanitizeEnumName(string name){return new string(name.Where(c => !char.IsWhiteSpace(c) && (char.IsLetterOrDigit(c) || c == '_')).ToArray()).Replace(" ", "_").Replace("-", "_").ToUpper();}}
-
미해결[유니티 레벨 업!] 모듈식으로 개발하는 스킬 시스템
텍스트 변환 Mark에 대하여 질문이 있습니다.
EffectAction에서public string BuildDescription(Effect effect, string description, int stackActionIndex, int stack, int effectIndex){ var stringsByKeyword = GetStringsByKeyword(effect); if (stringsByKeyword == null) return description; if (stack == 0) // ex. description = "적에게 $[EffectAction.defaultDamage.0] 피해를 줍니다." // defaultDamage = 300, effectIndex = 0, stringsByKeyword = new() { { "defaultDamage", defaultDamage.ToString() } }; // description.Replace("$[EffectAction.defaultDamage.0]", "300") => "적에게 300 피해를 줍니다." description = TextReplacer.Replace(description, "effectAction", stringsByKeyword, effectIndex.ToString()); else // Mark = $[EffectAction.Keyword.StackActionIndex.Stack.EffectIndex] description = TextReplacer.Replace(description, "effectAction", stringsByKeyword, $"{stackActionIndex}.{stack}.{effectIndex}"); return description;}여기 부분에서 왜 굳이 스택 0번째 인걸 구분하고 Effect에서 여기에서public string BuildDescription(string description, int effectIndex){ Dictionary<string, string> stringsByKeyword = new Dictionary<string, string>() { { "duration", Duration.ToString("0.##") }, { "applyCount", ApplyCount.ToString() }, { "applyCycle", ApplyCycle.ToString("0.##") } }; description = TextReplacer.Replace(description, stringsByKeyword, effectIndex.ToString()); description = Action.BuildDescription(this, description, 0, 0, effectIndex); // 여기부분에 질문이 있습니다 여기에서 0번째 것을 구분하고 var stackGroups = StackActions.GroupBy(x => x.Stack); foreach (var stackGroup in stackGroups) { int i = 0; foreach (var stackAction in stackGroup) description = stackAction.BuildDescription(this, description, i++, effectIndex); }// 여기에서 1스택이상 스킬의 텍스트를 전부 변환해주는데 return description;} EffectStackAction에서public string BuildDescription(Effect effect, string baseDescription, int stackActionIndex, int effectIndex) => action.BuildDescription(effect, baseDescription, stackActionIndex, stack, effectIndex);이렇게 까지 분리해서 텍스트로 변환하는지 여쭤보고 싶습니다.그냥 0번째부터 텍스트를 변환하면 안되는건지 질문이 있습니다.
-
미해결[유니티 레벨 업!] 모듈식으로 개발하는 스킬 시스템
스킬 구현 질문
잘 듣고 있습니다 강사님. 롤로 치면 그레이브즈 Q 를 구현하고 싶은데 Action을 Spawn Skill Object Action으로 하고 비슷한 파티클을 써서 해보니제 위치에서 나가는게 아니라 클릭한 기준으로 직선으로 나가더라구요 여러가지 방법을 시도 해보고 있는데 어떻게 해야할지 조언 부탁 드립니다!
-
미해결[유니티 레벨 업!] 모듈식으로 개발하는 스킬 시스템
Skill의 Custom Action 중 Action의 유니티 버그 레포트
안녕하세요 강의 잘 보고 있습니다.다름 아니라 Skill에 CustomAction의 Action 탭에서 Value값들을 바꿀려하면 유니티 버그 레포트가 나타나면서 유니티가 꺼지는 현상이 지속되고 있습니다.EX) Owner Or User를 Target으로 바꿀시 크래시...다른 Cast나 Charge, Preceding 쪽에선 문제가 발견되지 않습니다.스크립트상으론 강사님의 스크립트 그대로 가져와도 똑같은 문제가 발생하는 것 같은데 아님 혹시 제가 놓친 부분이 있나 싶어서 문의드립니다.
-
미해결[유니티 레벨 업!] 모듈식으로 개발하는 스킬 시스템
Statemachine 관련질문이 있습니다.
격투게임이나 몬스터헌터처럼 애니메이션의 특정 프레임 이후에 입력받아야 특정 애니메이션이 실행가능하게 하려하는데 이걸 어떻게 해야할까요?기존에는 애니메이션 이벤트를 이용해서 구현했었는데 어떻게 해야할까요?애니메이션 이벤트를 활용하려고 하니 오버로드된 함수들 때문에 이런 경고창이 뜨긴하는데 애니메이션 이벤트의 함수들은 오버로드된 함수들이 아니라 괜찮은가요?아니면 다른 좋은 방법이 있는지 알려주실수있을까요?
-
해결됨[유니티 레벨 업!] 모듈식으로 개발하는 스킬 시스템
StateMachine중에 이해가 안가는 부분이 있습니다
TryTransion함수에서if (transition.TransitionCommand != StateTransition<EntityType>.kNullCommand || !transition.IsTransferable) continue;이부분에서 나눠서 짜면if (커맨드있음) continue;if (전이불가) continue;인데 사실상 커맨드가 있으면 뒤에 전이상태는 상관이 없다고 생각을 하는데요.그런데 이제 StateMachine을 상속한 클래스에서 MakeTransition을 한것을 보면MakeTransition<ReadyState, CastingState>(SkillExecuteCommand.Use, state => Owner.IsUseCast);이런식으로 커맨드와 조건을 같이 써놓은것이 있는데, 뒤에는 작동이 안되지 않나라고 생각해서 제가 잘못해석한건지 알아보고자 질문드립니다.
-
미해결[유니티 레벨 업!] 모듈식으로 개발하는 스킬 시스템
스킬제작 질문입니다
리그오브레전드로 예시를 많이 드셨는데 바루스 Q나 비에고W같은 스킬은 어떻게 제작할 수 있을까요.간단한 힌트를 부탁드립니다..
-
미해결[유니티 레벨 업!] 모듈식으로 개발하는 스킬 시스템
DrawFoldoutTitle에 질문이 있습니다.
CustomEditorUtility에 있는public static bool DrawFoldoutTitle(string title, bool isExpanded, float space = 15f)와 public static bool DrawFoldoutTitle(IDictionary<string, bool> isFoldoutExpandedesByTitle, string title, float space = 15f)이 각각 있는데 첫번째 DrawFoldoutTitle에서 space 값을 변경해도 두번째의 DrawFoldoutTitle에있는isFoldoutExpandedesByTitle[title] = DrawFoldoutTitle(title, isFoldoutExpandedesByTitle[title], space);여기 때문에 변경이 안되는거고 타이틀이 여러개 있을경우를 대비해서 여러개 각각의 간격을 위한건가요
-
해결됨[유니티 레벨 업!] 모듈식으로 개발하는 스킬 시스템
deadstate 질문입니다
deadstate에서 에니메이션이 다 재생된후 destroy를 할려면 어떻게 해야할까요따로 함수를 만들어 애니메이션 트리거로 destroy를 하고 있는데 더 나은 방법이 있을까 해서 질문해봅니다
-
미해결[유니티 레벨 업!] 모듈식으로 개발하는 스킬 시스템
현업에서 OdinInpector도 자주 쓰이나요??
OdinInspector를 구매해 둔 김에 사용해보고 싶어서 강의를 따라가며 Editor코딩 부분을 Odin으로 해볼까 싶은데요일단 기본적인 Editor코딩 경험 vs OdinInspector사용 경험둘 중에 어떤 것을 더 추천하시나요??
-
해결됨[유니티 레벨 업!] 모듈식으로 개발하는 스킬 시스템
이런 스킬시스템을 저장하는 방법
강의 모두 잘들었습니다. 공부한 내용을 바탕으로 스킬시스템을 넣은 게임을 만드려고 합니다. 추가로 파이어베이스의 리얼타임 데이터베이스까지 사용해서 세이브/로드 기능도 구현하려고 하는데, 이때 Json으로 저장하는 부분에서 어려움을 느끼고 있습니다. 우선 제가 알고있는 수준은 string json = JsonUtility.ToJson(player); 같이 ToJson으로 변환해서 저장하는 정도입니다. 다만 이 방법으로는 int,string,float 같은 기본 자료형만 저장이 가능한데, 이때 Entity가 들고있는 저장해야하는 데이터들. 여기서는 SkillSystem과 Stats도 저장에 포함되어야겠죠 스탯과 스킬이니깐. 이런 것들은 어떤식으로 저장을 구현하는지 마땅히 떠오르지 않습니다..멀티 게임은 아니고 싱글게임에 서버만 입혀주는 정도기 때문에 Player(강의의 Entity)의 다양한 데이터를 저장하는 방법을 알아야 하는데, 이 강의에서 나오는 현재 플레이어가 보유한 스탯,스킬의 정보는 어떤식으로 저장을 해야하나요? 최대한 쉽게.. 알려주시면 정말 너무 감사하겠습니다 ㅠㅠ 어려워요..
-
미해결[유니티 레벨 업!] 모듈식으로 개발하는 스킬 시스템
유니티 2023.1을 쓰는 이유가 따로 있는지 궁금합니다.
최신 버전이라서 쓰는 건가요? 아니면 최신 버전에서 지원하는 기능이 있는 걸까요?강의를 이제 듣기 시작해서 한 번 여쭤봅니다!