묻고 답해요
148만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
시간 복잡도는 사실상 똑같지 않나요?
안녕하세요 루키스님!항상 강의 잘 듣고 있습니다. 다름이 아니라 기존에는 N^2 의 시간 복잡도라고 말씀해주셨습니다. 그 이유도 충분히 이해했습니다.그래서 GameRoom.cs의 _pendingList와 Flush 함수를 패킷 모아 보내는 용도로 사용하셨습니다. 그러나 사실상 Flush 내부를 자세히 보면 결국 N^2으로 시간 복잡도는 똑같다고 생각합니다. 왜냐하면 Flush 내부에서 세션용 foreach와Send함수 내부에서 List<ArraySegment<byte>> 용의 foreach로 인해서 총 2개의 foreach가 돌기 때문에 시간 복잡도는 여저힌 N^2이지 않나요? 만약 10명의 클라이언트가 접속했을 때,[패킷 모아 보내기 할 경우]100개의 패킷을 한 번에 보내는 것[패킷 모아 보내기 안 할 경우]10개의 패킷을 10번 보내는 것 으로 이해 했는데 맞을까요?
-
미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
switch문과 딕셔너리 효율 질문입니다.
https://rito15.github.io/posts/cs-switch-case-vs-dictionary/이 내용을 보면 딕셔너리를 이용하는것보다 스위치문을 이용하는게 더 효율적인것으로 보이는데, 어떤것이 맞는지 모르겠어요
-
해결됨[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
코드 오류 질문드립니다..ㅠㅠ
유니티 연동 #1 을 공부하는 도중 아래와 같은 오류가 떴습니다.유니티 서버를 연동하는 부분이고 정상동작을 한다면 Hello Server I am 1 이 출력되어야 합니다.소켓 부분에서 에러가 나서 OnConnectedCompleted 함수를 제대로 실행하시 못하는것 같습니다. 강의 파일을 받아서 실행해도 동일한 오류가 뜨고 아무리 구글링을 해봐도 해결을 못하겠어서 번거로우시겠지만 질문을 드립니다...
-
해결됨유니티 머신러닝 에이전트 완전정복 (기초편)
A2C 알고리즘을 드론 환경에 적용하려면
안녕하세요, 드론 환경에서 A2C 알고리즘을 적용해서 실험해보려고 합니다.환경에 맞게 적용을 하기 위해 state_size, action_size를 각각 9와 3으로 설정하고, 이 외에도 여러 부분을 수정하여 돌려 보려고 했는데 잘 안 되네요.get_action() 함수를 손보거나, preprocess를 하는 부분을 수정해주어야 할 것 같은데, 어떻게 해결해야 할지 잘 모르겠습니다.현재 상태에서는 다음과 같은 오류가 발생하고 있습니다.A2C.py의 코드는 아래와 같습니다.import numpy as np import datetime import platform import torch import torch.nn.functional as F from torch.utils.tensorboard import SummaryWriter from collections import deque from mlagents_envs.environment import UnityEnvironment, ActionTuple from mlagents_envs.side_channel.engine_configuration_channel\ import EngineConfigurationChannel # A2C를 위한 파라미터 값 세팅 state_size = 9 action_size = 3 load_model = False train_mode = True discount_factor = 0.9 learning_rate = 0.00025 run_step = 100000 if train_mode else 0 test_step = 10000 print_interval = 10 save_interval = 100 # VISUAL_OBS = 0 # GOAL_OBS = 1 # VECTOR_OBS = 2 # OBS = VECTOR_OBS # 유니티 환경 경로 game = "Drone" os_name = platform.system() if os_name == 'Windows': env_name = f"C:/Users/user/anaconda3/envs/mlagents/Drone_0427/Drone_1002_3.exe" elif os_name == 'Darwin': env_name = f"../envs/{game}_{os_name}" # 모델 저장 및 불러오기 경로 date_time = datetime.datetime.now().strftime("%Y%m%d%H%M%S") save_path = f"./saved_models/{game}/A2C/{date_time}" load_path = f"./saved_models/{game}/A2C/20210709235643" # 연산 장치 device = torch.device("cuda" if torch.cuda.is_available() else "cpu") print("CUDA is available" if torch.cuda.is_available() else "CPU is available") # A2C 클래스 -> Actor Network / Critic Network 정의 class A2C(torch.nn.Module): def __init__(self, **kwargs): super(A2C, self).__init__(**kwargs) self.d1 = torch.nn.Linear(state_size, 128) self.d2 = torch.nn.Linear(128, 128) self.pi = torch.nn.Linear(128, action_size) self.v = torch.nn.Linear(128, 1) def forward(self, x): x = F.relu(self.d1(x)) x = F.relu(self.d2(x)) return F.softmax(self.pi(x), dim=1), self.v(x) # A2CAgent 클래스 -> A2C 알고리즘을 위한 다양한 함수 정의 class A2CAgent(): def __init__(self): self.a2c = A2C().to(device) self.optimizer = torch.optim.Adam(self.a2c.parameters(), lr=learning_rate) self.writer = SummaryWriter(save_path) if load_model == True: print(f"... Load Model from {load_path}/ckpt ...") checkpoint = torch.load(load_path+'/ckpt', map_location=device) self.a2c.load_state_dict(checkpoint["network"]) self.optimizer.load_state_dict(checkpoint["optimizer"]) # 정책을 통해 행동 결정 def get_action(self, state, training=True): # 네트워크 모드 설정 self.a2c.train(training) #네트워크 연산에 따라 행동 결정 pi, _ = self.a2c(torch.FloatTensor(state).to(device)) action = torch.multinomial(pi, num_samples=1).cpu().numpy() return action def train_model(self, state, action, reward, next_state, done): state, action, reward, next_state, done = map(lambda x: torch.FloatTensor(x).to(device), [state, action, reward, next_state, done]) pi, value = self.a2c(state) # Value network with torch.no_grad(): _, next_value = self.a2c(next_state) target_value = reward + (1-done) * discount_factor * next_value critic_loss = F.mse_loss(target_value, value) #Policy network eye = torch.eye(action_size).to(device) one_hot_action = eye[action.view(-1).long()] advantage = (target_value - value).detach() actor_loss = -(torch.log((one_hot_action * pi).sum(1))*advantage).mean() total_loss = critic_loss + actor_loss self.optimizer.zero_grad() total_loss.backward() self.optimizer.step() return actor_loss.item(), critic_loss.item() # 네트워크 모델 저장 def save_model(self): print(f"... Save Model to {save_path}/ckpt ...") torch.save({ "network" : self.a2c.state_dict(), "optimizer" : self.optimizer.state_dict(), }, save_path+'/ckpt') # 학습 기록 def write_summray(self, score, actor_loss, critic_loss, step): self.writer.add_scalar("run/score", score, step) self.writer.add_scalar("model/actor_loss", actor_loss, step) self.writer.add_scalar("model/critic_loss", critic_loss, step) # Main 함수 -> 전체적으로 A2C 알고리즘을 진행 if __name__ == '__main__': # 유니티 환경 경로 설정 (file_name) engine_configuration_channel = EngineConfigurationChannel() env = UnityEnvironment(file_name=env_name, side_channels=[engine_configuration_channel]) env.reset() # 유니티 브레인 설정 behavior_name = list(env.behavior_specs.keys())[0] spec = env.behavior_specs[behavior_name] engine_configuration_channel.set_configuration_parameters(time_scale=12.0) dec, term = env.get_steps(behavior_name) # A2C 클래스를 agent로 정의 agent = A2CAgent() actor_losses, critic_losses, scores, episode, score = [], [], [], 0, 0 for step in range(run_step + test_step): if step == run_step: if train_mode: agent.save_model() print("TEST START") train_mode = False engine_configuration_channel.set_configuration_parameters(time_scale=1.0) #preprocess = lambda obs, goal: np.concatenate((obs*goal[0][0], obs*goal[0][1]), axis=-1) #state = preprocess(dec.obs[OBS]) #state = preprocess(dec.obs[OBS],dec.obs[GOAL_OBS]) state = dec.obs[0] action = agent.get_action(state, train_mode) action_tuple = ActionTuple() action_tuple.add_continuous(action) env.set_actions(behavior_name, action_tuple) env.step() dec, term = env.get_steps(behavior_name) done = len(term.agent_id) > 0 reward = term.reward if done else dec.reward next_state = term.obs[0] if done else dec.obs[0] score += reward[0] if train_mode: agent.append_sample(state[0], action[0], reward, next_state[0], [done]) # 학습 수행 actor_loss, critic_loss = agent.train_model() actor_losses.append(actor_loss) critic_losses.append(critic_loss) if done: episode += 1 scores.append(score) score = 0 # 게임 진행 상황 출력 및 텐서 보드에 보상과 손실함수 값 기록 if episode % print_interval == 0: mean_score = np.mean(scores) mean_actor_loss = np.mean(actor_losses) mean_critic_loss = np.mean(critic_losses) agent.write_summray(mean_score, mean_actor_loss, mean_critic_loss, step) actor_losses, critic_losses, scores = [], [], [] print(f"{episode} Episode / Step: {step} / Score: {mean_score:.2f} / " +\ f"Actor loss: {mean_actor_loss:.2f} / Critic loss: {mean_critic_loss:.4f}") # 네트워크 모델 저장 if train_mode and episode % save_interval == 0: agent.save_model() env.close()답변 주시면 감사하겠습니다!
-
미해결[유니티 레벨 업!] 모듈식으로 개발하는 퀘스트&업적 시스템
새로운 강의 일정 질문입니다.
안녕하세요 이전에 드렸던 질문이긴 하지만, 새로운 강의(스킬 시스템)은 10월 경에 정확히 수강 할 수 있는지 알 수 있나요?
-
미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
혹시 어려워서 포기할까 생각하시는 분들 보고 힘 얻으세요
지금 3번째 들으면서 지나가는 수강생입니다진짜 첫 번째 들을 때 두 번째 들을 때 세 번째 들을 때 이해되는 범위가 다릅니다처음에는 그냥 코드 따라 치면서 완주만 해보세요. 두 번째는 코드의 흐름만 본다는 느낌으로 따라가고, 세 번째는 강의를 눈으로만 보고, 혼자 힘으로 코드를 완성해 보면 확실히 체득이 되는 느낌입니다!다들 화이팅입니다! 저 같은 말하는 감자도 하는데 여러분도 할 수 있습니다!ps. 루키스님 강의 찍으시랴, 부트캠프 준비하시랴 많이 바쁘실텐데 항상 감사합니다!
-
해결됨[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
출력 간격 이상
안녕하세요 선생님! 클라이언트에서 온 패킷이 자꾸 이렇게 띄엄띄엄 출력 되는데 왜 그런지 알 수 있을까요?
-
미해결[유니티 3D] 실전! 생존게임 만들기 - Advanced
전체 프로젝트 파일 받을 수 있을까요?
강의를 보고 코드를 치다가 한두 곳 오류가 나왔는데 문제점을 도저히 못 찾겠습니다. 그래서 전체 프로젝트를 보면서 비교 분석해보고 싶은데 가능 할까요...?
-
해결됨[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
안녕하세요 강의 시청중 궁금한점 생겨서 질문드립니다.
웹서버의 경우 실무에서 docker를 많이 사용하는 것 같은데요, 혹시 소켓 기반 실시간 게임서버개발에도 docker를 많이 사용하는지 궁금합니다!
-
해결됨[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
PriorityQueue<JobTimerElem> _pq 우선순위큐 질문드립니다.
우선순위큐 안에 요소를 디버그 모드로 확인해보니 계속 한개의 요소만 있는데 0.25초마다 flushroom이 큐에 들어가고 처리되고 반복이어서 그런건가요?아니면 flushroom action 만 있어서 복잡하지 않아서 그런건지 잘 모르겠습니다.
-
해결됨[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part3: 유니티 엔진
StartCoroutine("CoStopExplode", 2.0f); 이 부분이 실행이 안됩니다.
using System.Collections;using System.Collections.Generic;using UnityEngine; public class GameScene : BaseScene{ Coroutine co; protected override void Init() { base.Init(); SceneType = Define.Scene.Game; Managers.UI.ShowSceneUI<UI_Inven>(); co = StartCoroutine("ExplodeAfterSeconds", 4.0f); StartCoroutine("CoStopExplode", 2.0f); } IEnumerable CoStopExplode(float seconds) { Debug.Log("Stop Enter"); yield return new WaitForSeconds(seconds); Debug.Log("Stop Execute!!!"); if (co != null) { StopCoroutine(co); co = null; } } IEnumerator ExplodeAfterSeconds(float seconds) { Debug.Log("Explode Enter"); yield return new WaitForSeconds(seconds); Debug.Log("Explode Excute!!!"); co = null; } public override void Clear() { } } StartCoroutine("CoStopExplode", 2.0f); BreakPoint 를 여기에 잡아서 유니티에 연결해 실행해 보았지만 두번째 StratCoroutine은 실행이 되지 않고 Stop Enter 로그도 찍히지 않고 넘어가 버립니다. 그냥 Explode Excute가 찍혀버리는데 혹시 StaretCoroutine을 중복 사용할 수 없게 업데이트가 된 걸가요?
-
해결됨[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part3: 유니티 엔진
버그 발생시
안녕하세요! 항상 좋은 강의 잘 보고 있습니다!! 버그 수정에 대해 궁금한게 있습니다 게임을 만들던 도중에 unityChan이 바닥을 향해 달려가는 버그가 발생해서 하루 종일 디버깅 해보고 오류를 수정하려고 했지만 결국 원인을 찾지 못하고, 처음 부터 다시 했더니 진짜 갑자기 됐습니다,, 근데 저는 아직도 그때 왜 버그가 났는지 이유를 모르겠습니다,, 그래서 제가 궁금한것은 게임을 만드시는 분들도 다들 이렇게 버그의 원인을 찾지 못하는 경우가 많나요? 저는 버그의 원인을 잘 찾지 못하는것 같은데,,, 다른 분들은 어떻게 하시나요?
-
미해결[유니티 레벨 업!] 모듈식으로 개발하는 퀘스트&업적 시스템
Quest Tracker 질문입니다.
선생님 영상 12분까지 따라했는데 Kill Normal Gem Slim5에 대한 Quest Tracker UI가 그대로 남아있습니다. 게임 Points는 30점으로 제대로 저장이 되어있고, 게임 시작시 Quest Giver로 인해 Active Quests로 2개의 퀘스트가 Add 되어서 UI로 다시 출력이 되는데 원인을 잘 모르겠습니다. (Completed Quest로 Kill Normal Gem Slim5이 Add 된 것은 확인했습니다)
-
미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
3D서버 만들 때 질문입니다
복학 전에 개인 작업으로 FPS게임서버를 만들고 있습니다. 구현된 것들: - 신규 유저 접속 시 기존 유저 데이터 전송, 기존 유저에게 신규 유저 스폰 전송 - 키보드 입력(Vertical, Horizontal)을 하나의 Vector3에 저장하여 이전 값과 다를 경우 패킷을 전송 ( 데드레커닝이 맞는진 모르겠음) - 카메라 회전 값을 각 클라이언트에서 0.25초 단위로 동기화 패킷 전송 ( 회전값은 서버에서 검증이 필요없을 거라 생각해서 검증 없이 Echo ) 위에 적은 대로 위의 기능은 문제없이 잘 작동하지만 이동 동기화에 대해서 문제가 심각합니다.... 데드레커닝처럼 이전값과 다를 때만 패킷을 보내는데, 상대 클라이언트는 회전값 동기화가 0.25 + (내RTT/2 + 상대RTT/2)이상이라 이동패킷이 더 빠르게 가버리면 위치값에 대한 데이터 일관성이 깨집니다. 그래서 추가로 1초 단위로 현재 위치를 서버에 전송합니다. 서버는 새로운 위치값을 받고 자신이 갖고 있던 해당 플레이어의 위치값 ( 서버 내에서도 이동방향, 회전값, RTT/2, 오차범위를 기준으로 위치값을 0.25초 단위로 업데이트함) 과 비교하여 이 값이 정상적인 데이터인지 검증합니다. 만약 결과가 정상적이라면 Broadcast, 비정상적이라면 Leave로 구현했습니다. 그런데 문제는 서버에서 검증하는 시간 + 내 RTT / 2 + 상대 RTT / 2 차이 때문에 데드레커닝으로 예측하더라도 계속 이전 위치로 돌아가는 현상이 발생했습니다. 데드레커닝을 포기하자니 너무 느린 반응때문에 FPS에 적합하지 않은 것 같고, 서버 검증을 포기하자니 에디터에 Inspector에서 위치 이동만 해도 핵처럼 보였습니다. FPS에서는 검증을 어떻게 하는게 맞을까요?
-
미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
유저 간 패킷전송의 평등성? 에 대한 질문입니다.
온라인 게임을 하다보면 pc의 성능이 안좋거나 인터넷 환경이 불안정한 경우 렉이 걸려 해당 유저의 캐릭터가 멈추는 경우를 봤습니다. 이는 아마도 서버와 패킷을 전송하는 과정에서 pc성능의 문제로 패킷을 소화하지 못하거나 인터넷이 끊겨 패킷을 제때 전달받지 못해서 발생하는 문제라고 생각합니다. 그렇다면 반대의 경우 pc 성능이나 인터넷 환경이 타유저에 비해 압도적으로 뛰어난 경우는 타 유저에 비해 보다 많은 패킷을 주고 받을 수 있을 거라 생각합니다. 그럴 경우 타인보다 더 많은 이동, 공격을 하는 등 유저 간 벨런스에 문제가 생길 것 같고 그를 방지하기 위해 패킷 전송에 있어 일종의 상한선을 걸어야 하지 않을까 라는 생각을 합니다. 마치 프레임 제한을 거는 것처럼요. 이게 맞다면 제 개인적인 판단으로는 그러한 한 번에 전송할 수 있는 패킷의 양, 전송대기 시간 등을 클라이언트 쪽에서 제한하는 쪽으로 코드를 짜야하는 게 맞다고 생각이 드는데 이런 부분을 클라쪽에서 관리를 해야할까요? 아니면 서버 쪽에서 관리를 해줘야 할까요? -- 번외의 질문입니다. 롤의 경우 렉이 걸리는 유저는 혼자 렉이 걸리고 심할 경우 게임에서 나가지는 식인 반면에 닌텐도의 슈퍼마리오메이커2는 유저대전에서 한 명이 렉이 걸리면 전원이 렉이 걸리는 방식으로 알고 있습니다. 게임을 개발하는 개발자로서 마리오 방식보다는 롤의 방식이 유저에게 좀 더 긍정적인 평가를 받을 수 있을 거라 생각하는데 게임사 측에서 마리오 방식을 택하는 이유가 있을까요? 늘 좋은 강의 감사합니다.^^
-
미해결[유니티 레벨 업!] 모듈식으로 개발하는 퀘스트&업적 시스템
미션 클리어 문의
선생님 첫번째 door에 가는 미션을 진행중인데 Second door에 가도 미션이 클리어되버리고 다음 미션인 두번째 키를 얻으라는 미션이 출력됩니다 ㅠ
-
해결됨[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part3: 유니티 엔진
UI 자동화 #1 Bind()함수 질문입니다
UI 자동화 #1 강의를 보다 Bind() 함수가 이해가 잘 안되어서 질문드립니다. enum ‘Buttons’는 Button을 컴포넌트로 가진 GameObject들의 목록이다. Bind()는 이 Buttons의 Type를 넘겨받아서 Dictionary ‘_objects’에 Key: 해당 컴포넌트 종류 Value: 해당 컴포넌트를 가진 GameObject들의 배열 형태로 맵핑해준다. Bind()는 나의 자식들 중, 해당 컴포넌트를 가진 GameObject들을 찾아주는 역할을 한다. 라고 이해하면 되는 걸까요?
-
미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part3: 유니티 엔진
매니저 구현 부분 질문이 있습니다.
인풋 매니저나 리소스 매니저 등등 여러 매니저를 구현하실 때 도통 이해가 잘 되지 않습니다... 개념 이해하지 못하고 무작정 클론 코딩만 하고 있는데, 일단은 넘어가도 괜찮을까요?
-
해결됨[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part3: 유니티 엔진
UI_Inven에서 Bind시 오류가 발생합니다
UI_Inven에서 Bind<GameObject>(typeof(GameObjects));를 할 때 오류가 떠서 breakpoint를 잡아보니 이 부분의 foreach문 에서 오류가 발생합니다 ArgumentException: GetComponent requires that the requested component 'GameObject' derives from MonoBehaviour or Component or is an interface. UnityEngine.GameObject.GetComponentsInChildren[T] (System.Boolean includeInactive) (at <4a31731933e0419ca5a995305014ad37>:0) UnityEngine.GameObject.GetComponentsInChildren[T] () (at <4a31731933e0419ca5a995305014ad37>:0) Util.FindChild[T] (UnityEngine.GameObject go, System.String name, System.Boolean recursive) (at Assets/Scripts/Utils/Util.cs:43) UI_Base.Bind[T] (System.Type type) (at Assets/Scripts/UI/UI_Base.cs:23) UI_Inven.Init () (at Assets/Scripts/UI/PopUp/UI_Inven.cs:21) UI_Inven.Start () (at Assets/Scripts/UI/PopUp/UI_Inven.cs:14) Bind할 때 GameObject가 아닌 Transform으로 Bind를 해보니 오류 없이 정상적으로 작동했습니다 해결은 했지만 강의에서는 GameObject를 받아서 잘 되었는데 저는 안 되는 건지 궁금해서 질문을 남겨봤습니다.. 강의랑 버젼이 달라서 그런 것인가요??
-
미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part3: 유니티 엔진
강의 관련 질문드립니다!
안녕하세요! 이제 막 파트3을 입문하려고 하는데 이전 파트2가 너무 어려워서 질문드립니다... 파트2를 수강하며 거의 무슨 내용인지도 모르고 클론 코딩만 한 거 같습니다ㅠㅠ 혹시 파트2를 완전히 숙지하지 못한 상태에서 파트3을 듣기에는 무리가 있는지 싶어 여쭈어봅니다!