이건 샘 화면이고 이건 제 맥북 vs 화면입니다. Hello Thread! 다섯번이 결과로 안나오네요 ㅠㅠ 챗지피티에 물어봤더니 아래와 같이 답을 줍니다. .NET ThreadPool은 개발자가 작업을 실행할 스레드 풀을 할당하여 여러 작업을 동시에 실행할 수 있도록 하는 메커니즘입니다. 그러나 Mac의 Visual Studio에서 ThreadPool 기능 문제에 대한 보고가 있었습니다. 이 문제에 대한 한 가지 잠재적인 이유는 Windows와 macOS 간의 기본 운영 체제 및 런타임 환경의 차이 때문일 수 있습니다. 또 다른 가능성은 Visual Studio의 두 버전 간에 ThreadPool 기능 구현의 차이일 수 있습니다. Mac의 Visual Studio에서 ThreadPool에 문제가 발생하는 경우 문제를 해결할 수 있는 업데이트 또는 패치를 확인하고 문제를 일으킬 수 있는 잠재적인 문제에 대한 코드를 검토하는 것이 좋습니다. 다른 플랫폼에서 더 나은 성능과 안정성을 제공할 수 있는 async/await 또는 TPL(Task Parallel Library) 사용과 같은 동시성에 대한 대체 접근 방식을 탐색하는 것도 가능합니다.
NullReferenceException: Object reference not set to an instance of an object Utill.GetOrAddComponent[T] (UnityEngine.GameObject go) (at Assets/Script/Utills/Utill.cs:10) UIManager.ShowPopupUI[T] (System.String name) (at Assets/Script/Mangers/UIManager.cs:23) PlayerControler.Start () (at Assets/Script/PlayerControler.cs:67) 먼저 오류 메시지는 이것입니다. 저는 UI_Button 프리펩 위치 Resources-Prefabs-UI-Popup폴더에 있구요 UIButton 스크립트 Scripts-UI-Popup 폴더에 있습니다. 이제 코드는 Utill.cs:10 -> T component = go.GetComponent<T>(); UIManager.cs:23 -> T popup = Utill.GetOrAddComponent<T>(go); PlayerControler.cs:67 ->Managers.UI.ShowPopupUI<UIButton>(); 실행 전 UI_Button 프리펩 딜리트했다가 하이라키에 있는 UI_Button 오브젝트를 다시 프리펩화 한다음 그 오브젝트는 다시 딜리트 하여 실행 해본 결과 UI_Button가 뜨지 않고 저 에러만 납니다. 뭐가 문제일까요 ???
GetButton((int)Buttons.ChapterButton_1).gameObject.BindEvent(() => { OnClickChapterButton(1); }); UI_SelectStageScene.cs 에서 왼쪽에 배치된 챕터 버튼들 같은 경우에는 위처럼 바인드해서 ChapterButton_1 은 OnClickChapterButton 메서드에 1을 전달하니까 너무 직관적인데요 Stage는 잘 이해가 안가요 ㅠㅠ for (int i = 0; i < _stageBlockUI.Length; i++) { _stageBlockUI[i] = Utils.FindChild<UI_StageBlock>(gameObject, "UI_StageBlock" + (i + 1), recursive: true); } Child에서 "UI_StageBlock" 를 전부 찾아서 _stageBlockUI[i] 에 저장하고 UI_StageBlock.cs 에서 아래처럼 바인드를하고..? GetButton((int)Buttons.SelectStageButton).gameObject.BindEvent(OnClickStageButton); OnClickStageButton() 으로 넘어가서 _selectStageSceneUI?.OnSelectStage(_stage); OnSelectStage를 실행하면서 _stage를 전달하는데 _stage가 몇인지는 어디서 판단하는건지 모르겠어요. 그러다보니 Refresh()함수에서도 _stage로 Text입히는것도 연결이 안되네요. 그리고 눌렀을때 콜백을 받아서 ShowStartStagePopup()으로 넘어가는데 public void ShowStartStagePopup() { Managers.UI.ShowPopupUI<UI_StartStagePopup>(callback: (popup) => { int templateID = (_selectedChapter - 1) * 20 + _selectedStage; popup.SetInfo(Managers.Data.Stages[templateID]); }); 여기서도 tempateID 를 가져오기 위한 _selectedStage가 몇스테이지인지 어디서 판단하는건지를 모르겠어요 ㅠㅠ 저만 계속 질문하는것 같아 너무 죄송스럽습니다. C# 1편이랑 3편이랑 하고 넘어왔는데도 여전히 어려워요... 자꾸 질문하는게 죄송스러워서 맘편히 질문만 할수있는 강의 그런거라도 있으면 구입하고싶어요. 좋은 주말되세요!
[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part7: MMO 컨텐츠 구현 (Unity + C# 서버 연동 기초)
안녕하세요 강사님 30분경에 '실질적으로 지금보다 좀 더 복잡한 MMO가 되면 불러와야 할 정보들을 클라에게 먼저 알려준 다음 클라에서 모든 정보 불러오기가 끝났으면 서버쪽에 준비됐다고 ok패킷을 날리게 되고 ok패킷을 받고나서야 서버쪽에서 게임에 입장 시킨다고 하시면서 여기까지는 구현하지 않을거라고 하셨는데 해당 내용이 나중에 강의중에(다른파트에서라도) 나오는지 궁금합니다! 혹시 강의중에 해당 내용이 없다면 구글링 검색어를 뭘로 하면 좋을지 알려주시면 감사하겠습니다!
안녕하세요. 만약에 타격시 소리를 추가한다고 한다면PlayerController 클래스의 OnHitEvent 메서드에서 Managers.Sound.Play를 호출해서 재생시키면 될것 같아요. 근데 또 특정 UI 가 켜지고 꺼질때나 플레이어가 죽을때 등등 많은 부분에서 사운드를 재생하는게 필요할텐데 그때마다 Managers를 호출해서 Sound를 재생시키면 안될것 같다는 느낌이 왠지 들어요. 너무 여러곳에서 Managers를 호출하면 코드가 꼬이지 않을까 하는 걱정이요. 그래서 InputManager를 구현한것 처럼 Action을 사용해서 다른곳에서 Sound 재생을 등록시키는게 더 나은 방법일까요..? GameScene이라는 곳에서 여러 Manager들을 호출해서 게임에 관련된 작업을 하는건 합리적으로 느껴지는데 다른곳에서도 Managers를 계속 호출하는게 괜찮은지 여쭤봅니당
List<int>[] adj2 = new List<int>[] { // new List<int> 뒤에 () 를 넣지 않아도 오류가 안나던데요. // ( 소괄호 ) 를 넣어도 안넣어도 되는건가요? // 선생님은 new List<int>(){ 1, 3} 이렇게 하셨습니다. new List<int>{ 1, 3}, new List<int>{ 0, 2, 3}, new List<int>{ 1}, new List<int>{ 0, 1, 4}, new List<int>{ 3, 5}, new List<int>{ 4} }; 또 잘이해가 안되는점이. 아래 링크한 블로그에서는 (소괄호) 가 이런식으로 있습니다. List<List<string>> list = new List<List<string>>(); https://codechacha.com/ko/csharp-init-2d-list/
if (rand.Next(0, 2) == 0) { Tile[y, x + 1] = TileType.Empty; count++; } else { int randomIndex = rand.Next(0, count); Tile[y + 1, x - randomIndex * 2] = TileType.Empty; count = 1; } 만약에 (1, 1) (1, 2) (1, 3) 이렇게 세 지점이 연속해서 뚫려있을 경우, (1, 0) 부터 보았을 때 (빨) (초) (빨) (초) 이런 상태에서 시작했다고 가정한다면.. x == 3 일 때 count 는 2 가 되고, 그렇기 때문에 randomIndex = {0, 1} 이 가능합니다. randomIndex = 0 일 경우 새로 뚫릴 지점의 좌표는 (2, 3) 이 되고, 1일 경우 (2, 1) 이 됩니다. 따라서 이 경우에 (2, 2) 지점은 뚫릴 가능성이 없습니다. >> 위에서 제가 이해한 것이 맞는건지 궁금합니다. 왜 이렇게 헷갈리는지 모르겠네요..
안녕하세요. 초보자이며 프로젝트 규모가 작다면 어드레서블을 굳이 사용할 필요가 없다는 말씀 듣고 질문드립니다. 기존의 Resource에서 로드하는 방식이 코드도 간결하고 쉬웠는데 어드레서블은 조금 복잡하네요 ㅠㅠ 제가 이해한 바로는 초기 빌드 용량이 커지거나 로딩 시간이 길어질때 씬 이동이 자주 일어나거나 해서 불필요한 메모리를 계속 들고있을 필요가 없을때 추후 빌드없이 패치를 구현하고 싶을때 등등에서 어드레서블 사용이 권장되는 것 같은데 제가 만드려는 게임에서 어드레서블이 필수인지 판단이 어렵네요. 그래서 혹시 강사님께서는 프로젝트에서 어드레서블을 사용하는 것이 효율적일것 같다 라고 판단하시는 어떤 기준이 있으신가 해서 질문드립니다. 항상 좋은 강의 감사드립니다!
public class ResourceManager { public T Load<T>(string path) where T : Object { return Resources.Load<T>(path); } } where T를 제거하면 오류가 뜨는데 그 이유가 있을까요 Managers쪽에 있는 ResourceManager resource = new ResourceManager(); 부분에서 궁금한점이 Managers s _instance는 싱글톤으로 유일성이 보장되었고 public static ResourceManager Resource{ get { return Instance._resource; } } 이런식으로 이루어 지는데 resource도 유일성이 보장되는 것인지 아니면 다른 곳에서 Managers.Resource가 호출되면 new ResourceManager로 새로운 _resource가 호출되는지 궁금합니다
안녕하세요! 강사님. 클라이언트를 500명으로 늘렸을 때 말로 설명해주신 부분에서 이해는 가는데, 일부분이 정확하게는 이해가 가지 않는 부분이 있습니다. 작업이 밀려버리면 스레드풀에서 보낸 스레드가 돌아오지 않으니 새로운 스레드를 만들기때문에 메모리가 점점 찬다 -> 스레드가 패킷을 async하게 recv한 다음 jobqueue에 push를 할 때, push 하기위해 lock이 있으니 해당영역에서 병목현상이 발생하고, 그로인해 blocking된 스레드가 오지 않으니 스레드풀에서 새 recv가 오면 스레드 재사용이 아니라 새 스레드를 할당하기 때문에 스레드는 각 스레드별로 stack을 가지고 있기 때문에 이런 스레드별로 가지고있는 용량이 계속 증가하는거라서 메모리가 늘어난다. 라고 이해를 했었습니다. 그런데 나중에 다시 말씀해 주셨을 때, 일이 계속 밀리면, 스레드풀에서 스레드가 돌아오지 않으니 새로운 스레드를 만들고, sendbuffer에서 큰 단위의 버퍼에서 짤라서 사용하는걸로 구현했기 때문에 메모리가 계속 늘어난다. 라고 하셨는데, sendbuffer는 여러 스레드가 큰 버퍼에서 짤라서 각자 쓰는 것으로 이해를 했었어서 여러 스레드가 써도 큰 버퍼는 그대로고 얼마나 sendbuffer를 사용하는 횟수가 많아지냐. 가 달라지는거라고 생각이 들었는데,,, 그게 아닌가요? sendbuffer에서 큰 단위의 버퍼에서 짤라서 사용하는 것이 메모리 증가에 무슨 영향이 있는지 잘 이해가 되지 않습니다.
안녕하세요, 강사님! GameRoom에서 client -> server로 보낸 메세지를 다른 client들에게 broadcasting을 하는데, 그래서 출력 결과가 10개씩 나오는 이유가 10개의 클라이언트들이 보낸걸 다시 반환하는것이기 때문에. 즉, 반사가 10개씩 나오는거고, 근데 클라이언트 console창이 하나로만 되어있다보니 10개의 클라이언트가 받은 반사메세지가 한번에 출력되어 10개씩 출력되는 것이라고 이해를 했습니다. 그런데 각 session이 어떤 순서로 반사를 받는지 궁금하여 client의 serversession에도 sessionid를 부여하고 테스트로 출력을 해 본 결과 아래와 같았습니다. session이 send 를 하는 것은 async로 구현하였기 때문에 비동기방식인데, 저렇게 규칙적으로 받아오더라구요.(4 2 3 1 5 0 6 7 8 9 ...순서) Program.Room .Enter(this); 를 한 순서대로 GameRoom의 _sessions 리스트에 추가가되니 Broadcast 때 리스트를 foreach하니까 리스트에 추가된 순서대로 오는 것 같다고 생각이 드는데, 사실 네트워크 상태에 따라서 패킷이 라우터에 경로가 달라지니 각기 다른 순서로 올 수도 있고(이건 그렇게 부하가 큰편은 아니니 그래도 해당 원인은 무시한다고 쳐도), 멀티스레드이기도 하고 thread context switching 으로 인해 스레드간 순서가 마구마구 뒤바뀔거라 예상을 했지만, 저렇게 규칙적으로 나오는 이유가 무엇인지 궁금합니다. 그리고 새로 실행 시 마다 저 규칙이 변경이 되는데, 그 이유는 사실Listener에서 Onconnected를 하여 Program.Room .Enter(this); 안에 들어가는 순서가 멀티스레딩이라서 다르게 들어가기 때문이라고 이해를 했습니다. 그렇다면 멀티스레딩으로 인한 순서 뒤바뀜이 있다는 증거이고 사실 listener가 받는 것 또 한 GameRoom에서 broadcasting하는것과 비슷하게 lock을 걸고 순서대로 session list에 추가하고 즉, 순차적으로 여기서 리스트 순서대로 보내도 순서뒤바뀜이 일어나서 GameRoom에서의 List에 쌓이는 순서도 바뀌는거라고 생각이 들거든요. 그러면 SendForEach에서 ServerSession리스트를 보낼 땐 멀티스레드로 인해서 순서가 뒤바뀌는데, Server의 GameRoom에서 ClientSession 리스트를 뽑아 send할 땐 순서가 유지되어 send보내지는 이유는 뭔가요?