UNet Tutorial (5) - Command와 Client Rpc

 

유니티 네트워크에서는 클라이언트와 서버 간에 액션을 수행하는 방법이 있다. 이를 원격 프로시저 호출(RPC)라고 하는데 유니티 네트워크 시스템에는 두 가지 타입의 RPC가 있다. 클라이언트에서 호출되어서 서버에서 수행되는 커맨드(Command)와 서버에서 호출되어서 클라이언트에서 수행되는 클라이언트 RPC(Client Rpc)가 그것이다.

 

아래의 다이어그램을 통해서 유니티 네트워크에서 원격 액션이 동작하는 방향을 확인할 수 있다.

 

 

 

 

 

커맨드(Command)

 

커맨드는 클라이언트의 플레이어 오브젝트에서 서버의 플레이어 오브젝트로 보내진다. 커맨드는 클라이언트 자신의 플레이어 오브젝트에서만 보낼 수 있으며 타 클라이언트가 소유한 플레이어 오브젝트를 통해서는 보낼 수 없다. 또한 일반적으로 플레이어 오브젝트가 아닌 네트워크 오브젝트에서도 커맨드를 보낼 수 없지만 5.2 버전부터 플레이어가 없는 오브젝트(클라이언트 권한 있음)에서도 커맨드를 보낼 수 있다. 이러한 오브젝트는 NetworkServer.SpawnWithClientAuthority를 통해 스폰되거나 NetworkIdentity.AssignClientAuthority를 통해 권한을 설정한 상태여야 한다. 이러한 오브젝트에서 전송한 커맨드는 오브젝트의 서버 인스턴스에서 실행되고, 클라이언트에서의 해당 플레이어 오브젝트에서 실행되지 않는다.

 

함수를 커맨드로 바꾸려면 [Command] 커스텀 속성을 사용하고 함수의 이름에 "Cmd" 접두사를 붙여주어야 한다.

 

using System.Collections;
using UnityEngine;
using UnityEngine.Networking;

public class Player : NetworkBehaviour
{
    int count = 0;

    [Command]
    public void CmdTestFunction(int i)
    {
        Debug.Log("Command Function Call. " + i);
    }

    void Update ()
    {
        if (Input.GetKeyDown(KeyCode.A))
        {
            CmdTestFunction(count++);

            Debug.Log("Input A. " + count);
        }
    }
}

 

 

 

서버와 클라이언트를 실행하고 클라이언트 측에서 'A'를 입력하면 커맨드가 호출되서 서버에서 수행되는 것을 확인할 수 있다.

 

 

 

 

클라이언트 Rpc(Client Rpc)

 

클라이언트 Rpc는 커맨드와 반대로 서버의 오브젝트에서 호출되어서 클라이언트의 오브젝트에서 수행된다. 서버의 경우에는 모든 권한을 가지고 있기 때문에 Network Identity를 포함해서 모든 서버의 오브젝트에서 이 호출을 보낼 수 있고 이것은 보안 상의 문제가 되지 않는다. 함수를 ClientRpc 호출로 만들기 위해서는 커맨드와 같이 [ClientRpc] 커스텀 속성을 함수 앞에 추가하고 함수 이름에 "Rpc"라는 접두사를 추가해야 한다.

 

using UnityEngine;
using UnityEngine.Networking;

public class Player : NetworkBehaviour
{
    int count = 0;

    [ClientRpc]
    public void RpcPlayerConnected()
    {
        Debug.Log("Client Rpc Call.");
    }

    [Command]
    public void CmdTestFunction(int i)
    {
        Debug.Log("Command Function Call. " + i);
    }

    void Update ()
    {
        if(Input.GetKeyDown(KeyCode.A))
        {
            CmdTestFunction(count++);
            Debug.Log("Input A. " + count);
        }
    }
}

 

using UnityEngine;
using UnityEngine.Networking;

public class CustomNetworkManager : NetworkManager
{
    public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId)
    {
        base.OnServerAddPlayer(conn, playerControllerId);

        Debug.Log("Add Player.");

        var players = FindObjectsOfType<Player>();
        foreach(var player in players)
        {
            player.RpcPlayerConnected();
        }
    }
}

 

위의 예제 코드는 서버에 새로운 클라이언트가 접속해서 새 플레이어 오브젝트가 생성되었을 때, 서버에 접속된 모든 클라이언트의 플레이어 오브젝트에 알려주는 역할을 하는 코드이다.

 

 

 

 

 

 

 

원격 액션에서의 매개변수

 

커맨드와 클라이언트 Rpc의 호출로 전달되는 매개변수는 직렬화되어 네트워크로 전송된다. 매개변수로 전달가능한 타입은 다음과 같다.

  • 기본 타입(byte, int, float, string, UInt64 등)
  • 기본 타입 배열
  • 허용 가능 타입을 포함하는 구조체
  • 빌트인 Unity 수학 타입(Vector3, Quaternion 등)
  • NetworkIdentity
  • NetworkInstanceId
  • NetworkHash128
  • NetworkIdentity 컴포넌트가 부착된 게임 오브젝트

원격 액션으로 전달되는 매개변수는 스크립트 인스턴스나 트랜스폼과 같이 게임 오브젝트의 하위 요소여서는 안된다. 직렬화되어 네트워크로 보내질 수 없는 타입도 매개변수가 될 수 없다.

 

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

UNet Tutorial (4) - Network Identity와 권한

 

지난 섹션에서 위치 동기화를 하면서, 게임 오브젝트에 Network Transform을 추가했을 때, Network Transform을 따라서 자동으로 추가된 컴포넌트를 기억하는가? 바로 Network Identity라는 컴포넌트다.

 

 

이름에서도 알 수 있듯이 이 컴포넌트는 오브젝트의 네트워크 ID를 관리하고 네트워킹 시스템에 알리는 역할을 한다. 즉, 이 오브젝트가 다른 서버나 클라이언트의 어느 오브젝트와 동기화되어야 하는지 알리는 역할을 한다

출처: http://wergia.tistory.com/99 [베르의 프로그래밍 노트]
이름에서도 알 수 있듯이 이 컴포넌트는 오브젝트의 네트워크 ID를 관리하고 네트워킹 시스템에 알리는 역할을 한다. 즉, 이 오브젝트가 다른 서버나 클라이언트의 어느 오브젝트와 동기화되어야 하는지 알리는 역할을 한다

출처: http://wergia.tistory.com/99 [베르의 프로그래밍 노트]
그것은 바로 Network Identity라는 컴포넌트인데, 이름에서도 알 수 있듯이 이 컴포넌트는 오브젝트의 네트워크 ID를 관리하고 네트워킹 시스템에 알리는 역할을 한다. 즉, 이 오브젝트가 다른 서버나 클라이언트의 어느 오브젝트와 동기화되어야 하는지 알리는 역할을 한다.

출처: http://wergia.tistory.com/99 [베르의 프로그래밍 노트]

지난 섹션에서도 언급했듯이 이 컴포넌트는 오브젝트의 네트워크 ID를 관리하고 네트워킹 시스템에 알리는 역할을 한다. 이 컴포넌트가 있어야 이 오브젝트가 다른 클라이언트의 어떤 오브젝트와 동기화 되어야 하는지 알 수 있는 것이다.

 

이번 섹션에서는 Inspector 뷰에서 표시되는 Server Only와 Local Player Authority라는 두 가지 옵션과 isServer, isClient, isLocalPlayer, hasAuthority라는 네 가지 프로퍼티에 대해서 알아볼 것이다.

 

우선은, Inspector 뷰에서 표시되는 두 가지 옵션에 대한 것이다.

 

Server Only - 여기에 체크된 오브젝트는 스폰될 때, 클라이언트에서는 스폰되지 않고 서버에서만 스폰된다.(네트워크 상에서의 스폰은 일반적인 Instantiate가 아닌 다른 방법을 통해서 스폰된다.)

Local Player Authority - 여기에 체크된 오브젝트는 이 오브젝트를 소유한 클라이언트가 오브젝트를 제어할 수 있다. 즉, 해당 클라이언트의 로컬 플레이어 오브젝트가 오브젝트에 대한 권한을 갖는다.

 

그 다음으로는, 네 가지 프로퍼티에 대한 것이다. 스크립트 상에서는 NetworkBehaviour를 상속받는 클래스의 멤버로 볼 수 있는데, 씬에서 스폰된 상태일 때는 Inspector 뷰 아래쪽에 Network Information으로 표시된다.

 

 

우선 설명할 것은 isClient와 isServer라는 프로퍼티이다. 이것은 간단히 말해서 지금의 네트워크가 서버이냐 아니면 클라이언트이냐를 알려주는 프로퍼티이다. 지난 섹션에서 본 Network Manager HUD를 이용하여 LAN Server Only(S)를 선택해서 서버를 열었다면 이 Network Identity의 isServer라는 프로퍼티는 true가 되는 것이고, LAN Client(C)를 선택해서 열린 서버에 접속했다면 isClient라는 프로퍼티가 true가 되는 것이다. 즉, 현재의 네트워크가 서버로서 다른 클라이언트의 접속을 받고 있는 것인지, 클라이언트로서 다른 서버에 접속하고 있는 것인지를 알 수 있다. 이것을 이용하면 서버에서만 동작하고 클라이언트에서는 동작하지 않는 방식의 코드를 작성할 수 있다.

 

일반적으로 이 isServer와 isClient는 둘 중에 하나만 true을 가지지만, LAN Host(H)를 선택하여 네트워크가 게임의 호스트가 되어서 다른 클라이언트들의 연결을 받게 되면 호스트 측에서는 이 두 프로퍼티 모두 true값을 가지게 되고, 호스트에 접속한 클라이언트들은 isClient 프로퍼티만 true값이 된다.

즉, isServer만 true라면 네트워크는 서버 역할만 맡고 있는 것이고, isClient만 true라면 클라이언트 역할만 맡고 있는 것이다. 그리고 isServer와 isClient가 모두 true라면 호스트로서 서버와 클라이언트의 역할을 동시에 하고 있는 것이다.

 

서버와 클라이언트가 분리된 방식은 일반적인 게임 서버나 데디케이트 서버에서 주로 사용되는 것이고, 하나의 클라이언트가 서버의 역할을 함께하는 호스트 방식은 주로 P2P 서버로 사용된다. 다만 P2P 서버 방식은 보안이나 해킹, 핵 등에 취약하다는 단점이 있다.

 

 

 

 

그 다음은 원래라면 HasAuthority 프로퍼티에 대한 설명을 할 차례지만 그전에 필요한 개념이 있기 때문에 isLocalPlayer에 대한 설명을 먼저 하겠다. 지난 섹션에서 클라이언트가 서버에 접속했을때, 이 클라이언트의 플레이어를 위한 하나의 프리팹을 Network Manager의 Player Prefab에 등록해준 것을 기억할 것이다. 이 플레이어 프리팹을 위해 사용되는 프로퍼티가 바로 isLocalPlayer이다.

 

 

 

플레이어 프리팹은 Auto Create Player의 설정을 통해서 하나의 클라이언트가 접속할 때마다, 자동으로 생성되거나, 클라이언트 측의 수동 플레이어 생성 요청을 받아 생성되는데, 이렇게 생성된 플레이어 오브젝트가 내 것인지를 알려주는 것이 바로 isLocalPlayer 프로퍼티이다. 클라이언트 측에서 작동할 코드를 만들때 그 클라이언트의 플레이어 오브젝트만 작동해야 하는 코드라면 isLocalPlayer 프로퍼티를 이용해 제한을 하는 것이 좋다.

 

 

 

 

그 다음은 HasAuthority 프로퍼티에 대한 내용을 알아보자. 이 프로퍼티는 이 네트워크 오브젝트의 권한을 가지고 있는가에 대한 프로퍼티이다.

 

 

 

위의 이미지에서는 Network Identity 컴포넌트의 Local Player Authority에 체크가 되어있는데, 이것이 체크되어 있지 않은 경우에는 그 오브젝트의 권한은 서버가 가지게 되고, 체크가 되어 있는 경우에는 위에서 설명한 isLocalPlayer가 true인 측에서 권한을 가지게 된다. isLocalPlayer가 아닌 쪽에도 이 권한을 줄 수 있지만, 그 방법에 대해서는 다른 섹션에서 설명하겠다.

 

이 hasAuthority 프로퍼티를 테스트하는 방법은 간단하다. 플레이어 프리팹에 Network Transform 컴포넌트를 추가하고 한 번은 Local Player Authority를 켜고, 또 한 번은 Local Player Authority를 끄고 움직여보자.

 

Local Player Authority를 켠 상태에서는 서버에서 아무리 플레이어 오브젝트를 움직여도 클라이언트 측으로 동기화 되지 않을 것이다. 하지만 그 플레이어 오브젝트를 isLocalPlayer로 가지는 클라이언트 측에서 플레이어 오브젝트를 움직이면 그 움직임이 서버와 다른 클라이언트에게 동기화 되는 것을 확인할 수 있다.

 

반대로 Local Player Authority를 끈 상태에서는 그 플레이어 오브젝트를 isLocalPlayer로 가지는 클라이언트는 물론 모든 클라이언트에서 움직여도 서버는 물론이고 다른 클라이언트로 동기화되지 않는다. 하지만 서버에서 플레이어 오브젝트를 움직이면 모든 클라이언트에 동기화된다.

 

네트워크 기능을 사용하는 커스텀 클래스를 만드는 경우, 위의 네 가지 프로퍼티들을 응용해서 각 상황에 따라 어떻게 동작하도록 할 것인지 정해줄 수 있다.

 

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

UNet Tutorial (3) - 기초적인 위치 동기화 구현

 

Network Manager와 Network Manager HUD를 이용한 간단한 서버와 클라이언트 만들기

 

이번 섹션에서 우리는 유니티에서 제공하는 NetworkManager와 NetworkManager HUD, NetworkTransform 등을 이용해서 간단한 위치 동기화 구현을 만들어볼 것이다.

 

 

우선의 위의 화면과 같이 오브젝트의 위치를 파악할 수 있게 카메라가 바닥인 평면을 바라보게 만들자.

 

 

그 다음에는 게임 오브젝트를 하나 만들어서 Network Manager와 Network Manager HUD를 컴포넌트를 넣어주자. 여기서 Network Manager는 게임 내에서 네트워크 통신을 처리해줄 것이고, Network Manager HUD는 유니티 네트워킹 테스트용 UI를 제공한다.

 

 

게임 오브젝트에 Network Manager HUD를 추가하고 게임을 실행하면 위의 이미지처럼 몇 개의 버튼이 화면에 보이게 되고 보이는 버튼을 누르는 것 만으로 간단하게 서버를 열거나 열어놓은 서버에 접속할 수 있게 된다. 이전 섹션에서 설명한 것처럼 LAN Host 버튼을 누르면 클라이언트가 서버의 역할을 겸하게 되는 서버가 열리고, LAN Server Only 버튼을 누르면, 클라이언트의 기능은 배제된 서버만 열리게 된다. 그리고 LAN Client 버튼을 누르면 열린 서버에 접속하게 된다.

 

 

 

 

Network Transform을 이용한 위치 동기화 구현

 

위에서 Network Manager를 이용해서 서버를 열고 접속하는 방법을 확인했으니 이번에는 Network Transform를 이용해서 위치를 동기화하는 방법에 대해서 알아보자. 우선은 게임 씬에 큐브 오브젝트를 하나 만든 후에 아래의 이미지처럼 Network Transform을 컴포넌트에 추가해주자.

 

 

오브젝트에 Network Transform 컴포넌트를 추가하면 하나의 컴포넌트가 자동으로 생성된 것을 볼 수 있다.

 

 

그것은 바로 Network Identity라는 컴포넌트인데, 이름에서도 알 수 있듯이 이 컴포넌트는 오브젝트의 네트워크 ID를 관리하고 네트워킹 시스템에 알리는 역할을 한다. 즉, 이 오브젝트가 다른 서버나 클라이언트의 어느 오브젝트와 동기화되어야 하는지 알리는 역할을 한다. 자세한 옵션에 대해서는 이후에 설명할 것이다.

 

 

 

Network Transform 컴포넌트를 추가했다면, Hierachy 뷰에 있는 오브젝트를 Project 뷰로 드래그 앤 드롭해서 프리팹으로 만들자. 프리팹으로 만든 이후에는 Hierachy 뷰에 있는 오브젝트는 삭제해도 된다.

 

 

그 다음에는 아까 전에 만든 Network Manager의 항목 중에 Player Prefab이라는 곳에 방금 만든 TransformSyncObject를 넣어준다. 이 Player Prefab은 한 명의 플레이어가 접속했을 때마다 생성되는 프리팹을 의미한다.

 

여기까지 작업했다면 프로젝트를 빌드하고 서버를 에디터에서 켜고 빌드된 프로젝트를 통해 클라이언트로 접속해보자.

 

 

 

접속하면 우리가 만들어서 플레이어 프리팹으로 등록한 오브젝트가 생겨나고 서버 측 에디터의 뷰에서 피벗을 잡고 움직이면 클라이언트 측 화면에서도 함께 움직이는 것을 볼 수 있다. 다만, 서버에서 움직임과는 다르게 클라이언트의 움직임은 약간 끊어져서 보이게 되는데 이것은 여러가지 방법으로 해결할 수 있다.

 

 

 

 

 

첫 번째 방법으로는, Network Transform 옵션에서 Network Send Rate를 높여주는 방법이 있다. 이것을 올려주면 초당 위치 동기화 횟수를 늘려서 통신량이 많아지는 대신에 좀 더 부드러운 움직임이 가능하게 만들어 준다. 다만 Inspector 뷰에서 바꾸는 방법은 초당 29회가 한계로 더 짧은 주기로 동기화하기를 바란다면, 두 번째 방법으로, 별도의 커스텀 네트워크 트랜스폼을 만드는 것이 좋다. 또한 부드러운 움직임을 원하지만 통신량이 많지 않기를 원한다면 커스텀 네트워크 트랜스폼을 구현하고 보간이나 Lerp, 추측항법 등을 가미해야 한다.

 

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

UNet Tutorial (2) - 간단한 개념

 

유니티에서 사용되는 개념들

 

1. 서버와 호스트

 

Unity 네트워크 시스템에서 게임은 한 개의 서버와 여러 개의 클라이언트를 가지게 된다. 이러한 방식은 클라이언트는 입력만 받고 서버에 전송해주고, 입력을 전송받은 서버가 모든 게임의 계산 처리를 한 이후 클라이언트에 전송해주는 데디케이트(Dedicate) 서버 방식에 사용된다. 전용 서버가 없는 P2P 방식의 경우에는 클라이언트 중 하나가 서버의 역할을 맡게 되며, 이 클라이언트는 “호스트”라고 부른다.

 

 

호스트는 동일 프로세스에서 서버이자 클라이언트이다. 호스트는 LocalClient라는 특수 클라이언트 유형을 사용하며, 다른 클라이언트는 RemoteClient를 사용한다. LocalClient는 동일 프로세스에 위치하고 있으므로 직접 함수 호출과 메시지 대기열을 통해 로컬 서버와 통신을 한다. RemoteClient는 서버와 일반적인 네트워크 연결을 통해 데이터를 주고 받는다.

네트워크 시스템의 목표 중 하나는 LocalClients와 RemoteClients 코드를 동일하게 하여 개발자가 되도록이면 한 종류의 클라이언트만 고려해도 되도록 하는 것이다.

 

 

 

 

2. 인스턴스화와 스폰

 

Unity에서는 GameObject.Instantiate() 함수를 통해서 새로운 Unity 게임 오브젝트를 생성한다. 하지만 네트워크 시스템의 경우 오브젝트는 NetworkServer를 통해서 “스폰”되어야만 네트워크에서 활성화가 된다. 이 과정은 서버에서만 할 수 있으며, 이를 통해 오브젝트가 연결된 클라이언트에서도 생성되도록 할 수 있다. 오브젝트가 스폰된 이후에는 스폰 시스템이 배포된 오브젝트의 생명주기 관리와 상태 동기화 원칙을 사용한다.

 

 

3. 플레이어, 로컬 플레이어, 권한

 

네트워크 시스템에서 플레이어 오브젝트는 특수하게 취급된다. 게임 플레이어 각각에 연관된 플레이어 오브젝트에 커맨드가 보내지게 된다. 자신이 아닌 다른 사람의 플레이어 오브젝트에는 커맨드를 호출할 수 없다. 플레이어가 추가되고 관계가 연결된 경우, 해당 플레이어 오브젝트는 플레이어 클라이언트의 “로컬 플레이어” 오브젝트가 된다. isLocalPlayer 프로퍼티는 true로 설정되며, 클라이언트 오브젝트에 호출된 OnStartLocalPlayer() 콜백이 발생한다. 아래 다이어그램은 두 클라이언트와 해당 로컬 플레이어의 예제를 보여준다.

 

 

오직 “본인” 플레이어 오브젝트에만 isLocalPlayer 플래그가 설정된다. 이 플래그를 통해 입력 프로세싱 필터링, 카메라 위치 조작, 또는 특정 플레이어에 대해서만 변경되어야 하는 클라이언트측 동작을 처리할 수 있다.

플레이어 오브젝트는 isLocalPlayer와 더불어 “로컬 권한”을 가질 수도 있다. 이는 소유자 클라이언트의 플레이어 오브젝트가 해당 오브젝트에 대한 권한이 있다는 의미입니다. 권한은 대부분 움직임을 제어하는 데 주로 활용되지만, 다른 용도로도 사용할 수 있습니다. NetworkTransform 컴포넌트는 이 권한을 이해하며 설정된 경우 클라이언트에서의 움직임을 보냅니다. NetworkIdentity는 LocalPlayerAuthority를 설정할 수 있는 체크박스가 있다.

적 오브젝트와 같이 비플레이어 오브젝트는 연관 클라이언트가 없으므로, 서버가 권한을 가지게 된다.

 

 

NetworkBehaviour에 있는 “hasAuthority” 프로퍼티를 사용하여 오브젝트에 권한이 있는지 파악할 수 있다. 따라서 비플레이어 오브젝트는 서버에 권한이 있고, 플레이어 오브젝트 중 localPlayerAuthority가 설정된 것은 각 소유자 클라이언트에 권한이 있다.

 

 

 

 

4. 비플레이어 오브젝트의 클라이언트 권한

 

Unity 5.2 릴리스 버전부터 클라이언트는 비플레이어 오브젝트에 권한을 가질 수 있으며, 두 가지 방법이 있다. 하나는 NetworkServer.SpawnWithClientAuthority로 오브젝트를 스폰한 후 클라이언트 네트워크 연결에 전달하여 소유권을 이전하는 방법이고 다른 하나는 NetworkIdentity.AssignClientAuthority를 클라이언트 네트워크 연결과 사용하여 소유권을 이전하는 방법이다.

클라이언트에 권한을 할당하면 오브젝트 NetworkBehaviours에 OnStartAuthority()가 호출되며, hasAuthority 프로퍼티는 true가 된다. 다른 클라이언트의 hasAuthority 프로퍼티는 계속 false가 된다. 클라이언트 권한이 있는 비플레이어 오브젝트는 플레이어와 같이 커맨드를 보낼 수 있다. 이 커맨드는 오브젝트 서버 인스턴스에서 실행되지, 연결에 관련된 플레이어 서버에서 실행되지 않는다.

클라이언트 권한이 있는 비플레이어 오브젝트는 NetworkIdentity에서 LocalPlayerAuthority가 체크되어 있어야 한다.

아래는 오브젝트를 스폰하고 스폰한 플레이어 클라이언트의 권한을 할당하는 예시이다.

 

[Command]
void CmdSpawn()
{
    var go = (GameObject)Instantiate(otherPrefab, transform.position + new Vector3(0,1,0), Quaternion.identity);
    NetworkServer.SpawnWithClientAuthority(go, connectionToClient);
}

 

 

 

 

5. 네트워크 컨텍스트 프로퍼티

 

NetworkBehaviour 클래스에는 언제든 네트워크된 오브젝트의 네트워크 컨텍스트가 무엇인지 알 수 있게 하는 프로퍼티가 있다.

  • isServer - 오브젝트가 스폰되었고 서버나 호스트에 있는 경우 true다.
  • isClient - 오브젝트가 서버에 의해 생성되었고 클라이언트에 있는 경우 true다.
  • isLocalPlayer - 오브젝트가 해당 클라이언트 플레이어 오브젝트인 경우 true다.
  • hasAuthority - 로컬 프로세스가 이 오브젝트를 소유하는 경우 true다.

이들 프로퍼티는 에디터 인스펙터 창의 오브젝트 미리보기 창을 통해 확인할 수 있다.

 

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

 

UNet Tutorial (1) - Overview

 

네트워크 게임을 제작할 때, 클라이언트의 네트워크를 구현하는 방법은 여러가지가 있다. 대표적인 방법으로는 포톤 클라우드가 제공하는 Photon Unity Networking과 넷텐션의 ProudNet으로 구현하는 방법등이 있다. 이번 포스팅에서는 이런 외부에서 제공하는 방식이 아니라 유니티가 제공하는 Unity Networking을 이용하는 방법에 대해서 알아보게될 것이다.

 

사실 이전까지는 유니티에서 제공하는 Networking은 잦은 버그와 잘알려지지 않은 점, 사용 예가 많지 않은 점등을 이유로 잘 사용되지 않은 편인데, 계속된 버전업과 지난 2017년 12월 04일에 유니티 테크놀러지 측에서 게임 서버 호스팅 업체를 인수한 것으로 충분히 적용해 볼만 하다고 여겨져서 튜토리얼을 작성하게 되었다.

 

 

 

 

UNet의 구조

 

 

유니티의 네트워킹 API는 위의 이미지와 같은 레이어로 이루어져 있는데 두 가지 방식으로 사용할 수 있다.

 

1. 유니티에서 제공하는 "High-Level" 스크립팅 API - HLAPI라고 부르며, 이것을 이용하여 네트워킹 기능을 구현할 경우 Low-Level의 세부 사항에 대해 신경쓰지 않고도 멀티 유저 게임에 일반적으로 필요한 대부분의 요구 사항을 만족시킬 수 있는 커맨드에 접근할 수 있다.

2. Low-Level의 전송 레이어(Transport Layer) API - 네트워크 인프라 또는 커스텀화된 고급 멀티 플레이어 기능을 구현하고자 할 경우, 이 API를 통해 저수준에서 스스로의 네트워킹 시스템을 빌드할 수 있으며, 이는 게임 네트워킹에 있어서 구체적이거나 고급 요구 사항이 있는 경우 유용하다.

 

위의 두 가지 API를 통해서 개발자는 저수준에서 고수준까지 원하는 방법으로 게임의 네트워크를 구현할 수 있게 된다.

 

 

 

Unity가 제공하는 서비스

 

이러한 API 이 외에 유니티는 Unity Multiplayer라는 서비스를 통해서 다음과 같은 기능들을

  • 매치메이킹 서비스
  • 매치를 생성하고 홍보.
  • 참여 가능한 매치 리스트를 제공하고 매치에 참여.
  • 릴레이 서버
  • 전용 서버 없이 인터넷을 통한 게임플레이.
  • 매치 참여자에게 메시지 전송.

단, 이 Multiplayer 서비스는 유료 서비스로 이용하게 될 경우 별도의 비용을 지불해야 한다.

 

 

다음 섹션에서는 UNet의 몇몇 개념과 간단한 구현 튜토리얼을 알아보게 될 것이다.

 

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

에셋 번들 중 원하는 번들만 빌드하기

 

유니티 엔진을 이용한 게임 개발 과정에서 패치 시스템 등을 위한 도구로서 에셋 번들이 자주 사용되는데 번들의 효율적인 관리와 사용을 위해서 모든 에셋들을 한 번들에 묶지 않고, 필요한 분류에 따라서 여러 번들에 나누어서 묶어서 사용하게 된다. 예를 들자면 캐릭터에 사용되는 리소스와 에셋들만 모아서 "character"라는 이름의 번들로 묶거나, UI에 사용되는 이미지들만 모아서 "ui_texture"라는 이름의 번들로 묶는 것이다.

 

이렇게 분류별로 나누어둔 번들은 다른 포스트에서 언급(http://wergia.tistory.com/29)했듯이 다음과 같이 BuildAssetBundles() 라는 함수를 통해서 빌드할 수 있다. 다음은 그 예시이다.

 

BuildPipeline.BuildAssetBundles(Application.dataPath + "/AssetBundles", buildAssetBundleOption, buildTarget);

 

위의 예시를 통해서 묶어둔 에셋들을 번들로 빌드할 수 있는데, 이 코드를 사용할 경우, 당신이 지정한 모든 번들들을 한꺼번에 빌드한다. 이것은 에셋 번들을 테스트로 빌드하거나, 적은 수의 혹은 작은 용량의 번들을 빌드할 때는 인식하지 못했던 문제를 발생시킨다. 이 문제는 개발자가 게임을 개발하는데 투자하는 가장 중요한 자원을 소모시킨다. 그 자원은 바로 "시간"이다.

 

 

 

작은 용량의 에셋을 번들로 빌드할 때는 고작 몇 초의 시간이 걸릴 뿐이지만, 수 GB의 에셋들을 번들로 빌드할 때는 5-10분, 혹은 그보다 많은 시간을 소모하게 된다. 만약에 가장 작은 크기의 번들에 들어가는 에셋을 수정했는데 새로이 번들을 빌드하기 위해 모든 에셋번들을 빌드해야 한다면 얼마나 많은 시간을 무의미하게 소모하게 될 것인가? 필요한 번들만을 빌드했다면 고작 수십 초에서 2-3분의 시간만을 소모했을 작업을 수 분, 수십 분을 소모해야 한다면 이 얼마나 불합리한 일인가?

 

그렇기 때문에, 필요한 번들만을 빌드하는 방법을 알아두어야만 한다.

 

AssetBundleManifest BuildPipeline.BuildAssetBundles(

string outputpath, // 빌드된 에셋 번들이 생성될 경로

AssetBundleBuild[] builds, // 빌드할 에셋 번들들의 정보

BuildAssetBundleOption assetBundleOptions, // 에셋 번들 빌드 옵션

BuildTarget targetPlatform // 에셋 번들의 타겟 플랫폼

);

 

필요한 번들만을 빌드하는 방법으로 유니티에서는 위의 코드와 같은 BuildAssetBundles() 함수의 오버로드를 제공한다. 원래 에셋 번들 빌드에 사용하던 함수에서 AssetBundleBuild라는 구조체 형식의 매개변수가 추가되었는데, 빌드하고자 하는 번들의 정보를 담는 구조체이다. 원하는 에셋 번들을 빌드하기 위해 제공해야할 정보들은 다음과 같다.

 

public struct AssetBundleBuild
{
    public string assetBundleName;   // 빌드할 에셋 번들의 이름
    public string assetBundleVariant; // 빌드할 에셋 번들의 Variant
    public string[] assetNames;        // 에셋 번들에 포함될 에셋들의 경로와 이름
}

 

빌드하고자 하는 에셋 번들에 대한 AssetBundleBuild 구조체 혹은 구조체 배열을 만든 뒤, 빌드할 에셋 번들의 이름, Variant(variant가 없다면 넣지 않아도 된다.), 에셋번드레 포함될 에셋들의 경로와 이름을 넣어주고 BuildAssetBundles() 함수의 2번째 매개변수로 전달하고 함수를 실행하게 되면 한 번에 모든 에셋 번들들을 빌드할 필요없이 원하는 에셋 번들만을 빌드할 수 있게 된다.

 

 

 

 

빌드하고자 하는 에셋 번들에 포함될 에셋들 찾기

 

원하는 에셋 번들만을 빌드하고자 할 때는 위에서 봤듯이 AssetBundleBuild 구조체를 만들어 필요한 정보들을 채워넣어 주어야 하는데, 그 중에서 에셋 번들에 포함될 에셋들의 경로와 이름인 assetNames의 경우에는 수동으로 입력하는 것은 매우 불편할 뿐더러 프로젝트가 커지면 커질 수록 관리하기도 힘들고 어떤 에셋이 어느 번들에 포함되기로 되어있는지 기억하기도 힘들어질 것이다.

 

이런 경우를 위해서 유니티에서 제공하는 함수가 있는데 바로 다음의 함수이다.

 

string[] AssetDatabase.GetAssetPathsFromAssetBundle(

string assetBundleName  // 찾고자 하는 에셋들이 포함된 에셋 번들 이름

);

 

위의 함수를 사용하면 유니티 에디터의 Inspector 창에서 해당 번들 이름으로 지정해둔 모든 에셋들의 경로와 이름을 string의 배열 형태로 반환한다. 이것을 AssetBundleBuild의 assetNames에 넣어주면 간편하게 번들에 포함될 에셋들의 정보를 AssetBundleBuild 구조체에 넣을 수 있다.

 

빌드하고자 하는 에셋 번들만을 빌드하는 간단한 예제 함수의 전체는 다음과 같다.

 

public void BuildNeedAssetBundle(string bundleName)
{
    if (!Directory.Exists(Application.dataPath + "/AssetBundles"))
    {
        Directory.CreateDirectory(Application.dataPath + "/AssetBundles");
    }

    AssetBundleBuild[] buildBundles = new AssetBundleBuild[1];

    buildBundles[0].assetBundleName = bundleName;
    buildBundles[0].assetNames = AssetDatabase.GetAssetPathsFromAssetBundle(bundleName);

    BuildPipeline.BuildAssetBundles(Application.dataPath + "/AssetBundles", buildBundles, buildAssetBundleOption, buildTarget);
}

 

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

유니티에서 Amazon S3에 업로드할 때 PostObject를 사용하면 파일 업로드에 실패하는 문제

 

 

AWS에서는 유니티에서 AWS 기능들을 사용할 수 있게 해주는 SDK를 제공한다. (AWS에서 제공되는 유니티용 AWS SDK) 해당 SDK에는 AWS의 기능을 유니티에서 사용하는 방법에 대한 샘플 코드 역시 포함되어 있는데, 그 중에서 Amazon S3의 기능을 알려주는 샘플 코드에 문제가 있다.

 

해당 샘플 코드에서는 S3에 등록된 버킷의 목록을 가져오는 법, 버킷에 업로드된 오브젝트의 목록을 가져오는 법, 버킷에 있는 오브젝트를 내려받는 법, 버킷에 새로운 오브젝트를 업로드하는 법, 버킷에 있는 오브젝트를 삭제하는 법에 대한 코드들이 포함되어 있다. 예제를 실행시켜보면 대부분 잘 작동하지만, 버킷에 새로운 오브젝트를 업로드하는 코드만 유독 정상적으로 작동하지 않는다.

 

다음은 문제의 작동하지 않는 코드이다.

 

/// <summary>
/// Post Object to S3 Bucket.
/// </summary>
public void PostObject()
{
    ResultText.text = "Retrieving the file";

    string fileName = SampleFileName;
            
    var stream = new FileStream(Application.dataPath + "/" + fileName, FileMode.Open, FileAccess.Read, FileShare.Read);

    ResultText.text += "\nCreating request object";
    var request = new PostObjectRequest()
    {
        Bucket = S3BucketName,
        Key = fileName,
        InputStream = stream,
        CannedACL = S3CannedACL.Private
    };

    ResultText.text += "\nMaking HTTP post call";

    Client.PostObjectAsync(request, (responseObj) =>
    {
        if (responseObj.Exception == null)
        {
            ResultText.text += string.Format("\nobject {0} posted to bucket {1}", responseObj.Request.Key, responseObj.Request.Bucket);
        }
        else
        {
            ResultText.text += "\nException while posting the result object";
            ResultText.text += string.Format("\n receieved error {0}", responseObj.Response.HttpStatusCode.ToString());
        }
    });
}

 

해당 코드를 실행하면 파일이 Amazon S3에 업로드되어야 하지만 정확한 실패 원인이 나오지 않고 업로드에 실패한다. 아마존 측에서 제공한 API에 문제가 있을 것으로 추정된다. 유니티에서 Amazon S3에 파일을 업로드하기 위해서는 코드를 다음과 같이 변경하여야 한다.

 

 

/// <summary>
/// Put Object to S3 Bucket.
/// </summary>
public void PutObject()
{
    AWSConfigs.HttpClient = AWSConfigs.HttpClientOption.UnityWebRequest;

    ResultText.text = "Retrieving the file";

    string fileName = GetFileHelper();

    var stream = new FileStream(Application.persistentDataPath + Path.DirectorySeparatorChar + fileName, FileMode.Open, FileAccess.Read, FileShare.Read);

    ResultText.text += "\nCreating request object";
    var request = new PutObjectRequest()
    {
        BucketName = S3BucketName,
        Key = fileName,
        InputStream = stream,
        CannedACL = S3CannedACL.Private
    };

    ResultText.text += "\nMaking HTTP post call";
    Client.PutObjectAsync(request, (responseObj) =>
    {
        if (responseObj.Exception == null)
        {
            ResultText.text += string.Format("\nobject {0} puted to bucket {1}", responseObj.Request.Key, responseObj.Request.BucketName);
        }
        else
        {
            ResultText.text += "\nException while puting the result object";
            ResultText.text += string.Format("\n receieved error {0}", responseObj.Response.HttpStatusCode.ToString());
        }
    });
}

 

위의 코드와 같이 PostObject 대신에 PutObject를 사용해야 Amazon S3에 파일 업로드가 정상적으로 되는 것을 확인할 수 있다.

 


 

참고

 

(AWS) 유니티에서 S3에 업로드하기

사흘 간 헤매던 원인을 해결해서 매우 기분이 좋다. 결론적으로 말하면 AWS에서 제공하는 Unity SDK...

blog.naver.com

 

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

안드로이드 버전의 빌드에서 디바이스의 로컬 저장소에 파일을 저장하는 법

 

유니티에서 게임을 만들 때, 네트워크로 받아온 파일을 로컬에 저장해야 하는 일이 많다. 특히 게임의 패치 시스템(Patch System)을 만들어야 하는 경우라면 100% 필요한 일이다. 윈도우 버전의 빌드에서는 적당히 원하는 경로에 파일을 저장할 수 있지만, 안드로이드 버전의 빌드에서는 경로마다 읽기/쓰기의 권한이 다르고 제한이 있다.

 

안드로이드의 데이터 경로와 읽기/쓰기 권한은 다음과 같다.

 

[안드로이드 External]
Application.persistentDataPath : /mnt/sdcard/Android/data/com.YourProductName.YourCompanyName/files [파일 읽기/쓰기 가능]
Application.dataPath : /data/app/번들이름-번호.apk
Application.streamingAssetsPath : jar:file:///data/app/번들이름.apk!/assets [파일이 아닌 WWW로 읽기 가능]

[안드로이드 Internal]
Application.persistentDataPath : /Android/data/com.YourProductName.YourCompanyName/files [파일 읽기/ 쓰기 가능]
Application.dataPath : /data/app/번들이름-번호.apk
Application.streamingAssetsPath : jar:file:///data/app/번들이름.apk!/assets [파일이 아닌 WWW로 읽기 가능]

 

위에 적힌 것처럼 네트워크에서 받아온 파일을 로컬에 저장하기 위해서는 읽기/쓰기가 모두 가능한 Application.persistentDataPath의 경로를 사용해야 한다.

 

위의 경로에 원하는 폴더를 만들고자 할 때는 다음의 코드를 참조하면 된다.

 

if (!Directory.Exists(Application.persistentDataPath + "/생성할 폴더 이름"))
{
    Directory.CreateDirectory(Application.persistentDataPath + "/생성할 폴더 이름");
}

 

위의 경로에 원하는 파일을 쓰고자 할 때는 다음의 코드를 참조하면 된다.

 

FileStream fs = new FileStream(Application.persistentDataPath + "/" + "TestFileName.txt", FileMode.Create, FileAccess.Write);
byte[] data = new byte[writeDataSize];
fs.Write(data, 0, (int)writeDataSize);
fs.Close();

 

이 섹션에서 소개한 내용은 제일 처음에 설명했듯이 주로 게임 패치 시스템에 많이 사용되는데, 유니티에서는 게임 패치에 에셋 번들을 많이 사용하는 편이다. 빌드된 에셋 번들은 manifest 파일을 제외하면 공통적으로 나오는 AssetBundles 파일을 비롯해서 주로 확장자 없이 지정한 번들 이름만 적힌 파일이 나오는데, 이렇게 확장자가 없는 에셋 번들 파일을 그대로 사용할 때는, 각 에셋 번들의 이름과 같은 폴더를 생성하려고 하면 폴더 생성에 실패하게 된다. 그렇기 때문에, 에셋 번들의 이름과 같은 이름의 폴더의 생성은 피하거나 에셋 번들 파일의 끝에 ".unity3d"같은 확장자를 붙여주는 것이 좋다.

 


참고 사이트

 

# Uniyt3D 게임엔진 예약된 폴더이름 및 데이터 경로 정리.

[윈도우 에디터]Application.persistentDataPath : 사용자디렉토리/AppData/LocalLow/회사이름/프로덕트이름 파일 읽기 쓰기 가능Application.dataPath : 프로젝트디렉토리/AssetsApplication.streamingAssetsPath : 프로젝트디

egloos.zum.com

 

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

+ Recent posts