다양한 숫자 형식(int, long, float 등)에 있는 TryParse 메서드를 사용하여 문자열을 숫자로 변환할 수 있다.


문자열의 시작과 끝에 있는 공백은 무시하지만 

다른 모든 문자는 적절한 숫자 형식(int, long, ulong, float, 10진수 등)을 구성하는 문자여야만 한다.

예를 들어 int.TryParse이면 문자열은 반드시 정수가 들어가야 하는 것이다.


1. Parse 메소드


int numVal = Int32.Parse("-105");

Console.WriteLine(numVal);


의 결과는 Output: -105로 정수로 변환이 되어 출력된다.

 

이것은 그냥 Parse로, 값을 변환해주는 메소드이다.

 

1. TryParse 메소드


int j;

if (Int32.TryParse("-105", out j))

    Console.WriteLine(j);

else

    Console.WriteLine("String could not be parsed."); 


TryParse의 반환값은 bool형이며, 성공적으로 변환되었으면 true가, 그렇지 않으면 false가 반환된다.

out j의 의미는
결과값을 j 변수에 저장하라는 의미이다.
변환이 성공한 경우 32비트 부호 있는 정수 값을 반환하고, 변환이 실패한 경우 0을 반환합니다.

위 예제의 경우


"-105"는 정수형 문자열이므로 정상적으로 변환이 성공하게 된다.

따라서, 결과값은 -105가 될 것이며 이 값이 j변수에 저장된다.


끝-

Posted by sungho88
,

[개념]


이전의 일반적인 사이트는 단순히 클라이언트의 요청(request)과 서버의 응답(response)로 작동했다.

주소창에 URL주소를 입력하거나, 웹사이트에 들어가 뉴스 링크를 클릭하는 등의 동작으로 Request가 발생하는데 

이 Request가 서버로 전달되면 서버는 Response를 보낸다. 즉, 서버는 클라이언트의 Request가 없으면 데이터를 전송하지 않는다. Request가 클라이언트쪽에서 먼저 시작되고, 그 request에 대한 response만 전달되었다.


웹이 발전하면서 웹소켓(Websocket)이 생겼고, 좀 더 자유롭게 데이터를 주고 받을 수 있게 되었다.

하지만, 지원하지 않는 브라우저가 있을 수 있고, 오래된 버전에서는 사용할 수 없다는 단점이 있다.

이런 단점을 보완하여 브라우저와 상관없이 웹에서 실시간으로 데이터를 처리할 수 있게 해주는 것이 socket.io이다.

TCP 구현보다 비교적 쉽게 구현할 수 있기 때문에 데이터를 처리하기 위해 웹소켓을 많이 사용한다.


socket.io는 다양한 언어를 지원한다. 자바스크립트, 자바, swift, c++

유니티 게임 개발할 때, 사용하기 위해서는 어떻게 할까?



Posted by sungho88
,

1. 클라이언트와 서버


클라이언트와 서버

이전의 일반적인 사이트는 단순히 클라이언트의 요청(request)과 서버의 응답(response)로 작동했다.

주소창에 URL주소를 입력하거나, 웹사이트에 들어가 뉴스 링크를 클릭하는 등의 동작으로 Request가 발생하는데 

이 Request가 서버로 전달되면 서버는 Response를 보낸다. 즉, 서버는 클라이언트의 Request가 없으면 데이터를 전송하지 않는다. Request가 클라이언트쪽에서 먼저 시작되고, 그 request에 대한 response만 전달된다.

결론 : 서버는 클라이언트의 요청에만 응답하므로 단방향성을 갖는 연결 관계라고 할 수 있다.


웹 소켓

웹의 발전하면서, 클라이언트의 요청에 응답만 하는 단방향성이 아닌 양방향성의 웹사이트가 유행하게 되었다.

즉, 클라이언트와 서버의 연결이 항상 유지된다. 연결이 유지된 상태에서 서버 또는 클라이언트상의 이벤트가 발생하면 Event listener에 의해 서버에서 클라이언트로, 또는 클라이언트에서 서버로 데이터의 전달이 이뤄진다. 

이것이 웹 소켓(WebSocket)이다. 아쉬운점은 오래된 브라우저의 경우 지원을 하지 않아 동작하지 않는 문제가 있다.

결론 : 웹소켓은 웹 서버와 웹 브라우저 간의 양방향 통신을 위해 만들어진 프로토콜이다.


socket.io

socket.io는 자바스크립트 모듈로, 양방향 통신이 가능한 웹사이트를 구축하기 위해서 node.js와 함께 사용된다.

웹소켓과 유사하나, 브라우저 간 호환이나 이전 버전 호환을 고려하여 개발된 node.js 모듈이다.


2. socket.io사용법


1) 새 폴더 생성

2) 터미널(또는 CMD)을 열고 1) 폴더 경로로 이동한다.

3) npm init --> package.json이 생성된다.

4) npm install express socket.io --save

5) 에디터(vs code 또는 atom 등등..)으로 열고 1) 경로로 Open.. 한다.

6) index.html과 server.js 파일을 생성한다.


이렇게 하면 세팅이 완료되었다.


server.js부터 작성해보자


먼저, 서버를 생성하고 접속 가능한 코드는 간단하지만 한번 해보면

var app = require('express')();

var http = require('http').Server(app);


app.get('/', function(req, res){

  res.send('<h1>Hello world</h1>');

});


http.listen(3000, function(){

  console.log('server on & port : 3000');

});


이렇게만 작성한 뒤, 터미널에서 node index.js 를 입력하면 생성한 서버가 동작하게 된다.

정상적으로 실행이 되었다면 server on & port : 3000이 뜰 것이다.

그리고 


http://localhost:3000/


으로 접속을 해보면


Hello world가 크게 보인다. 이렇게하면 node.js로 서버를 동작시키는 입문 오브 입문 예제를 완성한 것이다.


이제 socket.io를 사용해서 실시간 채팅을 만들어보려고 한다.























 

Posted by sungho88
,


NetworkBehaviour은 위와 같이 UnityEngine.Networking 클래스를 사용하며 MonoBehaviour을 상속받는다.


따라서, 이것을 사용하기 위해서는 다음과 같이 스크립트 코드를 추가 & 변경해줘야 한다.


using UnityEngine.Networking;

public class Player : NetworkBehaviour {



유니티에서 네트워크 관련 변수 또는 함수 사용을 위해서는 NetworkBehaviour를 사용해야 하기 때문이다.


유니티 네트워크를 사용하여 멀티플레이어 게임을 개발하기 위해서 꼭 필요한 설정이다.


이거 안 하면, 네트워크 관련 코드 그냥 다 못 쓴다.


자세한 목록은 


공식 홈페이지


에서 확인하고, 적절히 사용하도록 하자.

Posted by sungho88
,

[RequireComponent(type())]


보통 GetComponent는 대부분 자기 자신의 컴포넌트 중 하나를 가져와 사용한다.


자신에 부착돼있는 컴포넌트를 가져와 사용하려면 기본적으로, 다음과 같이 호출한다.


Rigidbody rigid = GetComponent<Rigidbody>();


보통 이런 목적으로 사용할 때는 Awake나 Start에서 미리 선언한 뒤 사용한다. 


하지만 Rigidbody 컴포넌트의 존재를 보장하지 않는다. 


무슨말이냐면, 실수로 Rigidbody를 게임오브젝트에서 지웠다면 null이 되어 실행 시, 문제가 발생된다.


그래서 엄격히 컴포넌트의 존재를 보장하고 싶을 때 RequireComponent를 사용한다.


사용방법은 다음과 같다. 클래스보다 위에 쓴다는 점. 명심하자.



[RequireComponent(typeof(Rigidbody))]
[RequireComponent(typeof(Collider))]

public class Bullet : MonoBehaviour
{



제법 깔끔하기도 하고 자주 사용하는 방법이다.


이렇게 되면, 이 게임오브젝트는 반드시 Rigidbody와 Collider를 갖고 있어야 한다는 의미이다.


따라서, 위 두 컴포넌트는 삭제할 수 없다. Delete해봐라. 그럼 아래와 같은 창을 볼 수 있다.



Bullet 스크립트가 Box Collide를 요구하고 있기때문에, 이것은 삭제할 수 없게 되므로 에러 발생 확률이 적어진다.






이렇게 인스펙터와 관련된 기능이 많다.



Posted by sungho88
,

01)  유니티 네트워크(Unet) 사용 전 알아야할 개념

02) 유니티 네트워크(Unet) 사용 : NetworkManager

플레이어들 사이에 위치를 네트워크 동기화를 시켜주기 위한 방법에 대해 알아보자.


NetworkTransform가 붙은 오브젝트는 


자기 자신의 위치를 자신의 네트워크 너머에 있는 리모트 플레이어에게 위치를 전달할 수 있다.


즉, 위치를 자동으로 위치를 동기화시켜주는 역할을 한다.


하지만, 다른 클라이언트에게 직접적으로 동기화를 하는 것이 아니라 호스트(방장)을 거쳐가게 된다.


NetworkTransform 컴포넌트에서는 이러한 속성들이 있다.





Transform Sync Mode에는 어떤 것을 동기화할 것인지 설정하는 것으로 다음과 같은 속성이 있다.


테스트하는 것이므로 기본값으로 해보자.


다시 창 2개를 띄우고 접속한 뒤 움직여보자.


로컬 플레이어만 움직이며, 움직이는 모습이 두 창에서 동기화된다.


그런데 여기 문제점이 하나 있다.


Player root 객체는 움직이는데 만약, 계층 구조로 되어 있다면, 이 자식 젝체들은 회전하지 않는다.


그래서, 자동차 같은 경우 바퀴와 차량 본체로 이뤄져 있다면 이동방향과 상관없이 회전하지 않는다.


따라서 이를 위해서 NetworkTransformChild을 사용해야 한다.


주의할 점은 이것을 자식 게임오브젝트에 추가하는 것이 아니라 Player(부모 게임오브젝트)에 컴포넌트로 넣는다.


PlayerCar

ㄴ wheel

ㄴ body


라면 PlayerCar에 NetworkTransformChild를 두 개 추가해준 뒤, 


Target에 wheel과 body를 드래그 & 드롭하면 된다. 이렇게 하면 두 화면 모두 동기화되어 잘 움직인다.






Posted by sungho88
,

네트워크에서 식별을 하기 위해서는 NetworkIdentity가 필요하다.


NetworkManager 개념 설명


유니티 네트워크를 사용하기 위해서는 NetworkManager라는 컴포넌트를 사용하는데,

이 때 NetworkIdentity가 없는 게임 오브젝트는 네트워크 상에서 동기화를 할 수 없다.

왜 동기화를 거절할까?


NetworkIdentity를 붙였다는 것은 서버와 클라이언트 간 이미 약속된 게임오브젝트라는 의미이다.

따라서, NetworkIdentity가 붙지 않았다는 것은 나쁜 짓(버그,핵)을 할 가능성이 있으므로 동기화를 거절한다.


Local Player Authority


컴퓨터 앞에 앉아 있는 캐릭터인 로컬 플레이어의 권한을 갖고 있다.


이렇게 한 뒤, 실행을 해보면 


NetworkManagerHUD에 의해 좌측 상단에 접속할 수 있 버튼이 만들어져있다.


가장 위에 LAN Host(H)를 누르면 Player가 생성된다.


PC로 빌드를 해서 1개를 더 띄운다음에 2번째 것은 LAN Client로 접속한다.


서버 호스트는 이미 만들었으므로. 그러면 플레이어가 두 개가 생성되는 것을 볼 수 있다.


캐릭터를 상하좌우로 움직여보면 


두 캐릭터가 동시에 같은 입력을 받아 움직이는 것을 확인할 수 있다.


그 이유는 이것은 생성된 플레이어가 게임 상에서 로컬 플레이어인지 리모트 플레이어인지 구분을 하지 않는다.


따라서, 스크립트의 모든 내용을 공유하기 때문에 뒤늦게 생성된 게임오브젝트는 리모트 플레이어지만 


로컬 플레이어만 동작해야 할 코드를 같이 적용하게 되는 것이다.


따라서,  로컬 플레이어인지 체크한 뒤에 조작과 관련된 코드의 적용을 통제해야한다.


하지만, 먼저 MonoBehaviour가 아니라 NetworkBehaviour 를 상속해주어야 네트워크 관련 코드를 작성할 수 있다.




Update() 코드에서 조작을 하는 코드 위에 다음과 같이 작성해준다.


        if (!isLocalPlayer)

        {

            return;

        }

 

이렇게되면, 로컬 플레이어가 아니라면 조건문이 true가 되므로 return으로 빠져나가 나 자신만 움직일 수 있게 된다.

Posted by sungho88
,

유니티 네트워크를 사용하기 위해서 가장 중요한 세팅이 바로 NetworkManager를 추가하는 것이다.


NetworkManager는 로컬 플레이어와 리모트 플레이어의 전반적인 동기화를 담당하며 네트워크 통신을 관리해준다.


NetworkManager는 게임 상태 관리, 배치 관리, 씬 관리, 게임 매치 등등 전반적인 프로젝트 상태를 관리하게  된다. 


NetworkManagerHUD는 네트워크 개발 시 프로토타입으로 사용할 때 사용하는 객체로 기본 버튼이 생성된다.


NetworkManager에 플레이어를 등록을 하게 되면, 그 로컬 플레이어로써 게임 상에 탄생을 시킨다.


등록하는 위치는 아래 이미지에서와 같이, Spawn Info - Player Prefab이다.




NetworkManager 생성 방법


1. Create Empty로 빈 GameObject를 생성한다.

2. 된 GameObject의 이름을 NetworkManager로 재정의한다.

3. 해당 GameObject를 선택한 뒤, NetworkManager, NetworkManagerHUD 컴포넌트를 추가한다.

 

추가 방법

Add Component -> Network선택하면 확인할 수 있다.


다시 한번 정리


NetworkManager : 

- 게임의 전체적인 네트워크 상태를 관리 및 제어한다.


NetworkManagerHUD :

-실행시, 네트워크 상태를 조작할 수 있는 간단한 유저 인터페이스를 제공한다.

- 물론, 개발 단계에서 프로토타입 용도로 사용되는 것이며, 게임 출시전에는 제거한 뒤 커스텀해야한다.


Posted by sungho88
,

일단, 출처는 여기다.


4인 멀티 플레이어 게임은 총 몇 명이 존재할까?

당연히, 4명이라고 말하겠지만, 실제로는 16명의 플레이어가 존재한다.

이유는, 4인의 컴퓨터에 각각 4개의 캐릭터가 보이기 때문이다. 즉, 네 개의 게임 세상이 존재한다고 할 수 있다.


A에도 A, B, C, D 캐릭터가

B에도 A, B, C, D 캐릭터가

C에도 A, B, C, D 캐릭터가

D에도 A, B, C, D 캐릭터가 보인다.


따라서, 4*4 총 16개의 플레이어가 보이게 된다.

(물론 인간은 4명이겠지만...여기서 플레이어는 게임 상에서 나타나는 캐릭터를 뜻한다.)



(빨간색 - 로컬 플레이어 / 파란색 - 리모트 플레이어)



1) 로컬 플레이어란?


A라는 플레이어가 하고 있는 게임 상에서는 A캐릭터가 플레이어를 대표한다. 즉, A 세상에서는 A가 주인공이다.

이 대표하는 플레이어를 로컬 플레이어라 부른다. 또는 로컬 클라이언트라고돌 한다.

정리하면,


A 게임 상에서는 A가,  

B 게임 상에서는 B가,  

C 게임 상에서는 C가, 

D 게임 상에서는 D가

로컬 플레이어라고 할 수 있다.


2) 리모트 플레이어란?


반면에,

A 게임 상에서는 B, C ,D는 다른 로컬 플레이어가 아니라 다른 게임 세상에서 (원격으로) 건너온 플레이어이므로

원격 플레이어 또는 리모트 플레이어(Remote Player)라고 부른다. 또는 리모트 클라이언트라고돌 한다.

다른 

정리하면,


A 게임 상에서는 B,C,D 가,  

B 게임 상에서는 A,C,D 가,  

C 게임 상에서는 A,B,D 가, 

D 게임 상에서는 A,B,C 가

리모트 플레이어라고 할 수 있다.


그럼 어떻게 네 개의 게임 세상이 마치 하나의 게임처럼 동기화가 될까?

A의 입장에서는 A 게임 세상에서 A만 실존하는 존재이며, B,C,D 캐릭터는 그냥 보여지는 복제품일 뿐이다.

따라서, A만 컨트롤하고 이동하거나, 총을 쏘거나 하는 움직임이 발생하면 B,C,D에 있는 A에게 동기화를 적용한다.

이렇게 되면 B,C,D에 있는 A는 움직이게 된다. 하지만, 움직이는 주체는 A세상에 있는 A 캐릭터이다.


그렇다고 A가 복제되어 움직이는 것이 아니라 A,B,C,D 세상에 있는 A는 전혀 별개의 게임오브젝트이다.

단지 동기화를 통해 동작을 공유한다. 만약, 동기화가 안 될 경우 A는 각각 다른 행동을 취하게 된다.


서버 - 클라이언트 


서버-클라이언트를 게임에 적용하는 방식은 총 2가지가 있다.


1) 호스트(Host)

  

서버 자체도 한 명의 클라이언트로 참여하는 것이다. 흔히 방장이라고 부른다.

만약 A B C 세명이 멀티플레이어 게임을 한다고 할때 C가 호스트라고 가정하자. 


그러면 A,B,C의 네트워크 동작을 C가 관리하게 된다.

그래서, 위에서처럼 A가 직접 동기화를 시키는 것이 아니라 방장(Host)에게 수정을 요청한다.

그러면 Host가 동기화를 진행 한 뒤, 다른 클라이언트들에게 전파를 해서 동기화를 맞추게 된다.

즉, 어떤 처리를 동작하는 것처럼 보이지만 실제 동작하지 않고 호스트에게 부탁하고 호스트가 처리하게 된다.

결론 : 모든 중요한 처리는 Host가 대신 처리한 뒤, 다른 클라이언트들에게 뿌리는 방식이다.


장점 : 클라이언트가 나쁜 짓(핵,버그)을 할 수가 없다.

클라이언트를 믿지 않고 서버에서 처리하므로 아무리 클라이언트에서 나쁜 짓을 해도 서버에서 무시해버린다. 


단점 : 서버가 모든 일을 다 처리하므로, 동기화 및 통신의 지연시간이 발생할 수 밖에 없다. 

따라서, 총을 쏴도 안 맞는 일 발생. 왜냐하면 서버로 요청하는 순간 상대편이 이동하게 되면- 결국은 빗맞는다.

쏜 사람은 분명 쐈고 명중했다고 생각하는데 데미지를 입지않아 열받는 일이 발생한다.


클라이언트에서 아무리 뭘 열심히 했다고해도 서버에서 일어나지 않는일은 그냥 전혀 없던 일이 된다.


1) Dedicated

호스트 방식과 다른점은,


100% 자원을 서버 역할을 하기 위해 사용한다. 호스트와 다른점은 플레이어로 게임에 참가하지 않는다.

게임에 참여하지 않고 모든 ㅈㅏ원을 게임 서버로 사용하기 때문에 네트워크 품질이 좋아진다.






Posted by sungho88
,

DestroyImmediate를 사용하려고 했는데, 설명에는 다음과 같이 나온다.



Destroys the object obj immediately. You are strongly recommended to use Destroy instead.


즉,


Destroy 함수를 사용할 것을 강력하게 추천한다?


왜?


바로 없애면 좋은 것 아닌가?


하지만, 당장 오브젝트를 제거하는 것이 좋은 것이 아니라 나쁜 것이다.


이 블로그를 참조하자



Posted by sungho88
,