묻고 답해요
169만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
SendBuffer 새로 sendbuffer 할당해주는 문제
public static ArraySegment<byte> Open(int reserveSize) { if (CurrentBuffer.Value == null) { CurrentBuffer.Value = new SendBuffer(ChunkSize); } if (CurrentBuffer.Value.FreeSize < reserveSize) { CurrentBuffer.Value = new SendBuffer(ChunkSize); } return CurrentBuffer.Value.Open(reserveSize); }Sendbuffer에서 남은버퍼를 반환해주는 open함수에서 필요한 사이즈가 현재 남아있는 free사이즈보다 큰 경우(CurrentBuffer.Value.FreeSize < reserveSize) 새로 sendbuffer를 CurrentBuffer.Value에 넣는데, 아직 CurrentBuffer.Value 에 보내지 못한 데이터가 있는 경우에 open을 해버리면 새 sendbuffer가 CurrentBuffer.Value로 치환되어버려서 데이터가 날라가버리는 것 아닌가요? 즉, 예를들어 아직 100명한테 다 안보냈는데 새로 할당해버리면 안되지않나요? _usedSize를 recvbuffer에서처럼 땡겨서 쓰지 않는 이유가 누군가가 계속 이전에 있던 부분(현재 사용 중인 부분)을 참조하고 있을 수도 있기 때문에 그냥 증가시키는 방법으로 한 것 처럼.. CurrentBuffer.Value 도 저렇게 그냥 새로 할당해버리면 안될 것 같다고 생각이 계속 듭니다 ㅜㅜ
-
미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part1: C# 기초 프로그래밍 입문
리뉴얼 질문
안녕하세요 루키스님! 항상 좋은 강의를 만들어 주셔서 정말 감사합니다.오랜만에 복습하러 들어왔는데, 강의 리뉴얼을 진행중이시군요!혹시 리뉴얼이 파트1만 해당인가요? 아니면 점차 모든 파트를 리뉴얼 하실 예정이신가요?선수지식 하나도 없는 상태에서 2파트 4파트 강의를 들었을 때, 너무 어려워서 울면서 나간 기억이 나네요ㅋㅋㅋㅎㅋㅋㅎㅋㅠㅠ
-
미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part3: 유니티 엔진
animation event
inspector 창에 다른 파라미터들?이 뜨게 하려면 어떻게 해야 하는지 알고싶습니다... 어떻게 이벤트를 생성해도 창이 뜨지 않아서 ㅠㅠ 넘어가질 못하고 있습니다
-
해결됨[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
컴파일러 최적화 강의 관련 질문
안녕하십니까 선생님귀한 강의 항상 감사한 마음으로 듣고 있습니다. 아래 질문과 관련해 릴리즈 모드로 해서 실행을 하면 먹통이 되어야 하는데, 저는 먹통이 안 되고 "종료성공"까지 다 나옵니다. 혹시 이유를 알 수 있을까요?참고로 아래 질문의 증상과 저도 동일하게 나타났고 닷넷 프레임워크로 프로젝트를 만들었습니다.혹시나 해서 닷넷코어로 프로젝트를 만들어서 해보면 수업처럼 먹통이 되긴 하는데, 닷넷프레임워크로 프로젝트 만들면 릴리즈로 실행 시 먹통이 안 되고 잘 실행이 됩니다.감사합니다~! --아래 질문----------------안녕하세요, 선생님 c# 게임 서버 강의를 수강하다가 선생님과 다르게 작동하는 부분이 있어서 질문드립니다6번째 강의인 컴파일러 최적화 강의에서 코드를 실행하면 4:25초경에쓰레드 시작!쓰레드 종료!Stop 호출종료 대기중종료 성공이 순서대로 선생님은 실행이 되는데요, 저는쓰레드 시작!Stop 호출종료 대기중쓰레드 종료!종료 성공순서로 쓰레드 종료!가 더 늦게 뜨네요강의에서처럼 _stop에 volatile을 붙이면 선생님이랑 같은 값이 나오긴 하는데컴퓨터 성능 차이 때문일 수 있나요?코드가 다른 부분은 없습니다. 몇 번이고 확인했어요감사합니다!
-
미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part1: C# 기초 프로그래밍 입문
새로운 객체를 만들때 new Knight 를 두고 왜 knight clone()을 사용하는지 궁금합니다.
힙과 스택을 공부해보면 new 연산자를 통해서 각기 다른 객체를 만들수 있는데 왜 굳이 clone 함수를 만들어서 하는건가요?기존의 hp attack 값을 그대로 복사한체 새로운 객체를 만들수있어서 그런가요??
-
미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part3: 유니티 엔진
Util.cs의 FindChild의 recursive == true인 부분이 이해가 가질 않습니다.
안녕하세요 수업을 듣다가 16분쯤에 질문이 생겨 남깁니다.재귀라 하면 자식의 자식, 자식의 자식의 자식까지 쭉 돌면서 계속 찾아야하는 거라고 생각했는데 현재 코드대로라면 자식의 자식까지만 탐색하고 종료한다고 생각합니다.else - foreach에서 FindChild<T>(component, name, true)로 함수를 다시 호출해야하는 건 아닌지 궁금합니다.감사합니다.
-
미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
궁금해져서 질문드립니다
C_Chat chatPakcet = packet as C_Chat 여기에서 as로 형 변환을 하는것과 안하는 것의 차이점을 알고 싶습니다
-
해결됨[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part1: C# 기초 프로그래밍 입문
구조체와 new에대해 질문드립니다
구조체 타입을 new로 생성해 값을 복사할 경우, 얕은 복사가 일어날까 싶어 확인해보니 깊은 복사가 일어나는 것을 확인했습니다.구조체는 기본적으로 복사 타입으로 생성되지만, new를 통해 생성된 변수는 힙영역에 참조 타입으로 생성되는걸로 알고 있습니다. 구조체에 new로 동적할당을 할경우 특별하게 작용하는 것인지, 혹은 제가 잘못 이해한 것인지 질문드립니다.
-
미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part3: 유니티 엔진
Start() 순서 관련하여 문제가 발견된듯 합니다
강의에서 stat 클레스 생성후 start Start()문이 PlayerController Start() 보다 느리게 만들어져 speed값이 0이 되는 문제가 발견 됬습니다 이럴때는 어떻게 하면 좋을까요
-
미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
SendBuffer 마지막부분 이해가 안됩니다.
질문 1. TLS로 SendBuffer를 스레드별 전역변수로 지정했으면, SendBuffer 멤버필드인 buffer도 스레드별 전역변수가 아닌가요?그런데 왜 _buffer는 공유자원처럼 다수의 스레드가 참조하는 건가요?(28:39 부분) 질문 2. 만약 _buffer는 TLS 여도 다수의 스레드가 볼 수 있다고 쳐도, 어차피 Send하는 부분은 그 스레드가 넣은 부분만(handler에서 close로 보내준 segment영역) 보내주기때문에 상관없는 것 아닌가요? (하지만 애초에 질문 1이 이해가 안됩니다.) 질문 3.이전에 Session#2 강의 시작부분에 설명해주신 내용에서,SEssion의 receive는 OnRecvCompleted()메서드에 여러 스레드가 동시다발적으로 들어가는 경우는 없다. 라고 하셨는데, 해당 강의에서는 어떤 이유로 멀티스레드를 생각해야 하는 상황이 된건지 궁금합니다.질문 4.Session 객체는 connect되는 client당 하나씩이니까 client와 연결 될 때 마다 새로운 session객체가 생성되어 다 따로 만들어지는 것이기 때문에 애초에 _sendQueue도 스레드별로 따로 아닌가요? 질문 5. _buffer는에서 읽기만 하는거니까..(30:03) 라고 하셨는데 읽는 부분이 어느부분인지, deq하는것을 읽는것이라고 표현하신건가요? 어떤 경우들을 말슴하시는건지 이해가 안되어 헷갈리는게 많습니다. 일단 질문은 더 있지만, 대표적인 질문들로 올려봅니다
-
미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
segmeng 범위 지정시에 질문
안녕하세요, RecvBuffer 강의중에서//읽을 수 있는 유효한 데이터의 범위 public ArraySegment<byte> ReadSegment { get { return new ArraySegment<byte>(_buffer.Array, _buffer.Offset + _readPos, DataSize);} } //사용가능한, 비어있는 범위 public ArraySegment<byte> WriteSegment { get { return new ArraySegment<byte>(_buffer.Array, _buffer.Offset + _writePos, FreeSize); } }위와 같이 segment 프로퍼티를 설정하였는데, 중간 인자로 그냥 readPos를 넣지 않고 buffer.Offset + readPos 로 계산한 이유를 모르겠습니다. 현재 저의 생각으로는 buffer.Offset은 결국 언제나 0이지 않나? 입니다. 코드를 보았을 때 offset을 조작하거나 건드리는 코드는 아직 현재강의(RecvBuffer)까지는 없고, 나중에라도 _readPos와 DataSize가 결국 segment범위를 바꿔주니 이 offset을 건들일 필요는 없다고 생각이 드는 상태입니다. 또한, 만약 offset을 변경시키는 경우가 있더라도 offset+readpos 하면 offset이 0이 아닌경우 readpos에 맞지않는곳이 시작위치가 될텐데 왜 offset을 더하는건지 이해가 되지 않습니다.따라서 offset을 더한 이유가 궁금합니다!
-
미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
RecvBuffer clean함수 이렇게 작성하면 어떻게 되나요?
안녕하세요, RecvBuffer 클래스를 작성하는 강의에서, clean()함수를 작성하실 때 강사님께서는이렇게 작성하셨는데,혹시 아래와 같이Array.Copy(ReadSegment.Array, 0, _buffer.Array, 0, DataSize);이렇게 작성해도 똑같은 결과가 나오려나요? 혹은 나중에 다른상황에서 이렇게 작성하면 다르게 동작한다던지 그런 문제가 있을까요?위에 적용된 ReadSegment범위를 사용하지 않는 이유가 뭔지 궁금합니다.public void Clean() { int dataSize = DataSize; if (dataSize == 0) { _readPos = 0; _writePos = 0; } else { Array.Copy(ReadSegment.Array, 0, _buffer.Array, 0, DataSize); _readPos = 0; _writePos = dataSize; } }
-
미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
RegisterRecv()에서 args초기화 구문 사라진 이유
안녕하세요, 현재 RecvBuffer 강의를 시청중입니다.강의를 듣다가 RegisterRecv 를 봤는데 강사님께서void RegisterRecv(SocketAsyncEventArgs args) { args.AcceptSocket = null; bool pending = _socket.ReceiveAsync(args); //바로 성공했으면 if(pending == false) { OnRecvCompleted(null, args); } } 위와 같이 원래 있었는데void RegisterRecv(SocketAsyncEventArgs args) { bool pending = _socket.ReceiveAsync(args); //바로 성공했으면 if(pending == false) { OnRecvCompleted(null, args); } } 위처럼 args.AcceptSocket = null; 를 언제인지는 모르겠지만 삭제를 하셨던거같은데,언제, 왜 삭제하신건지 이유가 궁금합니다.
-
미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part3: 유니티 엔진
manager들 사이의 호출순서가 궁금해요
manager public class Managers : MonoBehaviour{static Managers s_Instance; //유일성이 보장된다public static Managers instance { get { Init(); return s_Instance; } } // 유일한 매니저를 갖고온다InputManager _input = new InputManager();public static InputManager input { get { return instance._input; } }// Start is called before the first frame updatevoid Start(){Init();}// Update is called once per framevoid Update(){_input.OnUpdate();}static void Init(){if (s_Instance == null){GameObject go = GameObject.Find("@Managers");if (go == null){go = new GameObject { name = "@Managers" };go.AddComponent<Managers>();}DontDestroyOnLoad(go);s_Instance = go.GetComponent<Managers>();}}}==================================playercontroller.cs public class PlayerController : MonoBehaviour{[SerializeField]float _speed = 10.0f;// Start is called before the first frame updatevoid Start(){Managers.input.KeyAction -= OnKeyboard; //실수 방지용으로 미리 한번 -함Managers.input.KeyAction += OnKeyboard;}// Update is called once per framevoid Update(){ } void OnKeyboard(){if (Input.GetKey(KeyCode.W)){transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(Vector3.forward), 0.2f);transform.position += Vector3.forward Time.deltaTime _speed;}if (Input.GetKey(KeyCode.S)){transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(Vector3.back), 0.2f);transform.position += Vector3.back Time.deltaTime _speed;}if (Input.GetKey(KeyCode.A)){transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(Vector3.left), 0.2f);transform.position += Vector3.left Time.deltaTime _speed;}if (Input.GetKey(KeyCode.D)){transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(Vector3.right), 0.2f);transform.position += Vector3.right Time.deltaTime _speed;}}}==================================public class InputManager{public Action KeyAction = null; public void OnUpdate(){if (Input.anyKey == false)return;if (KeyAction != null)KeyAction.Invoke();}}==================================player.cs public class Player : MonoBehaviour{ // Start is called before the first frame updatevoid Start(){Managers mg = Managers.instance;}// Update is called once per framevoid Update(){ }} 지금 unitychan 오브잭트에 playercontroller 컴포넌트를 inspector창에다 추가한뒤에 실행을 하는데 input값을 입력받을떄마다 어떤식으로 작동이되는지 순서가 이해가 안가요playercontroller 에 update()에 아무것도 없는데 지속적으로 어떻게 key값을 받는지 궁금해요start()는 1회실행되는 함수인데 player.cs도 지금 존재 이유가 유일한 manager 컴포넌트를 쓰게하기 위해서 만들었는데[ 점점 갈수록 어렵네요
-
미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
listener, connector static 차이 이유
안녕하세요, connector와 listener변수에서 static 차이가 일어나는 이유에 대해 질문드리고자 합니다. server 코드의 listener는 아래와 같이 static으로 정의하셨는데, (그리고 저 _obj는 왜 있는건지, 그냥 지워도 되는걸까요?) static object _obj = new object(); static Listener _listener = new Listener(); client코드의 connector는 그냥 static없이 Connector connector = new Connector();이렇게 그냥 변수로 지정하신 이유가 궁금합니다.
-
미해결[유니티6] 따라하면서 배우는 하이퍼캐주얼게임 시리즈 01
여기서 래디안을 구하는 이유가 이해가 안갑니다.
안녕하세요 고박사님.제가 이 강의에서 모든 부분 다 이해가 갑니다. 근데 제가 게임수학 부분은 안해봐서 그런지, 삼각함수 쪽에서 좀 막혀서 따로 공부했는데, 타겟에 핀 배치할 때 왜 굳이 래디안을 구해야하는 지 이해가 잘 안가서 여쭤봅니다.실험으로 래디안 식 없이 돌려보니 핀 머리는 잘 배치가 되는데 막대기 부분의 위치와 로테이션이 잘못 배치돼더군요. 꼭 있어야하는 식인 것 같은데, 왜 그런지 이해가 안갑니다.이 부분만 설명 한번만 부탁드려도 될까요?
-
미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
ArraySegment<byte>
public ArraySegment<byte> ReadSegment { get { return null; } } public ArraySegment<byte> WriteSegment { get { return null; } } 심각도 코드 설명 프로젝트 파일 줄 비표시 오류(Suppression) 상태오류 CS0037 'ArraySegment<byte>'은(는) null을 허용하지 않는 값 형식이므로 null을 이 형식으로 변환할 수 없습니다. ServerCore 저는 null을 넣을때 오류가 뜨는데 무슨 이유일까요?
-
해결됨[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part3: 유니티 엔진
LayerMask를 사용하면 왜 최적화가 되는지 잘 이해가 되지 않습니다.
LayerMask를 통해 RayCasting을 하면 하지 않았을 때보다 최적화가 된다고 하셨는데 왜 그런지 잘 이해가 되지 않습니다. 혹시 더 자세하게 알려주실 수 있나요?
-
미해결유니티 Addressable 을 이용한 패치 시스템 구현
구매한 아이템을 로드할 때
게임 내에서 아이템 세트를 구매하면 어드레서블로 다운로드 받고 에셋을 로드하는데요. 껐다 켰을 때 영수증 검증 되면서 구매한 아이템들을 또 Load Asset Async로 불러와야 하나요?
-
미해결[유니티6] 따라하면서 배우는 하이퍼캐주얼게임 시리즈 01
2020.3.0f1 Unity Package Manager Error
2020.3.0f1 버전을 설치 후 프로젝트를 실행하면 위와같은 사진이 나오면서 프로젝트가 열리지 않습니다. 혹시 해결 방안이 있을까요 ??