GeekCoders

[Unity] flatbuffers 연동 본문

Client/Unity

[Unity] flatbuffers 연동

령호 2016. 10. 8. 04:13

flatbuffers에 대한 자료는 https://google.github.io/flatbuffers/ 에서 참조 바라며 이 글은 짧게 설치, 사용만 설명한다.


https://github.com/google/flatbuffers/releases

- releases에서 바이너리를 다운로드


윈도우 기준으로

flatc.exe 가 생성된다.


https://google.github.io/flatbuffers/flatbuffers_guide_using_schema_compiler.html

스키마 컴파일러에 대한 옵션들을 확인. --csharp 명령어를 이용하면 cs파일을 얻을 수 있다.


https://google.github.io/flatbuffers/flatbuffers_guide_writing_schema.html

스키마 예제를 보고 원하는 idl 파일을 작성한다.



namespace syncnet;


struct vec3 {

  x: float;

  y: float;

  z: float;

}


table movement {

  dir: vec3;

  elapsed_time: float;

}


난 위와 같이 작성했다.

해당 패킷이 어떤 패킷인지 지정하며, 방향과 흐른 시간을 통신하려고 한다.





syncnet.fbs 파일명으로 저장했으며 편리하게 관리하기 위해 폴더 구조를 위와 같이 잡았다.


flatbuffers-master : 버전 관리를 위한 저장

node : node.js 서버이므로 이번 포스팅에선 무시

syncnet : flatc.exe에서 생성된 코드가 저장될 위치

unity : unity project

flatc.bat : flatc.exe를 편리하게 사용하기 위해 작성 (아래에서 설명)

flatc.exe : 위에서 다운로드 받은 release

syncnet.fbs : 위에서 작성한 idl 파일


bat파일 내용은 아래와 같다. (--js는 무시해도 됨. node.js에서 사용할 결과물)



bat파일을 실행시키면

위와 같은 경로에 결과물이 생성된다. (packet_type은 무시. 이 글과 무관하게 생성한 파일.)

cs 파일들을 유니티 Scripts 폴더에 넣는다. (위에 flatc.bat 파일의 경로를 수정하면 편하다.)



아래는 유니티에서 사용한 샘플 코드다.

node.js에서도 동작테스트를 하기위해 통신을 과정이 포함되어 있다. 단순 echo 만 하기에 메세지가 그대로 response 된다.

binary 통신이 정상적으로 동작하는 부분을 확인했다.


유니티만 본다면 encode 부분과 decode 부분만 확인하면 된다.





[ unity sample code ]



using UnityEngine;

using WebSocketSharp;

using System;

using System.IO;

using FlatBuffers;


public class Sample : MonoBehaviour

{

    public string m_domain;

    public string[] m_protocols;


    private WebSocket m_socket;


    void Start()

    {

        m_socket = new WebSocket(m_domain, m_protocols);

        m_socket.OnClose += OnClose;

        m_socket.OnError += OnError;

        m_socket.OnMessage += OnMessage;

        m_socket.Connect();

        Debug.Log("Connect");


        /// encode

        FlatBufferBuilder builder = new FlatBufferBuilder(1);

        syncnet.movement.Startmovement(builder);

        syncnet.movement.AddDir(builder, syncnet.vec3.Createvec3(builder, 1, 2, 3));

        syncnet.movement.AddElapsedTime(builder, 1f);

        var orc = syncnet.movement.Endmovement(builder);

        builder.Finish(orc.Value);


        /// send

        m_socket.Send(builder.SizedByteArray());

        

        /// local decode test

        ByteBuffer bb = new ByteBuffer(builder.SizedByteArray());

        syncnet.movement movement = syncnet.movement.GetRootAsmovement(bb);

    }


    void OnClose(object sender, CloseEventArgs e)

    {

        Debug.LogWarning("[OnClose] " + e.Reason);

    }


    void OnError(object sender, WebSocketSharp.ErrorEventArgs e)

    {

        Debug.LogError("[OnError] " + e.Message);

    }


    void OnMessage(object sender, MessageEventArgs e)

    {

        /// receive decode test

        Debug.Log("[OnMessage] " + e.Data);

        ByteBuffer bb = new ByteBuffer(e.RawData);

        syncnet.movement movement = syncnet.movement.GetRootAsmovement(bb);

    }


    // Update is called once per frame

    void Update()

    {


    }

}