묻고 답해요
141만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결[켠김에 출시까지] 유니티 방치형 키우기 게임 (M1 + T2)
resoureceManager.cs질문
이전 유니티강의에서는public class ResourceManager { public T Load<T>(string path) where T : Object { return Resources.Load<T>(path); } public GameObject Instantiate(string path, Transform parent = null) { GameObject prefab = Load<GameObject>($"Prefabs/{path}"); if (prefab == null) { Debug.Log($"Filed to load prefab : {path}"); return null; } return Object.Instantiate(prefab, parent); } public void Destroy(GameObject go) { if (go == null) return; Object.Destroy(go); } } 로 로드할때 path안에 T타입에 해당하는것들을 찾아서 로드했는데 public class ResourceManager { private Dictionary<string, UnityEngine.Object> _resources = new Dictionary<string, UnityEngine.Object>(); private Dictionary<string, AsyncOperationHandle> _handles = new Dictionary<string, AsyncOperationHandle>(); #region Load Resource public T Load<T>(string key) where T : Object { if (_resources.TryGetValue(key, out Object resource)) return resource as T; return null; } public GameObject Instantiate(string key, Transform parent = null, bool pooling = false) { GameObject prefab = Load<GameObject>(key); if (prefab == null) { Debug.LogError($"Failed to load prefab : {key}"); return null; } if (pooling) return Managers.Pool.Pop(prefab); GameObject go = Object.Instantiate(prefab, parent); go.name = prefab.name; return go; }이번 강의에 것은 Dic으로 담아둘곳은 만들었는데 어디서 찾아서 Dic에다 담아두고 Load로 값을 반환하는지 모르겠습니다 모르겠습니다. 다시 계속 코드를 봤는데_resource라는 dic형태 데이터에 #region Addressable private void LoadAsync<T>(string key, Action<T> callback = null) where T : UnityEngine.Object { // Cache if (_resources.TryGetValue(key, out Object resource)) { callback?.Invoke(resource as T); return; } string loadKey = key; if (key.Contains(".sprite")) loadKey = $"{key}[{key.Replace(".sprite", "")}]"; var asyncOperation = Addressables.LoadAssetAsync<T>(loadKey); asyncOperation.Completed += (op) => { _resources.Add(key, op.Result); _handles.Add(key, asyncOperation); callback?.Invoke(op.Result); }; } _resources.Add(key, op.Result);이 부분에서 데이터를 채워주는것 맞나요? 라이브강의 점점따라가기 힘들어서 시간날때 뒤에서부터 하나하나 계속 보고있습니다.. 강의를 다시보니 LoadAsync가아니라 LoadAllAsync에서 싹다 긁어서 dic데이터형태의 _resource에 메모리상에 들고있겠다로 해석되는데 맞나요?
-
미해결[켠김에 출시까지] 유니티 방치형 키우기 게임 (M1 + T2)
로드완료후 터치해서 게임신으로 넘어가면 생기는 오류입니다.
NullReferenceException: Object reference not set to an instance of an objectObjectManager.Spawn[T] (UnityEngine.Vector3 position, System.Int32 templateID) (at Assets/@Scripts/Managers/Contents/ObjectManager.cs:38)GameScene.Init () (at Assets/@Scripts/Scenes/GameScene.cs:24)InitBase.Awake () (at Assets/@Scripts/Utils/InitBase.cs:20)
-
해결됨[켠김에 출시까지] 유니티 방치형 키우기 게임 (M1 + T2)
6강 ObjectManager에서 UI_Joystick
UI_Joystick 컴포넌트를 학습하는 도중에 궁금사항이 생겨 질문 드립니다.강의 중에 처음에 RawImage가 달리지 않은 오브젝트를 이용할때는 클릭했을때 조이스틱의 위치가변경되는 범위가 조이스틱 오브젝트가 있는 부분에서만 되었다가RawImage가 추후 부착된 프리펩을 이용했을때는 RawImage의 범위에 속하는곳에 어느곳에터치를 해도 조이스틱 위치가 이동이 되었는데.유니티를 아직 잘 다루지 못해서 추측해서 이해를 했는데 맞는지 한번 확인 부탁 드리겠습니다. public class UI_Joystick : UI_Base { enum GameObjects { JoystickBG, JoystickCursor, } private GameObject _background; private GameObject _cursor; private float _radius; private Vector2 _touchPos; public override bool Init() { ... gameObject.BindEvent(OnPointerDown, type: Define.EUIEvent.PointerDown); gameObject.BindEvent(OnPointerUp, type: Define.EUIEvent.PointerUp); gameObject.BindEvent(OnDrag, type: Define.EUIEvent.Drag); return true; }해당 스크립트에서 BindEvent로 연결해준 부분이 GetObject로 달아준 하위 오브젝트가 아니라컴포넌트가 달린 UI_Joystick 캔버스 자체에 이벤트를 달아주어서캔버스 자체에는 Raycast Target이 없기 클릭을 해도 이벤트 인식이 안되서Raycast Target이 활성화된 하위 오브젝트를 눌렀을때 이벤트가 발생이 되어서 처음에는 조이스틱 부에서만작동이 됬던것이 맞는가요?그게 맞다면 오브젝트 자체에 이벤트를 달아주게 되면, 그리고 그 오브젝트에 이벤트를 인식하는 Raycast Target가 비활성화 되어있거나 관련된 컴포넌트가 없다면, 그 이벤트가 달린 오브젝트의 모든 하위 오브젝트에 Raycast Target 상태를 확인해서 활성화 되어 있다면 하위 오브젝트에 모두 이벤트가 동작되게 되는것 인가요?
-
미해결[켠김에 출시까지] 유니티 방치형 키우기 게임 (M1 + T2)
DataManager을 훑어보던 도중에 궁금한점이 있습니다.
public interface ILoader<Key, Value> { Dictionary<Key, Value> MakeDict(); } public class DataManager { public Dictionary<int, Data.TestData> TestDic { get; private set; } = new Dictionary<int, Data.TestData>(); public void Init() { TestDic = LoadJson<Data.TestDataLoader, int, Data.TestData>("TestData").MakeDict(); } private Loader LoadJson<Loader, Key, Value>(string path) where Loader : ILoader<Key, Value> { TextAsset textAsset = Managers.Resource.Load<TextAsset>(path); return JsonConvert.DeserializeObject<Loader>(textAsset.text); } } namespace Data { #region TestData ... [Serializable] public class TestDataLoader : ILoader<int, TestData> { public List<TestData> tests = new List<TestData>(); public Dictionary<int, TestData> MakeDict() { Dictionary<int, TestData> dict = new Dictionary<int, TestData>(); foreach (TestData testData in tests) dict.Add(testData.Level, testData); return dict; } } ... #endregion }TestDic = LoadJson<Data.TestDataLoader, int, Data.TestData>("TestData").MakeDict();DataManager의 위 라인을 실행할 때 TestDataLoader 의 tests 리스트에 값을 담거나 하는 명시된 부분이 없는것 같은데 어떻게 MakeDict(); 가정상적으로 실행될 수 있는것 인가요?신기해서 이유를 알고싶어 질문 드립니다.[Serializable]를 명시하면 리턴되는 JsonConvert.DeserializeObject<Loader>(textAsset.text); 의 값이 알맞은 변수에자동으로 담기는 것인가요?
-
미해결[켠김에 출시까지] 유니티 방치형 키우기 게임 (M1 + T2)
람다식에 대해서 궁금증이 있습니다..
프레임워크 코드를 보면서 공부중에 람다식에 대해 궁금증이 생겨서 질문을 남깁니다..프레임워크상으로 람다식으로 액션을 할당하고 있는데, 람다식에 대해 공부를 해봐도 잘 이해가 가지 않아서..위에 매개변수로 넣는 evt는 람다식으로 작성한 Debug.Log("ChangeScene");Managers.Scene.LoadScene(EScene.GameScene);의 내용이 들어감 액션 함수의 이름이라고 볼수있는걸까요?인터넷에 있는 람다식에 대한 영상이나 자료들을 아무리봐도 강사님의 프레임워크처럼 효율적으로 직접 사용하는 부분에 대해서는 내용을 찾을 수가 없어서 공부하는데 힘이드네요..람다식에 대해 설명을 부탁드리겠습니다..혹시 내용이 많아 힘드시다면 공부하기위한 자료가 있을까요?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
LNK1104 'Debug\ServerCore.lib' 파일을 열 수 없습니다. 에러 질문
안녕하세요! Lock-Based Stack / Queue 강의부터 수업 자료를 다운로드 받아서 실행 시킬 경우 위와 같은 에러가 발생합니다. 라이브러리 파일을 열 수 없다고 뜨는데, 이에 대한 원인을 찾아 보고 있으나 진전이 없어서 무엇이 문제일까 여쭤봅니다.
-
해결됨[켠김에 출시까지] 유니티 방치형 키우기 게임 (M1 + T2)
5월 서버 기본기관련되서 질문이있습니다.
5월 서버 강좌를 듣기전에 미리 예습을 하고자하는데,강사님 강의중에Part4 : 게임 서버 (네트워크, 멀티쓰레드, OS)Part5 : 데이터베이스(SQL Server)Part6 : 웹서버 (ASP.NET Core Blazor, WebApi) 현재 강의Part7 : MMORPG 컨텐츠 구현 (Unity + C# 서버 연동)부분을 미리 공부해야할까요?? 해당 파트 내용들이 지금 강의에서 중심적으로 다루어지는지 알고 싶습니다.
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
Select 모델을 사용해야 하는 이유
강의를 수강하던중 Select 모델과 (Non)blocking의 차이점에 궁금증이 생겨 질문을 남기게 되었습니다. Select를 사용하기전 Blocking, Non-blocking 방식에서도 해당 소켓의 정상/비정상 상태를 확인하여 패킷을 전송하는 것으로 이해하였습니다. 그중 Non-blocking은 명칭적으로는 정상/비정상에 큰 신경을 쓰지 않지만 소켓의 상태가 정상/비정상인지 확인하는 과정을 거치기에 자원 손실이 일어나는 것으로 이해됐습니다. 이런 단점을 해결하기 위해 Select 모델을 이용해 send, write에 소켓을 저장해 해당 소켓이 정상인지, send, recv 중 어떤 소켓을 진행해야 할지, 준비되었는지 판단하는 과정이 Blocking과 Non-blocking에서의 상태 파악 과정과 비슷하다는 생각이 들어 Select 모델을 사용하는게 별 다른 이점이 없지 않나? 라는 생각이 들어 질문을 남기게 되었습니다.
-
미해결[켠김에 출시까지] 유니티 방치형 키우기 게임 (M1 + T2)
현제 몬스터 ai로는 아이들 상태일때만 플레이어 판별하는거죠?
아이들 상태일때만 플레이어를 판별하고 있는게 맞을까요?만약 Patrol로 인한 무브 상태일때는 플레이어가 가까이 와도 플레이어를 판별못해서 이동만하고 있는 상태가 되는게 맞는걸까요?
-
해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
SocketUtils::SetTcpNoDelay 부분 오타
bool SocketUtils::SetTcpNoDelay(SOCKET socket, bool flag) { return SetSockOpt(socket, IPPROTO_TCP, TCP_NODELAY, flag); }로 코드를 고쳐주어야 할 것 같습니다. (SOL_SOCKET -> IPPROTO_TCPSOL_SOCKET, TCP_NODELAY로 인자를 넣어주면 SO_DEBUG 옵션을 대신 설정해주게 됩니다. 현재 기준으로 마지막 코드까지 오타가 수정되어 있지 않으니 혹시 실제로 서버를 사용하실 분들은 해당 코드를 수정하여 사용하시는걸 권장드립니다.
-
미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part9: MMO 컨텐츠 구현 (DB연동 + 대형 구조 + 라이브 준비)
해당 강의를 완강하면 실제 여러 대 PC의 환경에서 MMO구현이 가능할까요?
안녕하세요. 간단히나마 실제 멀티게임 구현을 목표로 이전 강의(Part7)들 듣고 있습니다. 아직 Part7을 듣고 있어서 그런데 해당 강의 Part9를 들으면 실제 서버 전용 PC를 두고 여러개의 클라PC가 각 .exe파일을 실행하는 환경을 구축하는 내용이 포함되어 있을까요? 만약 그렇지 않다면, 다른 강의에서는 혹시 위 내용이 포함된 강의가 있을까요? 루키스님은 물론이고, 다른 수강자 선배님들, 인프런 AI 인턴 답변 모두모두 환영합니다. 답변 미리 감사합니다.
-
해결됨[켠김에 출시까지] 유니티 방치형 키우기 게임 (M1 + T2)
5월 부터는 서버를 구현한다고 되어있는데!
안녕하세요 5월부터 시작하는 수업에서BM (광고, 결제) 시스템과 서버 기본기 구현을 배우게 되는것으로 알고있는데요!이과정에서 c#과 AWS를 사용하여 직접 서버를 구축하는 방법을 배우는것인지아니면 파이어베이스나 뒤끝같은 관리형 서비스를 사용하는 방법을 배우는건지 궁금합니다 !
-
해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
Conditional Variable 과 Event에 대해 이해하고 싶습니다.
제가 이해한것이 맞는지 확인하고 싶어 질문을 남기게 되었습니다. Event는 Signal, Non-Signal 상태를 WaitForSingleObject(handle, INFINITE)를 통해 대기합니다.여기서 INFINITE로 무한정 대기를 통해 불필요한 컨텍스트 스위치가 일어나지 않게 됩니다.하지만 그만큼 자원(메모리? CPU? )의 손해가 일어나기에 생겨난 것이 Conditional Variable입니다. Conditional Variable cv.notify_one();를 통해 대기하고 있던 Thread를 실행합니다. Conditional Variable는 메모리에 Thread를 Wait 시키지 않고 대기 시키다가 cv.notify_one();를 통해 실행하는 것이고 Event는 Thread를 메모리에 WaitForSingleObject(handle, INFINITE)를 통해 대기시켰다가 SetEvent(handle);를 통해 실행시킨 점이 차이라고 이해하면 될지 여쭙고 싶습니다.
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
buffsOffset을 사용하는 이유가 궁금합니다.
안녕하세요 지난 강의 '패킷직렬화 #1' 부터 현재강의에서 buffsOffset을 사용하는데 이 변수가 존재해야 하는 이유를 모르겠습니다.sizeof(PKT_S_TEST)를 이용하면 되는게 아닌지 자꾸 의문이 들어서요.sizeof(PKT_S_TEST)를 이용해서는 안되는 경우가 있어서 buffsOffset을 사용하는 걸까요?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
ObjectPool.h Push에는 괄호를 안쓴 이유가 무엇일까요
ObjectPool.h에서 게임서버쪽에서 MakeShared를 사용할때도 메모리 풀이 적용되게해주는 함수인데여기서 Push는 왜 괄호를 안쓴걸까요 ?? static shared_ptr<Type> MakeShared() { shared_ptr<Type> ptr = { Pop(), Push}; return ptr; } GameServer.cpp에서 이미 아래와 같이 인자를 전달해서 그런걸까요..??왜 이렇게 되는지 궁금합니다..ObjectPool<Knight>::Push(knights[i]);
-
미해결[켠김에 출시까지] 유니티 방치형 키우기 게임 (M1 + T2)
하반기 MMO 서버 개발
하반기 MMO 서버 개발은 c# or c++ 뭐로 개발할 예정이신가요?
-
해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
UniqueLock과 Lock의 차이점이 궁금합니다.
uniquelock은 lock_guard와 달리 std::unique_lock<std::mutex> uniqueLock(m, std::defer_lock);를 통해 명시해놓고 자신이 원하는 순간에 uniqueLock.lock 을 할 수 있다고 이해하였습니다. 일반적인 Lock과의 차이점은 자신이 원하는 순간에 lock을 거는 것은 똑같지만lock_guard와 같이 unlock과 같이 명시를 해주지 않더라도 일정 부분이 끝나게 되면 자동으로 unlock이되는 것이라고 이해해도 괜찮을까요?
-
미해결[켠김에 출시까지] 유니티 방치형 키우기 게임 (M1 + T2)
UIManager의 SetCanvers() 부분에서
안녕하세요..UIManager 의 SetCanvas 에서public void SetCanvas(GameObject go, bool sort = true, int sortOrder = 0) { Canvas canvas = Util.GetOrAddComponent<Canvas>(go); if (canvas == null) { canvas.renderMode = RenderMode.ScreenSpaceOverlay; canvas.overrideSorting = true; }"if (canvas == null)" 부분이 "canvas != null" 이 되어야 될 것 같은데 설명 부탁드립니다.
-
미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part9: MMO 컨텐츠 구현 (DB연동 + 대형 구조 + 라이브 준비)
Room마다 Thread를 만들기
안녕하세요 루키스님 덕분에 서버개발자로 취업하였습니다.루키스님의 강의를 체화하기 위해서 간간히 코드를 보면서 잊어먹을랑 말랑한 것들을 다시 강의로 듣곤 합니다그러다가 아래 코드를 보면서 문득 의문이 들었는데요.while(true) { GameLogicTask.Instance.Update() }게임 실행 시 위 로직을 타면서 메인쓰레드 하나서 모든 Room의 Update를 담당하고 있는데Room에 유저수가 많아지게 되면 메인 쓰레드에 점점 부하가 더 많아지는게 아닌가해서 질문을 드립니다.메인쓰레드 부하가 많아지면 컨텍스트 스위칭이 생겨도 Room마다 Thread를 생성하여남은 자원을 Update가 바쁘게 돌아가는 Room쪽에 쓰레드를 조금 더 할당해 주어도 될까요?(밑에 질문에 답변해 주셨네요 ^^; Room마다 쓰레드를 더 만들겠습니다.) 심리스 월드에서 Actor마다 JobSerializer를 할당하는 방법을 쓰면,쓰레드를 너무 많이 만들게 될것 같은데 컨텍스트 스위칭 외에 또 생기는 성능적인 사이드 이펙트를 뭘 또 고려하면 좋을까요?Actor마다 JobSerializer를 쓴다고 하면 Actor단일로서는 lock을 걸지 않아도 되지만서로 상호작용이 일어나는 상황에서는 어쩔수 없이 lock을 걸어줄수 밖에 없을 것 같은데, 그러면 결국은 JobSerializer를 쓰지 않아도 되지 않나 부족한 지식으로 어렴풋이 생각이 듭니다.또한 JobSerializer를 Flush 하기 위해선 Actor마다 while(true) 루프를 돌면서 계속해서 잤다가 깼다가 확인 하는 과정과 컨텍스트 스위칭비용이 점점 더 늘어날 것 같은데 이런 비용을 감안하면서 사용하는 것인지요. 아니면 딱히 신경쓰지 않아도 될만한 부하인지 궁금합니다.
-
미해결[켠김에 출시까지] 유니티 방치형 키우기 게임 (M1 + T2)
UI_TitleScene에서 bindevent
GetObject((int)GameObjects.StartImage).BindEvent((evt) => { Debug.Log("ChangeScene"); Managers.Scene.LoadScene(EScene.GameScene); });에서 bindevent()로 extention의public static void BindEvent(this GameObject go, Action<PointerEventData> action = null, Define.EUIEvent type = Define.EUIEvent.Click) { UI_Base.BindEvent(go, action, type); }로 오고 여기서 UI_Base에 있는 public static void BindEvent(GameObject go, Action<PointerEventData> action = null, Define.EUIEvent type = Define.EUIEvent.Click) { UI_EventHandler evt = Util.GetOrAddComponent<UI_EventHandler>(go); switch (type) { case Define.EUIEvent.Click: evt.OnClickHandler -= action; evt.OnClickHandler += action; break; case Define.EUIEvent.PointerDown: evt.OnPointerDownHandler -= action; evt.OnPointerDownHandler += action; break; case Define.EUIEvent.PointerUp: evt.OnPointerUpHandler -= action; evt.OnPointerUpHandler += action; break; case Define.EUIEvent.Drag: evt.OnDragHandler -= action; evt.OnDragHandler += action; break; } }로 참조해서 가져오는것 맞나요? 궁금한것은 지금 define에 4가지 evt상태를 만들어놨는데 pointdown-누를때pointup-땔때drag-드래그Click-클릭 지금은 제일위에 object.bindevent(evt)=> 여기에 evt로 4가지 전부 받아지는것아닌가요? 강의를 다시보니 loadAysync로 전부 로드완료한뒤에 클릭하면 된다고 되어있는데 그냥 4가지 전부 evt로 가져와지고 제일먼저 입력된 click이 받아와지는건가요? pointdown은 누를때 이벤트가 전송되면 pointdown으로 evt가 받아와져야 되는것 아닌가요?