묻고 답해요
145만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결따라하면서 배우는 고박사의 유니티 하이퍼캐주얼게임 시리즈 02
1010 프리팹 생성 질문
BackgroundBlockSpawner 스크립트에서프리팹을 생성하는 // 블록 생성 (원본 프리팹, 위치, 회전, 부모 Transform)GameObject clone = Instantiate(blockPrefab, position, Quaternion.identity, transform);부분에서 마지막 부모 Transform 위치에 적은 transform 작성 이유를 모르겠습니다... 뭔가 프리팹이 생성 될 때, 어떤 부모 오브젝트의 자식으로 프리팹이 생성되는 것 같은데.. 정확한 설명 부탁드립니다.
-
미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part7: MMO 컨텐츠 구현 (Unity + C# 서버 연동 기초)
학습자료 실행 관련 문의
안녕하세요 학습자료 다운로드 후 실행 관련해서 질문 드립니다..csproj파일이 있는 클라이언트 폴더를 유니티로 실행 시키고, 게임 씬을 더블클릭 하고 실행했는데 작동이 되질 않더라구요. 보면 하이라키에 있는 인스턴스들이 보이질 않는데 매번 프로젝트를 실행할 때마다 하이라키를 추가를 해줘야 하나요???또 전체 흐름 로그를 한번 찍어보고 싶은데 어떤 식으로 찍어봐야 할지 모르겠습니다.
-
미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
강의에서 쓰레드 생성되는게 제가 이해한게 맞을까요?
다만 Listener의 Init 부분에서 위 사진의 코드가 register개 만큼 쓰레드를 생성한다고 보면 맞을까요? 그리고 C++에서는 여러개의 Worker Thread가 GetQueuedCompletionStatus 로 이벤트 분기에 따라 send, recv, accept, connect 등을 처리해줬는데, 이 코드는 Accept만 멀티쓰레드로 처리하고 Send, Recv는 싱글쓰레드로 처리되는건가요?
-
미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part3: 유니티 엔진
unitychan의 프리팹을 만들 수가 없습니다.
"폴더 정리" 강의의 9:51초 화면에서는유니티쨩의 모델을 hierachy로 뺀 후 playercontroller 스크립트 적용 후, 프리팹 폴더로 빼면서 프리팹을 만드는 화면이 나오는데, 제쪽에서는 유니티쨩 모델을 hierachy 창으로 끌어당기면 강의 화면처럼 inspector 창에 Model 이라는 표시 대신, 이미 프리팹이 적용된 것 처럼 나와 유니티쨩을 프리팹으로 만들려고 하면 prefab variant로만 만들 수 있다고 창이 표시됩니다. 분명 말씀하신대로 tank 프리팹과 유니티쨩 모델의 앞부분 박스 상자 아이콘은 다른데, 유니티쨩에게서 모델이라는 내용을 강의와는 다르게 찾아볼 수가 없습니다. 현재 22.2.16 버전을 사용중인데 버전이 올라가면서 해당 내용이 뭔가 수정된 부분이 있는걸까요?
-
미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part7: MMO 컨텐츠 구현 (Unity + C# 서버 연동 기초)
Tilemap.cellBounds에 관련해서 질문 있습니다.
제가 Tilemap을 아래와 같이 만들어 놨는데요,cellBounds에 break point를 잡아서 디버깅을 해보니 x.Max = 20, y.Max = 9가 나오더라구요. (제가 찍은 tilemap을 일일히 하나하나 세보니 x의 최대 좌표는 19고 y는 8인데도 말이죠.)그렇다면 위 코드와 같이 반복문을 돌면 타일이 찍혀있지 않는 y = 9, x = 20 일 때도 반복문을 도니까 제가 만든 맵보다 가로 세로가 한 줄씩 늘어나게 출력됩니다. (아래 사진처럼 맨 윗줄과 오른쪽 줄에 0이 출력되서 나옵니다.)제가 생각하기에는 아래와 같이 코드를 짜야 알맞은xMin, xMax, yMin, yMax값과 map이 출력될 거 같은데 혹시 제가 틀린건가요?using (var writer = File.CreateText($"Assets/Resources/Map/{go.name}.txt")) { writer.WriteLine(tmBase.cellBounds.xMin); writer.WriteLine(tmBase.cellBounds.xMax - 1); writer.WriteLine(tmBase.cellBounds.yMin); writer.WriteLine(tmBase.cellBounds.yMax - 1); for (int y = tmBase.cellBounds.yMax - 1; y >= tmBase.cellBounds.yMin; y--) { for (int x = tmBase.cellBounds.xMin; x < tmBase.cellBounds.xMax; x++) { TileBase tile = tm.GetTile(new Vector3Int(x, y, 0)); if (tile != null) writer.Write("1"); else writer.Write("0"); } writer.WriteLine(); } }
-
미해결따라하면서 배우는 고박사의 유니티 하이퍼캐주얼게임 시리즈 01
IEnumerator 사용이유?
코루틴을 사용하는 이유가 뭔가요?시간이 지난 뒤에 함수를 실행하기 위해서는 Invoke를 사용하고반복을 위해서는 While을 사용하면 되지않나요? 너무 햇갈려요..
-
해결됨두고두고 써먹는 유니티 VR
5-2. Teleportation - Basic관련 문의드립니다.
학습내용 확인하여 실행하고 공지사항 확인하여 세팅후 실행하였으나래이캐스트 및 텔레포트가 되지 않아서 프로젝트 압축파일을 보냈습니다.ㅜㅜ확인 부탁드립니다.항상 친절한 답변 감사드립니다.
-
해결됨[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
서버엔진 수요에 관해서 질문드립니다.
대학 게임학과에 재학 중인 학생입니다.교수님과 게임서버프로그래밍에 대해 상담을 나누는 도중교수님께서 MMORPG를 포함한 대부분의 프로젝트에서 서버를 직접 만드는 경우는 거의 없고언리얼 데디케이트, 포톤, 프라우드넷 같은 이미 만들어진 모델이나 서버엔진을사용한다고 말씀하셨는데 정말인가요?보통 반대로 대부분의 프로젝트가 게임에 맞춰 서버엔진을 제작하는 줄 알았는데제가 알던 상식과는 너무 달라서 질문드립니다.
-
미해결따라하면서 배우는 고박사의 유니티 하이퍼캐주얼게임 시리즈 01
2D Wave.Io 카메라 흔들기 질문
카메라 흔들기 스크립트를 작성하여 싱글톤하는 이유는카메라 흔들기 효과 자체가 게임오버뿐만아니라 여러 가지 스크립트에서 사용 가능하게 하기 위해서 인가요?그리고 카메라 흔들기 스크립트를 싱글톤화하고 다른 스크립트도 싱글톤화 하여도 상관 없나요?
-
해결됨두고두고 써먹는 유니티 VR
Gun Grab관련 문의드립니다.
안녕하세요 강사님~Gun Grab관련 문의드립니다.실행하면 컨트롤러 동작에는 문제가 없는데 Grab만 안되어서 문의드립니다.밑에 동일증상 게시글이 있어 확인해봤는데 다 설정이 잘 되어있는데 안되서 질문드립니다.혹시 제가 XR Interaction Toolkit을 2.3.1버전을 쓰고 있는데 그게 원인일까요?
-
미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part7: MMO 컨텐츠 구현 (Unity + C# 서버 연동 기초)
화살 쏘는 것을 처리하는 방식
안녕하세요 루키스님!제가 루키스님이 강의중 만드신 게임에서 쓰이는 좌표를 float으로 바꾸고 화살이 이동하는 방식을 수정하였습니다.(저는 화살이 아니라 기본 동그라미 이미지의 총알로 사용해봤습니다)수정 내용은 화살 이동 로직을 처리하는 방법입니다. 기존 로직은 서버에서 GetFrontCellPos 함수를 이용하여 서버에서 이동된 좌표를 클라로 알려줘 이동되는 것으로 알고 있습니다. 클라에서는 UpdateMoving를 통해 움직이고 있구요!GetFrontCellPos 함수를 활용하여 서버에서 화살을 움직이기에는 좌표 단위가 Int가 아니라 float이니 어떻게 해결 해야할지 고민을 하다가 생각난 방법이 있습니다.화살을 쏜 후 유니티의 update 문에서 60fps로 서버에 화살이 이동했다는 것을 가르쳐준 후 브로드캐스팅 되게 했습니다. 그 후 서버에서는 받은 패킷에 따라 브로드 캐스팅하게 핸들링 해줬구요.이제 2명을 접속시키고 화살을 쏴보니 패킷이 밀려서 그런지 몰라도 쐈던 자리로 다시 롤백되는 현상을 발견했습니다(배그에서 트레이서 되는 느낌)60fps가 너무 자주 요청하는 건가 싶어서 15fps로 돌리니 클라 화면에서 내가 쏜 총알은 똑같이 롤백되면서 총알이 나가지만 다른 Player가 쏜 총알은 롤백이 되지 않았습니다. 하지만 이동된다기 보다는 순간이동 하는 것 처럼 보이기 시작했습니다.몇가지 실험을 해보니 혼자 접속중일때는 총알이 롤백현상이 일어나지 않고 곧게 잘 날아가는 것을 확인할 수 있으나 인원수가 한 명 늘어나는 순간부터 총알의 롤백 현상이 생기는 것을 확인했습니다. 브로드 캐스팅의 연산량이 늘어나서 패킷이 밀리는 것이 원인인 것 같습니다.C_SkillMove, S_SkiilMove 라는 패킷을 새로 파주고 실행했습니다. message C_SkillMove{int32 objectId = 1;PositionInfo posInfo = 2;}message S_SkillMove{int32 objectId = 1;PositionInfo posInfo = 2;}클라의 업데이트 문에선if (Time.frameCount % 15== 0){C_SkillMove skillMovePacket = new C_SkillMove();PosInfo.PosX = transform.position.x;PosInfo.PosY = transform.position.y;skillMovePacket.PosInfo = PosInfo;skillMovePacket.ObjectId = Id;Managers.Network.Send(skillMovePacket);} 이런 코드로 움직입니다. 서버에선public static void C_SkillMoveHandler(PacketSession session, IMessage packet){C_SkillMove skillMovePacket = packet as C_SkillMove;ClientSession clientSession = session as ClientSession;Arrow arrow= ObjectManager.Instance.Find<Arrow >(skillMovePacket.ObjectId);if (arrow== null)return;GameRoom room = arrow.Room;if (room == null)return;room.HandleSkillMove(arrow, skillMovePacket);} 이런식으로 핸들링 하고 HandleSkillMove 함수는 public void HandleSkillMove(Arrow arrow, C_SkillMove skillMovePacket){if (arrow == null)return;lock (_lock){ObjectInfo info = arrow.Info;info.PosInfo = skillMovePacket.PosInfo;S_Move resMovePacket = new S_Move();resMovePacket.ObjectId = arrow.Info.ObjectId;resMovePacket.PosInfo = skillMovePacket.PosInfo;Broadcast(resMovePacket);}}이런 로직으로 움직입니다.float일 때의 서버에서 이동 처리 방법이 궁금합니다! 또한 위처럼 순간이동되게 가는 것을 방지하는 법도 궁금합니다.. (스르륵 이동하게 처리하는 부분)
-
미해결유니티 Addressable 을 이용한 패치 시스템 구현
CheckForCatalogUpdates() 대한 이해
1)Addressables.CheckForCatalogUpdates()를 통해 업데이트 할께 있다. 없다를 판단 하는거 같습니다. 체크를 통해 Count가 0 이상이면 업데이트 할께 있으므로 다운로드 진행으로 알고 있습니다. 그런데 의문점 드는 부분의 코드가 CheckForCatalogUpdates() 체크 후Count 0 이상 > 카탈로그 업데이트 > 다운로드 사이즈 체크 Count 0 이하 > 다운로드 사이즈 체크 2번 같은 경우 카탈로그 체크로 인해 0 이므로 다운로드를 받을 필요가 없는데 굳이 다운로드 사이즈 체크해서 다운로드를 하는 이유가 무엇인가요? 2) 제공 해주신 프로젝트로 카탈로그 테스트 중 이상 현상이 나와 질문 드립니다. 번들 빌드를 한후 서버에 올리고 다운을 받으면, AppData\LocalLow\Unity/프로젝트이름/ 위치로 다운 받아 지는 거 같습니다. 다시 테스트를 위해 위 위치의 캐시를 지운 후 테스트를 하면 카탈로그체크카운트가 0입니다.내 캐쉬에 없는데도 카탈로그체크카운트가 0이상이지 않습니다. 혹시나 몰라 addressables_content_state.bin도 삭제 Group > Clean Build 를 해보아도 카탈로그체크카운트가 카운트 되지 않습니다.최초 실행은 카탈로그체크카운트가 카운트 되지 않나요?아님 리셋 시키는 방법이 있을까요?
-
미해결유니티 머신러닝 에이전트 완전정복 (기초편)
unity ML-Agent 생성 모델 활용한 inference
unity에서 디지털 트윈환경을 구축하고 ML-Agent로 학습한 모델을실제 운영환경에 적용하여 inference하려고 할 때모델 input/output은 어떻게 구성할 수 있나요?참고할 만한 자료가 있을까요?
-
미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part3: 유니티 엔진
unitychan 프리팹에 Poolable 스크립크를 추가하면 nullreference 에러가 발생합니다.
pool manager #3강을 듣고 있습니다.유니티짱 프리팹에 Poolable을 삽입하고 실행하면NullReferenceException 에러가 발생합니다.코드는 아래와 같습니다.답변해주시면 감사하겠습니다. ㅜㅜ//Poolable.cs using System.Collections; using System.Collections.Generic; using UnityEngine; public class Poolable : MonoBehaviour { //오브젝트가 이 컴포넌트를 들고 있으면 메모리 풀링 적용 public bool isUsing; //풀링이 됐는지 확인 } //PoolManager.cs using System.Collections; using System.Collections.Generic; using UnityEngine; public class PoolManager { #region Pool class Pool { public GameObject Original { get; private set; } #region 설명 /*이 속성은 get 접근자를 가지고 있어 Original GameObject을 가져올 수 있습니다. 또한 private set 접근자를 가지고 있어 Original GameObject을 Pool 클래스 내부에서만 설정할 수 있습니다. private set 접근자가 있는 속성을 사용하면 값을 읽을 수는 있지만 클래스 외부에서 그 값을 변경할 수 없습니다. 이렇게 하면 Original GameObject은 Pool 클래스의 lnit() 메서드로만 설정할 수 있으므로 풀을 특정 GameObject로 초기화할 수 있습니다.*/ #endregion public Transform Root { get; set; } #region 설명 /* //이 코드는 Pool 클래스의 Root 속성을 나타냅니다. 이 속성은 해당 풀에 속한 오브젝트들을 담을 게임 오브젝트의 Transform 컴포넌트입니다. get 접근자와 set 접근자를 모두 가지고 있으므로, 해당 속성은 읽기 및 쓰기가 가능합니다. Root 속성이 null인 경우, 새로운 게임 오브젝트의 Transform 컴포넌트를 만들어 Root 속성으로 할당합니다. */ #endregion Stack<Poolable> _poolStack = new Stack<Poolable>(); #region 설명 /* Pool 클래스 내부에 Stack<Poolable> 타입의 _poolStack 멤버 변수를 선언합니다. 이 스택은 풀링을 위해 사용되며, Poolable 객체의 인스턴스들을 담아 놓습니다*/ #endregion public void lnit(GameObject original, int count = 5) #region 설명 /*인자로 original, count를 받아서 Original, Root를 초기화합니다. Original은 Pool 클래스 내에서 사용되는 GameObject 변수이며, Root는 Pool 내에서 생성된 객체들의 부모 객체로 사용됩니다. 그리고 for문을 사용하여 count만큼 Create 함수를 호출하여 Poolable 객체들을 생성하고 Push 메서드를 호출하여 Stack에 추가합니다. Push 메서드는 Pool 클래스 내부에 구현되어 있으며, Poolable 객체를 Stack에 추가하고 비활성화합니다. */ #endregion { Original = original; Root = new GameObject().transform; Root.name = $"{original.name}_Root"; for (int i = 0; i < count; i++) { Push(Create()); } } Poolable Create() #region 설명 /*Create() 메소드는 새로운 객체를 생성하고, 이를 Poolable 컴포넌트를 추가한 뒤 반환합니다. 첫 번째로 Instantiate 메소드를 사용하여 Original 게임 오브젝트의 복사본을 만들어 go 변수에 할당합니다. 이후 go 변수의 이름을 Original 게임 오브젝트의 이름으로 변경합니다. 마지막으로 go.GetOrAddComponent<Poolable>() 메소드를 호출하여 Poolable 컴포넌트가 이미 추가되어 있으면 해당 컴포넌트를 반환하고, 추가되어 있지 않으면 새로운 Poolable 컴포넌트를 추가한 뒤 반환합니다. 이렇게 반환된 Poolable 컴포넌트가 Push 메소드에서 사용됩니다. */ #endregion { GameObject go = Object.Instantiate<GameObject>(Original); // 복사본은 go에 저장 go.name = Original.name; return go.GetOrAddComponent<Poolable>(); } public void Push(Poolable poolable) #region 설명 /*Push 함수는 Poolable 객체를 받아서 _poolStack 스택에 저장합니다. 이 함수는 객체 풀링의 핵심입니다. 먼저 poolable이 null인 경우, 즉 재활용할 객체가 없는 경우 함수를 바로 종료합니다. 그렇지 않으면, poolable의 transform의 parent를 Root로 설정하여 원본 객체의 하위 개체로 추가합니다. 그리고 gameObject를 비활성화하고, Poolable.isUsing 변수를 false로 설정하여 해당 객체가 사용 중이 아님을 나타냅니다. 마지막으로, poolable을 _poolStack 스택에 푸시합니다. 이렇게 되면 풀에 객체 가 추가되고, 다음에 필요할 때 재활용할 수 있습니다.*/ #endregion { if (poolable == null) return; poolable.transform.parent = Root; #region 설명 /* transform은 Unity 게임 오브젝트의 구성 요소 중 하나로, 게임 오브젝트의 위치, 회전 및 크기를 관리합니다. transform.parent 속성은 해당 게임 오브젝트의 부모 객체의 transform을 나타냅니다. 따라서 poolable.transform.parent = Root; 코드는 poolable 게임 오브젝트의 transform의 부모를 Root로 설정하여, Root 아래에 생성된 모든 게임 오브젝트가 Root의 자식으로서 계층 구조적으로 관리되도록 합니다.*/ #endregion poolable.gameObject.SetActive(false); #region 설명 /* 인자로 전달된 poolable 객체의 게임 오브젝트를 비활성화합니다. 이것은 해당 객체가 풀에 반환되어 사용 가능한 상태가 되었음을 의미합니다.*/ #endregion //업데이트문을 받지않고 수면상태 poolable.isUsing = false; _poolStack.Push(poolable); } public Poolable Pop(Transform parent) #region 설명 /*Pop 함수는 오브젝트 풀에서 사용 가능한 Poolable 객체를 꺼내서 반환하는 함수입니다. parent 매개변수는 반환된 Poolable 객체를 부모로 하는 Transform을 설정할 때 사용됩니다. 함수는 다음과 같은 동작을 수행합니다: _poolStack 스택에서 사용 가능한 Poolable 객체를 가져옵니다. _poolStack 스택에 사용 가능한 Poolable 객체가 없으면 Create() 함수를 호출하여 새로운 Poolable 객체를 만듭니다. 가져온 혹은 새로 만든 Poolable 객체를 활성화합니다. parent 매개변수로 받은 Transform을 부모로 하는 Poolable 객체의 Transform을 설정합니다. isUsing 변수를 true로 설정하여 해당 객체가 사용 중임을 나타냅니다. Poolable 객체를 반환합니다.*/ #endregion { Poolable poolable; if (_poolStack.Count > 0) poolable = _poolStack.Pop(); else poolable = Create(); poolable.gameObject.SetActive(true); poolable.transform.parent = parent; poolable.isUsing = true; return poolable; } } #endregion Dictionary<string, Pool> _pool = new Dictionary<string, Pool>(); #region 설명 /*Dictionary는 key-value pair를 저장할 수 있는 C#의 데이터 구조 중 하나입니다 이 코드는 Dictionary<string, Pool> 타입의 _pool 변수를 선언합니다. Dictionary는 key-value 쌍의 컬렉션으로, 각각의 key에 대응하는 value를 저장합니다. 여기서 key는 string 타입이고 value는 Pool 타입입니다. 따라서 _pool 변수는 string 타입의 key와 Pool 타입의 value를 가지는 Dictionary입니다. 이 변수는 나중에 게임 오브젝트를 풀링할 때 사용됩니다.*/ #endregion //다른곳에 기생 리소스 매니저 보조 Transform _root; #region 설명 /*_root 라는 이름의 Transform 타입 변수를 선언하고 있습니다. Transform은 Unity Engine에서 게임 오브젝트의 위치, 회전, 크기 등의 정보를 담고 있는 컴포넌트입니다. _root 변수는 풀링된 객체들이 모여있는 루트 오브젝트를 가리키는 역할을 합니다. 이 변수는 lnit() 함수에서 생성됩니다.*/ #endregion //트렌스폼은 게임 오브젝트와 연결 public void lnit() #region 설명 /*lnit 함수는 Pool 클래스가 생성될 때 호출되며, Pool 클래스 내부에서 사용되는 변수인 _root를 초기화합니다. _root는 Pool 클래스에서 생성된 모든 객체들이 생성될 때 사용되는 부모 객체입니다. 먼저 if문을 사용하여 _root가 null인지 확인합니다. null이라면, _root가 존재하지 않으므로 새로운 GameObject를 생성하고 _root 변수에 할당합니다. GameObject가 생성되면 해당 GameObject의 이름을 "@Pool_Root"으로 설정하고, Object.DontDestroyOnLoad 함수를 사용하여 게임 오브젝트를 씬 전환시 파괴되지 않도록 합니다. 이렇게 함으로써, Pool 클래스는 게임이 실행되는 동안 계속해서 _root 객체를 사용할 수 있으며, 필요한 경우 Poolable 객체들을 _root 객체의 하위에 위치시켜 관리할 수 있습니다.*/ #endregion { if (_root == null) { _root = new GameObject { name = "@Pool_Root" }.transform; Object.DontDestroyOnLoad(_root); } //게임이 실행된이후로 영구적으로 존재 //풀링이 필요하면 pool_root 산하로 이동해서 보관 } public void CreatePool(GameObject original, int count = 5) #region 설명 /*이 함수는 GameObject을 이용해서 새로운 객체 풀을 생성하는 역할을 합니다. 함수 인자로 original과 count를 받습니다. original은 객체 풀링을 위해 복제할 원본 게임 오브젝트를 의미합니다. count는 생성할 초기 오브젝트 개수를 나타냅니다. 함수 내부에서는 Pool 객체를 생성하고 lnit() 메소드를 이용해 생성한 original과 count를 초기화합니다. 그리고 이 Pool 객체의 Root 프로퍼티를 _root의 자식으로 설정합니다. 마지막으로, _pool 딕셔너리에 original의 이름과 pool을 추가합니다. 따라서, CreatePool() 메소드를 호출하여 객체 풀을 생성하면 해당 원본 게임 오브젝트를 original로 하는 Pool 객체가 생성되고, 이 Pool 객체는 _root 아래에 생성된 후, _pool 딕셔너리에 추가됩니다. 이렇게 생성된 객체 풀은 나중에 필요할 때 GetPool() 메소드를 이용하여 언제든지 접근할 수 있습니다.*/ #endregion { Pool pool = new Pool(); pool.lnit(original, count); pool.Root.parent = _root; //루트를 pool_root에 연결 _pool.Add(original.name, pool); } public void Push(Poolable poolable) #region 설명 /*위 코드는 입력받은 Poolable 객체를 다시 풀에 반환하는 메서드입니다. 입력받은 Poolable 객체의 GameObject 이름을 키로 사용하여, 해당 GameObject의 프리팹이 풀에 존재하는지 검사합니다. ContainsKey 메서드는 Dictionary 클래스에 있는 메서드로, 지정된 키가 Dictionary 컬렉션에 포함되어 있는지 여부를 확인합니다. 여기서는 _pool 딕셔너리에 입력받은 Poolable 객체의 GameObject 이름이 존재하지 않으면, 해당 객체의 게임 오브젝트를 파괴하고 메서드를 종료합니다. 만약 프리팹이 존재하면 해당 객체를 다시 Push 메서드를 이용하여 해당 프리팹의 Pool 객체에 반환합니다.*/ #endregion //풀에다가 푸시하는 함수 //다 사용한다음에 반환하는 작업 { string name = poolable.gameObject.name; if (_pool.ContainsKey(name) == false) #region 설명 /*ContainsKey는 Dictionary<TKey, TValue>에 키가 포함되어 있는지 여부를 반환하는 메서드입니다. 키가 포함되어 있으면 true를, 그렇지 않으면 false를 반환합니다. 예를 들어, Dictionary<string, int> 인스턴스 dict가 있다고 가정해보겠습니다. 이 경우 dict.ContainsKey("apple")은 dict에 "apple"이라는 키가 포함되어 있는지 확인하고, 있으면 true를, 없으면 false를 반환합니다.*/ #endregion { GameObject.Destroy(poolable.gameObject); return; } _pool[name].Push(poolable); } public Poolable Pop(GameObject original, Transform parent = null) #region 설명 /*해당 함수는 풀에서 객체를 꺼내는 역할을 수행하는 함수입니다. 먼저, _pool이 해당 original 객체의 키를 가지고 있는지 확인합니다. 만약 해당 original 객체의 키가 없으면, CreatePool 함수를 통해 새로운 풀을 생성합니다. 그러나 해당 함수에서는 객체를 반환하지 않고, null을 반환하고 있습니다. 객체를 반환하기 위해서는 Pool 클래스의 Pop 함수를 호출해야 합니다. 또한, Transform parent 인자를 활용하여, 해당 객체를 생성한 후, 지정된 부모 객체의 자식으로 추가할 수 있습니다.*/ #endregion // 꺼내는 함수 // parent는 없을 수 도 있다고 체크함. { if (_pool.ContainsKey(original.name) == false) //풀에 오리지날 네임이 있는지 확인 CreatePool(original); return null; } public GameObject GetOriginal(string name) #region 설명 /*이 코드는 이름이 name인 GameObject가 포함된 풀의 Original GameObject를 가져오는 함수입니다. name: 가져오려는 GameObject의 이름 _pool Dictionary에 name을 key로 가지는 Pool이 있는지 검사합니다. 없다면 null을 반환합니다. 있다면 해당 Pool의 Original GameObject를 반환합니다. 이를 통해 필요한 GameObject를 재사용할 수 있습니다.*/ #endregion { if (_pool.ContainsKey(name) == false) return null; return _pool[name].Original; } //@@신이동할때 캐시를 날린다. public void Clear() { foreach (Transform child in _root) #region 설명 /* _root의 자식들에 대해 반복문을 실행하는 코드입니다. _root는 Transform 타입의 변수이며, 생성한 Pool 객체들의 Root Transform을 담고 있는 부모 객체입니다. 즉, _root의 자식들은 Pool 객체의 Root Transform입니다. 따라서 이 코드는 생성한 모든 Pool 객체들의 Root Transform에 대해 반복문을 실행합니다.*/ #endregion //루트 산하에 접근 GameObject.Destroy(child.gameObject); _pool.Clear(); //풀 초기화 } }
-
미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part7: MMO 컨텐츠 구현 (Unity + C# 서버 연동 기초)
이동 동기화 중에서 딜레이후 동기화 처리
실무에 가깝게 적용할만한 캐릭터간 이동 동기화 중에서 딜레이후 동기화 처리에 대한 참고할만한 이론이나 문서 같은것이 있을까요? 게임 장르는 존 방식이고 한 방에 최대 100명 이하? 정도 될것 같은데요환경은 모바일이고요 약.. 서버에서 1초에 4~8번 정도(정확히 아직 1초에 몇번 보내는지는 모릅니다)의 이동관련 패킷을 TCP나 UDP로 보낸다고 가정할 경우 일정 시간 이동 관련 위치 값을 수집해서 보간 처리 해볼까 하는데 언리얼 데디케이트 서버에서 어떻게 해야 할지 좀 막막한것 같은데 관련된 문서나 방식등이 있을까요?루키스님 강의 중 C++ 쪽 서버강의에서 이미 강의는 어느정도 듣긴했지만 이동 관련된것이 없는것 같아서 질문 남깁니다답변좀 부탁드리겠습니다!
-
미해결따라하면서 배우는 고박사의 유니티 하이퍼캐주얼게임 시리즈 01
2D Wave.io 에서 IEnumerator 질문
StageController 스크립트 작성할 때, IEnumerator Start() 함수를 작성하였는데 별도의 StartCoroutine("Start"); 이 없는데 어떻게 실행이 되는건가요?? 마우스 왼쪽 버튼을 눌렀을때 text가 없어지고 게임이 시작되는 부분입니다.
-
해결됨두고두고 써먹는 유니티 VR
콘솔창 내용관련 문의드립니다.
안녕하세요 강사님 섹션 2. XR Interaction Toolkit 개념과 핵심 기능 2. HMD, Controller Tracking 진행중인데 플레이 해보면 작동은 정상적으로 하는데 콘솔창에 아래 메시지가 출력되어 해결방법이 있는지 문의드립니다.유니티 버전은 2020.3.47f1 XR interaction Tollkit은 2.3.1 사용중입니다.
-
미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part3: 유니티 엔진
Data Manager 와 Data.Contents 스크립트의 연결
강의 중에 기존에 DataManager.cs 에서 작성한 Stat class와 DataStat class를 Data.Contents 파일로 이동 후에다른 추가 작업 없이 DataManager 스크립트에서 자연스럽게 Stat 클래스와 DataStat 클래스를 활용할 수 있는 부분이 의문스럽습니다강의처럼 사용할 수 있는 이유를 예상해보았는데 "Asset 폴더 내에 있는 script간에는 접근제한자로 제한하지 않는 경우에는 특별한 지시문 없이도 접근이 가능하다"가 맞는걸까요? 아니면 다른 이유가 있는건지 궁금합니다.
-
미해결따라하면서 배우는 고박사의 유니티 기초
[asset] 이 로딩이 안되는 이유
안녕하세요, 고박사님 인강을 보며 유니티 독학을 하는 학생입니다. 저는 유니티 2021.3.23f1 LTS 버전을 사용하고 있는데 제가 유니티를 켤 때마다NullReferenceException: Object reference not set to an instance of an object라고 콘솔에 경고가 떠서 여러 유튜브 영상을 찾아 똑같이 해결 시도를 해보았지만 늘 떠있습니다. 또한 유니티 홈페이지에서 다운 받은 애셋을 추가하거나, 현재 강의에서 올려주신 것처럼 파일을 다운받아 프로젝트에 옮겨넣어도 무반응입니다.홈페이지에서 다운 받은 에셋을 추가하면 이 창이 뜨고 스킵을 눌러도 아무런 반응이 없습니다..ㅠㅠ제거를 하고 다시 설치를 해보면 좀 해결이 될까요ㅠㅠ?
-
미해결유니티 Addressable 을 이용한 패치 시스템 구현
멀티 라벨 처리 방식 질문
안녕하세요 선생님! 강의 잘 보고있습니다. 현재 제공해주신 샘플 코드가 한개의 라벨에서 어드레서블을 다운로드하는 방식으로 구현되어있는데요. 여러 라벨을 한번에 다운로드하고 관리하는 샘플도 추가해주실수 없을까요? 그게 조금 어려우시면 좀 번거로우실듯 하지만 ..ㅜㅜ 답변으로 심플 하게라도 현재 제공해주신 코드에서 어떤 코드 (몇번째 라인)에 라벨 스트링 배열 값(라벨 목록) 을 삽입하여 처리하면 되는지 권장하시는 방식을 간단 하게라도 알려주시면 감사하겠습니다! ^^