파이어베이스 Authentication 게임이 시작되고 게스트로그인 ContinueWith을 통해 계정생성이 잘 완료되고 Realtime Database에도 USER라는 곳에 데이터가 잘 저장되고 불러오기가 되는데 (익명) 사용자가 바로 생성되지 않습니다 무슨 문제일까요?? 시간이 한참 지나면 생성되어져 있습니다. (강의영상보면 바로 생성되던데 저는 안되네요)
안녕하세요 선생님 다름이 아니라 스크립터블 오브젝트를 활용해서 액션 함수를 만들어서 플레이어의 정보를 갱신하고 갱신이 되면 UI 를 관리하는 곳에서 해당 UI 의 정보를 같이 갱신하는 식으로 구현되는 걸로 알고 있는데요 만약에 플레이어의 MaxHp 가 변한다거나 총알의 MaxAmmo 가 변하는 경우에는 UI 를 관리하는 곳에서도 Player와 Weapon 의 정보를 같이 들고 있어야 하는건가요? 아니면 다른 처리 방식이 있을까요?
scene을 전환하실 때 단순히 DontdestroyOnLoad를 활용해서 고정시켜둘 객체들을 고정시켜두고 scene을 전환하셔서 구현하셨는데요... additive를 활용해서 mainscene에 고정시켜둘 객체들을 두고 mapscene들을 비동기로 로딩하는 방식이 어떤차이가 있는지 궁금합니다...
콜백 함수 콜백 함수는 update에서 도는 건가요? 매 프레임마다 충돌되는지 안 되는지 체크를 해야 충돌 감지를 할 것 같은데... Start함수랑 Update함수 다 지우고 void OnCollisionEnter 함수만 둬도 잘 돌아가는 게 무슨 원리인지 궁금해요. 가비지 콜렉션 시니어 프로그래머가 아닌 이상 입문자에게 이것까지 관리하기엔 어려울 것 같은데, 그냥 "==문자열" 이 코드만 피하면 되는 걸까요?
안녕하세요 강의 잘 듣고 있는 학생입니다. 다름이 아니라 스크립터블 오브젝트로 변수들을 저장하여 메모리 사용의 효율과 확장성을 늘리는 부분에 대해서는 너무 좋은 방법이고 이해를 했습니다. 근데 이펙트, 사운드 등의 파일도 Pooling 방식으로 사용이 가능 하고 효율은 어떤게 더 좋은지 궁금해서 입니다. 예를들어 EffectManager 라는 오브젝트내에 사용할 Effect 들을 넣어두고 그 Effect 가 사용되는 시점에 enable 이 됐다가 사용이 끝나면 다시 disable 되고 다른곳에서 사용되면 다시 enable 로 사용하는 방식으로 하는 방법도 있던데 이런 방법의 장단점과 차이점에 대해서 알고 싶습니다.
안녕하세요 시간이 많이 흐른 지금도 보실지는 모르겠지만 강의 중에 궁금한게 있어서 질문 드립니다. Physics.OverlapSphere 을 사용하면 공격 대상이 빠르게 움직이면 공격을 받지 않는다고 하셔서 Physics.CastSphere 이걸 사용하셔서 움직인 궤적 사이에 겹치는 물체를 감지 해서 공격이 가능하게 구현을 하셨는데 만약에 좀비가 공격을 할때 플레이어가 움직이면서 피하고 데미지를 받지 않게 하려면 Physics.OverlapSphere이걸 써서 그냥 구현하면 되는건가요?
이 서버코드를 가지고 오목게임을 구현해보고 싶은데요 랜덤매칭을 해서 매칭이 된다면 방을 만들어서 방에서 조작하는게 맞겠죠 ? 그럼 GameRoom 은 전체 시스템에 대한 접속이라 생각하고 ( 전쳇말 등등을 위한 ) GameActualRoom 이란걸 만들어서 매칭된사람들끼리의 룸 이라고 생각하고 만들면될까요 ? ..
미로 생성 25*25 격자가 콘솔창에 출력 되지 않고 있습니다.. 1.Board 코드 ***************************************************************************** using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace C__알고리즘_6_플레이어_이동 { class Board { const char CIRCLE = '\u25cf'; public TileType[,] Tile { get; private set; } //배열 public int Size { get; private set; } public int DestY { get; private set; } public int DestX { get; private set; } Player _player; public enum TileType { Empty, Wall, } public void Initialize(int size, Player player) { if (size % 2 == 0) return; _player = player; Tile = new TileType[size, size]; Size = size; DestY = Size - 2; DestX = Size - 2; GenerateBySideWinder(); } public void GenerateBySideWinder() { // 일단 길을 다 막아버리는 작업 for (int y = 0; y < Size; y++) { for (int x = 0; x < Size; x++) if (x % 2 == 0 || y % 2 == 0) Tile[y, x] = TileType.Wall; else Tile[y, x] = TileType.Empty; } // 랜덤으로 우측 혹은 아래로 길을 뚫는 작업 // Binary Tree Algorithm Random rand = new Random(); for (int y = 0; y < Size; y++) { int count = 1; for (int x = 0; x < Size; x++) { if (x % 2 == 0 || y % 2 == 0) continue; if (y == Size - 2 && x == Size - 2) continue; if (y == Size - 2) { Tile[y, x + 1] = TileType.Empty; continue; } if (x == Size - 2) { Tile[y + 1, x] = TileType.Empty; continue; } if ( rand.Next (0, 2) == 0) { Tile[y, x + 1] = TileType.Empty; count++; } else { int ramdomIndex = rand.Next (0, count); Tile[y + 1, x - ramdomIndex * 2] = TileType.Empty; count = 1; } } } } public void Render() { ConsoleColor prevColor = Console.ForegroundColor; for (int y = 0; y < Size; y++) { for (int x = 0; x < Size; x++) { // 플레이어 좌표를 갖고 와서, 그 좌표랑 현재 y, x가 일치하면 플레이어 전용 색상으로 표시 if (y == player.PosY && x == player.PosX) Console.ForegroundColor = ConsoleColor.Blue ; else if(y == DestY && x == DestX) Console.ForegroundColor = ConsoleColor.Yellow; else Console.ForegroundColor = GetTileColor(Tile[y, x]); Console.Write(CIRCLE); } Console.WriteLine(); } Console.ForegroundColor = prevColor; } ConsoleColor GetTileColor(TileType type) { switch (type) { case TileType.Empty: return ConsoleColor.Green ; case TileType.Wall: return ConsoleColor.Red ; default: return ConsoleColor.Green ; } } } } ***************************************************************************** 2. Player 코드 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace C__알고리즘_6_플레이어_이동 { class Pos { public Pos(int y, int x) { Y = y; X = x; } public int Y; public int X; } class Player { public int PosY { get; private set; } public int PosX { get; private set; } Random _random = new Random(); Board _board; enum Dir { Up = 0, Left = 1, Down = 2, Right = 3 } int _dir = (int)Dir.Up; List<Pos> _points = new List<Pos>(); public void Initialize(int posY, int posX, Board board) { PosY = posY; PosX = posX; _board = board; // 현재 바라보고 있는 방향을 기준으로, 좌표 변화를 나타낸다. int[] frontY = new int[] { -1, 0, 1, 0 }; int[] frontX = new int[] { 0, -1, 0, 1 }; int[] rightY = new int[] { 0, -1, 0, 1 }; int[] rightX = new int[] { 1, 0, -1, 0 }; _points.Add(new Pos(PosY, PosX)); // 목적지 도착하기 전에는 계속 실행 while (PosY != board.DestY || posX != board.DestX) { // 1. 현재 바라보는 방향을 기준으로 오른쪽으로 갈 수 있는지 확인. if (_board.Tile[PosY + rightY[_dir], PosX + rightX[_dir]] == Board.TileType.Empty) { // 오른쪽 방향으로 90도 회전 dir = ( dir - 1 + 4) % 4; // 앞으로 한 보 전진. PosY = PosY + frontY[_dir]; PosX = PosX + frontX[_dir]; _points.Add(new Pos(PosY, PosX)); } // 2. 현재 바라보는 방향을 기준으로 전진 할 수 있는지 확인. else if (_board.Tile[PosY + frontY[_dir], PosX + frontX[_dir]] == Board.TileType.Empty) { // 앞으로 한 보 전진 PosY = PosY + frontY[_dir]; PosX = PosX + frontX[_dir]; _points.Add(new Pos(PosY, PosX)); } else { //왼쪽 방향으로 90도 회전 dir = ( dir + 1 + 4) % 4; } } } const int Move_TICK = 10; int _sumTick = 0; int _lastIndex = 0; public void Update(int deltaTick) { if (_lastIndex >= _points.Count) return; _sumTick += deltaTick; if(_sumTick >= Move_TICK) { _sumTick = 0; PosY = points[ lastIndex].Y; PosX = points[ lastIndex].X; _lastIndex++; } } } } ***************************************************************************** 3. Progarm 코드 namespace C__알고리즘_6_플레이어_이동 { internal class Program { static void Main(string[] args) { Board board = new Board(); Player player = new Player(); board.Initialize(25, player); player.Initialize(1, 1, board); Console.CursorVisible = false; const int WAIT_TICK = 1000 / 30; int lastTick = 0; while (true) { #region 프레임 관리 int currentTick = Environment.TickCount & Int32.MaxValue; // FPS 프레임 (60프레임 O 30프레임 이하 X) // 만약에 경과한 시간이 1/30초보다 작다면 if (currentTick - lastTick < WAIT_TICK) continue; int deltaTick = currentTick - lastTick; lastTick = currentTick; #endregion // 입력 // 로직 player.Update(deltaTick); // 렌더링 Console.SetCursorPosition(0, 0); board.Render(); } } } }
F11을 눌러서 확인 했을 때 public void GenerateBySideWinder() { // 일단 길을 다 막아버리는 작업 for (int y = 0; y < Size; y++) { for (int x = 0; x < Size; x++) if (x % 2 == 0 || y % 2 == 0) Tile[y, x] = TileType.Wall; else Tile[y, x] = TileType.Empty; } 이 부분에서 무한루프를 돌고 있습니다 아래는 전체 코드입니다. using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace C__알고리즘_6_플레이어_이동 { class Board { const char CIRCLE = '\u25cf'; public TileType[,] Tile { get; private set; } //배열 public int Size { get; private set; } public int DestY { get; private set; } public int DestX { get; private set; } Player _player; public enum TileType { Empty, Wall, } public void Initialize(int size, Player player) { if (size % 2 == 0) return; _player = player; Tile = new TileType[size, size]; Size = size; DestY = Size - 2; DestX = Size - 2; GenerateBySideWinder(); } public void GenerateBySideWinder() { // 일단 길을 다 막아버리는 작업 for (int y = 0; y < Size; y++) { for (int x = 0; x < Size; x++) if (x % 2 == 0 || y % 2 == 0) Tile[y, x] = TileType.Wall; else Tile[y, x] = TileType.Empty; } // 랜덤으로 우측 혹은 아래로 길을 뚫는 작업 // Binary Tree Algorithm Random rand = new Random(); for (int y = 0; y < Size; y++) { int count = 1; for (int x = 0; x < Size; x++) { if (x % 2 == 0 || y % 2 == 0) continue; if (y == Size - 2 && x == Size - 2) continue; if (y == Size - 2) { Tile[y, x + 1] = TileType.Empty; continue; } if (x == Size - 2) { Tile[y + 1, x] = TileType.Empty; continue; } if ( rand.Next (0, 2) == 0) { Tile[y, x + 1] = TileType.Empty; count++; } else { int ramdomIndex = rand.Next (0, count); Tile[y + 1, x - ramdomIndex * 2] = TileType.Empty; count = 1; } } } } public void Render() { ConsoleColor prevColor = Console.ForegroundColor; for (int y = 0; y < Size; y++) { for (int x = 0; x < Size; x++) { // 플레이어 좌표를 갖고 와서, 그 좌표랑 현재 y, x가 일치하면 플레이어 전용 색상으로 표시 if (y == player.PosY && x == player.PosX) Console.ForegroundColor = ConsoleColor.Blue ; else if(y == DestY && x == DestX) Console.ForegroundColor = ConsoleColor.Yellow; else Console.ForegroundColor = GetTileColor(Tile[y, x]); Console.Write(CIRCLE); } Console.WriteLine(); } Console.ForegroundColor = prevColor; } ConsoleColor GetTileColor(TileType type) { switch (type) { case TileType.Empty: return ConsoleColor.Green ; case TileType.Wall: return ConsoleColor.Red ; default: return ConsoleColor.Green ; } } } }
저는 유니티6를 0.38f1 버전을 사용하고 있는데요 카메라에서 Dead Zone, Soft Zone 등이 안보여서 찾아보니 FreeLook 카메라 인스펙터 창에서 Status Live 부분을 클릭해주시고 아래 Rig 관리하는 부분에 Aim 이라는 탭을 여시면 선생님이 화면에서 보시던 Zone 설정하는 부분이 보이게 됩니다.
강의를 따라 진행중 다음과 같은 오류가 발생하였습니다. " 'Items'속성의 코드를 생성하지 못했습니다 ... "KaburiKiosk.Moels.Product" 형식이 serializable로 표시 되어 있지 않습니다" 해당 오류는 Product Class에 [Serializable] 속성을 달아주니 해결이 되었지만 강의에서는 따로 설정 해주는 부분이 없어도 잘 실행되는 것을 볼 수 있는데 버전 차이로 인해 발생하는 문제일까요? 궁금합니다