[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part7: MMO 컨텐츠 구현 (Unity + C# 서버 연동 기초)
22:24의 부분에서부터 말씀해주시는 것 중 루키스님께서 말씀하신것은 2개인거로 사료됩니다. Start에 원하는 애니메이션 플레이 코드 삽입 움직일 때 None이 되면 가만히 있는 코드를 역이용하여 사용. 이렇게 있는데 잠깐 애니메이터를 만지다가 알게 된 건데 애니메이터의 'Entry' 블록에서 Default state를 IDLE_RIGHT와 같이 원하는 항목으로 지정해도 되더라구요. 혹시 현업에서는 어떻게 이용하는지 궁금합니다. 1, 2번처럼 하게 될 때 걱정되는 점은 만약에 도중에 애니메이션 파일 이름을 변경하게 될 때 코드에서 까지 바꿔야 되는 점이 염려스럽습니다. 나중에는 애니메이션 파일이 하나 뿐만이 아닐텐데 그것을 일일이 찾기도 어려울 것이라고 판단했습니다.
영상에서 7분즘에 이런 말씀을 하셨는데요. "커넥터를 딱 하나만 하는 경우도 있겠지만 경우에 따라서는 우리가 리스너에서 계속 뺑뺑이를 돌면서 천명이건 만명이건 계속 받을 수 있는 것처럼 커넥터도 한 번만 받고 끝내는게 아니라 여러 병을 받을 수 있으니까 굳이 이런 식으로 소켓으로 받기 보다는 이런 식으로 이벤트를 통해서 인자를 넘겨주고 있는 것이다." 하지만 그 리스너에서는 Socket을 필드로 들고 있도록 하셨었잖아요? Socket을 필드로 들고 있는 것과 SocketAsyncEventArgs의 Token으로 socket을 넘겨주는건 결국 똑같이 작동하는 건가요? connector에서는 Socket을 필드로 두지 않고 args의 token으로 socket을 건네주신 이유를 이해하지 못하겠습니다. 아니면 그냥 똑같이 동작하는데 이런 방법도 있다고 알려주기 위함이셨나요?
일단 코드를 따라서 구현하고 코드의 흐름으로도 Projectile script가 붙은 파이어볼이 10초뒤에 자연적으로 소멸해야하는데 소멸이 되지않습니다. 코드의 흐름을 보면 PlayerController 에서 StartProjectile함수로 파이어볼을 생성해서 발사 ProjectileController에서 Init함수에서 StartDestroy(_lifeTime); 함수로 넘어가서 SkillController에서 구현된 CoDestroy 에서 Managers.Object.Despawn(this)에 의해 소멸되어야하는데 소멸되지않아 Despawn 쪽에 T가 SkillController 코드를 추가하니 정상적으로 시간뒤에 파괴되는것을 확인했는데 왜 ProjectileController 가 아닌 SkillConroller에서 파괴되는지 궁금합니다. 브레이크포인트를 잡고 해도 SkillController로 넘어가네요
// GameRoom.cs public void Flush() { foreach (ClientSession s in _sessions) s.Send(_pendingList); _pendingList.Clear(); } foreach를 돌며 s.Send()를 하는 와중에 _ sessions가 변경되면, ( _ sessions.Add 되거나 _ sessions.Remove 되면) 아래와 같이 컬렉션 변경 에러가 나옵니다. 이를 해결하려고 아래와 같이 _sessions를 _sessionsCopy에 복사하여 foreach 돌렸습니다. // GameRoom.cs public void Flush() { List<ClientSession> _sessionsCopy = _sessions.ToList(); // 복사 foreach (ClientSession s in _sessionsCopy) s.Send(_pendingList); _pendingList.Clear(); _sessionsCopy = null; } 더 좋은 방법이 있을까요?
안녕하세요? 강의 재밌게 보고 있습니다. 아래 인프런 질문을 보면 Q. Receive()는 lock을 사용하지 않는 이유? A. 명시적으로 Recv()처럼 호출하지 않기 때문에 1번에 1개의 스레드만 접근하여 스레드 세이프함 이라는 질문을 보았는데요, 이 답변을 조금 확대 해석해 봤는데 Q. 명시적으로 함수()를 하지 않으면 무조건 스레드세이프할까요? 답변 미리 감사합니다.
안녕하세요. Part 4를 완강하고 Part 7으로 넘어가기 위해 새로운 솔루션을 생성해서 기존 Part 4 솔루션 내의 프로젝트들을 우선 Ctrl + C, V 한 뒤 기존 프로젝트 추가로 Part 7에서 사용할 서버 솔루션을 Part 4와 동일하게 맞추는 작업을 하고 있었습니다! 그런데, DummyClient의 연결 수를 20개 정도로 하면 문제가 없지만, 30개부터는 특정 ClientSession의 Room이 null인 상태에서 서버 측의 C_MoveHandler가 실행되어 서버가 뻗어버리는 경우가 간헐적으로 발생하고 있습니다. (강의 보면서 따라 한 솔루션은 100이면 100 잘 되며, 새롭게 복사한 솔루션은 대부분 잘 되지만 가끔식 위 오류가 발생합니다..) 처음엔 단순히 Ctrl+C , V 하는 과정에서 프로젝트나 솔루션의 설정값들이 새로운 경로로 옮기면서 동기화가 안되어 생기는 문제인 줄 알았는데, 코드를 계속 천천히 읽다보니 의문이 들게 되었습니다. public GameRoom? Room { get; set; } public override void OnConnected(EndPoint? endPoint) { Console.WriteLine($"OnConnected: {endPoint}"); Program.Room.Push(() => Program.Room.Enter(this)); } 제가 이해한 바로는 ClientSession의 Room은 Listener에 의해서 ClientSession.OnConnected가 호출되며 Program.Room 에게 Enter(this)를 요청하고, 이후 Program.Room 은 Flush()를 통해 특정할 수 없는 시점에 비로소 Enter를 호출하게 되며, ClientSession.Room 이 자기 자신을 가리키도록 합니다. 그런데, 정말 운이 안 좋다면 Program.Room 이 A번 ClientSession에 대한 Enter 작업이 미처 다 수행되기 전에 DummyClient 측의 SendForEach로 인해 A번 ClientSession과 대응되는 ServerSession으로 이동 패킷을 보내고, 최종적으로 A번 ClientSession의 Room이 null인 상태에서 C_MoveHandler를 실행 할 여지가 있는 것이 아닌가 생각하게 되었습니다. 혹시 제가 생각하고 있는 것이 맞는건지, 아니면 단순하게 솔루션을 잘못 복사해와서 문제가 생긴건지 궁금합니다.. 만약 그런 여지가 있다면 단순히 room이 아직 null인지 체크하고 이동 패킷을 무시하면 되는걸까요?
[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part1: C# 기초 프로그래밍 입문
한 가지의 공통된 주제를 가지고 있는 속성들을 struct에 여러 데이터형식과 이름으로 저장해두고 각각 필요한 함수에 넣어서 사용하는거 맞나요? 활용하는 방법은 하나의 클래스에 저장해두고 여러 클래스에다가 사용하는거 맞나요? 예를 들어 스탯과 관련된 큰 클래스에다가 struct함수를 만들어 정리해두고 각각 다른 클래스에다 호출해서 사용하는거요
제이슨을 파싱하는 과정중에서 int, class 형식으로 가져오고 있는데 string, class 형식으로도 가져오게 할 수 있나요?? [Serializable] public class ValueDataLoader : ILoader<int, ValueData> { public List<ValueData> datas = new List<ValueData>(); public Dictionary<int, ValueData> MakeDict() { Dictionary<int, ValueData> dict = new Dictionary<int, ValueData>(); foreach (ValueData Data in datas) dict.Add(Data.ID, Data); return dict; } }
안녕하세요 3주 차 코드로 공부하고 있는 중 spine 을 animator controller로 교체하려고 하는데요. Creature.cs 의 public virtual void SetInfo(int templateID) { . . SkeletonAnim.skeletonDataAsset = Managers.Resource.Load<SkeletonDataAsset>(CreatureData.SkeletonDataID); SkeletonAnim.Initialize(true); // Register AnimEvent if (SkeletonAnim.AnimationState != null) { SkeletonAnim.AnimationState.Event -= OnAnimEventHandler; SkeletonAnim.AnimationState.Event += OnAnimEventHandler; } 부분에서 SkeletonAnim.skeletonDataAsset = Managers.Resource.Load<SkeletonDataAsset>(CreatureData.SkeletonDataID); 는 캐릭터 간 다른 애니메이션을 사용하기 위해 json에서 읽어온 animator 파일을 지정하는 걸로 이해하고 Animator Controller로 교체했는데요. BaseObject.cs public Animator SkeletonAnim { get; private set; } Creature.cs public virtual void SetInfo(int templateID) { . . SkeletonAnim.runtimeAnimatorController = Managers.Resource.Load<RuntimeAnimatorController>(CreatureData.SkeletonDataID); // Animator Controller로 교체 // Register AnimEvent if (SkeletonAnim.AnimationState != null) { SkeletonAnim.AnimationState.Event -= OnAnimEventHandler; SkeletonAnim.AnimationState.Event += OnAnimEventHandler; } SkeletonAnim.AnimationState.Event -= OnAnimEventHandler; SkeletonAnim.AnimationState.Event += OnAnimEventHandler; 이 부분은 왜 사용하는지 어떻게 수정해야 되는지 모르겠습니다.
private void Write() { // 다른 스레드가 읽기나 쓰는지 검증 ... var request = DateTime.Now .ToString(); Interlocked.Increment(ref writeCount); //...쓰기작업 } 03:40 부분의 내용입니다 스레드1 이 var request = DateTime.Now .ToString(); 이 부분을 실행할때는 아직 writeCount 가 0인 상태인데 이때 스레드2가 writeCount와 readCount 0인거 확인하고 들어올 위험은 없는건가요? 어떻게 상호배제 되는지 이해가 안갑니다!
Wall을 새워두고 (hit.point - _player.tranform.position).maginitude * 0.8f 를 하게 되는데 hit.porint는 카메라기준으로 Ray가 나갔을 때 벽에 닿는 바로 그 순간인가요? 그렇다면 벽이 만약 두꺼우면 0.8f을 잘못 설정하면 카메라가 벽안으로도 들어갈수 있나요?
[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part7: MMO 컨텐츠 구현 (Unity + C# 서버 연동 기초)
안녕하세요, 루키스님.개인 프로젝트를 진행하는 중 리슨서버를 구현해보려고 하는데 몇 가지 궁금한 점이 있습니다. 리슨서버를 구현하려면 서버 코드를 모두 클라이언트에 이식하고, 컴포넌트로 관리할 수 있도록 수정해야 하나요? 만약 1의 가정이 맞다면, 1을 통해 구현된 서버에서 유니티엔진의 기능들을 사용할 수 있지 않을까 생각이 되는데, 만약 된다면 충돌과 관련된 부분을 처리하는데 활용해도 괜찮을까요? 유니티 자체에서도 네트워크를 관리해주는 매니저를 제공하는 것으로 알고있는데, 강의처럼 따로 서버를 구현하는 이유는 역시 성능 때문일까요? 현재 생각 중인 방식이 어몽어스와 유사한데요.중앙 서버에서 방을 생성하는 유저(호스트)들의 ip와 방 정보를 가지고 단순히 방 목록을 관리하며 클라이언트들이 접속할 수 있는 역할만 해주고, 클라이언트가 방에 접속하는 순간부터 모든 처리는 호스트가 하게되는... 구조가 맞을까요? 최근 들어 질문을 자주하게 되는 것 같은데..항상 친절히 답변해주셔서 감사합니다.
안녕하세요 섹션4 코드를 보면 requests 라는 오브젝트 키를 사용해서 스레드1과 스레드2가 임계영역을 이용중인데 서버 함수를 보면 일이 없으면 lock 안에서 wait 즉 대기 상태로 빠집니다 그리고 클라 함수를 보면 일을 넣어주고 다른 스레드를 깨웁니다 여기서 의문인게 임계영역 안에서 대기중인 스레드와 실행중인 스레드가 공존할 수 있나요 https://www.inflearn.com/questions/1046075 제가 다른 수업에서 한 질문인데 답변에는 ai 답변이긴 하지만 그럴 수 없다고 들어서 질문드립니다