반응형

Unity 에서 Redis 서버를 사용해보자

 

Unity 버전 2019.4.15f1

 

NuGet의 StackExchange.Redis를 사용했다.

 


 설치&세팅

 

visual studio의 NuGet에서 Plugin을 다운받고 사용하면 사용이 안된다.

사용이 안되는 이유는 두가지로 

 

1. 유니티 내부에 있어야한다.

2. 유니티에서 호완하는 버전이 아니다

 

 

 

 

1. 누겟 페키지를 다운받았으면 다운받은 파일에 들어가서 

 

 

 

 

 

dll 파일과 xml 파일을 

 

unity Assets 파일에 Plugin 파일을 만들어서 넣어준다

 

 

 

 

 

 

 

 

 

 

 

2. 유니티 2019버전에서는 Redis 2버전대가 호환이 안된다

그럼으로 1.5버전을 다운받아서 넣어주면 된다.

 

 


사용법

 

 

그뒤로 unity 내부에서 사용하는 방법은 매우간단하다.

    private ConnectionMultiplexer redisConnection;
    private IDatabase DB;
    private ISubscriber sub;

3가지를 선언해 준다.

 

 첫줄은 StackExchange.Redis의 메인 객체다

 두번째 줄은 DB 데이터 를 주고받을 객체다.

 마지막줄 sub역시 데이터를 전달하기위해 있는객체다.

 

백문이 불여일견 코드로 보겠다.

Init Code

 public bool Init(string host, int port)
    {

        this.redisConnection = ConnectionMultiplexer.Connect(host + ":" + port);
        if (redisConnection.IsConnected)
        {
            this.DB = this.redisConnection.GetDatabase();
            sub = redisConnection.GetSubscriber();
            return true;
        }

        return false;
    }

    public bool Init(string host, int port, Events LoopEvents)
    {

        T = new Thread(new ThreadStart(LoopEvents));
        
        try
        {
            ConfigurationOptions option = new ConfigurationOptions
            {
                ConnectTimeout = 1000,
                AbortOnConnectFail = false,
                EndPoints = { $"{host}:{port}" },
            };
            redisConnection = ConnectionMultiplexer.Connect(option);
        }
        catch (Exception e)
        {
            Debug.Log(e);
        }

        if (redisConnection.IsConnected)
        {
            this.DB = this.redisConnection.GetDatabase();
            sub = redisConnection.GetSubscriber();
            T.Start();

            return true;
        }

        return false;
    }

 

위 코드의

        this.redisConnection = ConnectionMultiplexer.Connect(host + ":" + port);  줄에서 알수있듯

       "ip주소:포트넘버: 로 이루어져 있다. 

 

로컬로 테스트 할때는 아래 코드처럼 "localhost" 를 넣어서 사용하면된다.

this.redisConnection = ConnectionMultiplexer.Connect("localhost")

 

 그냥 주소로 connect를 시도 해도 좋지만

 

   ConfigurationOptions option = new ConfigurationOptions
            {
                ConnectTimeout = 1000,
                AbortOnConnectFail = false,
                EndPoints = { $"{host}:{port}" },
            };
            redisConnection = ConnectionMultiplexer.Connect(option);

이 부분처럼 ConfigurationOptions 를 사용하여 전달해도 좋다.

 그러면 구성 옵션을 세팅을 한번에 해줄수도 있다.

   

 

      this.redisConnection = ConnectionMultiplexer.Connect(host + ":" + port);

           ㄴ주소로 연결


        if (redisConnection.IsConnected) //연결 완료되었는가
        { 

       //연결 완료후 데이터들을 받는다.

            this.DB = this.redisConnection.GetDatabase();

            sub = redisConnection.GetSubscriber();

        }

 

 

 

 

이제 정상적으로 넘어간다면 다 끝났다. 

데이터를 주고받는 방법은 간단하다.

 

 

 

 

 

 

 

 

 

 

 

아까 선언해주었던 DB 객체의 내부에 전부 들어있다. 

아래 코드처럼 자신의 프로젝트에서 사용하기 편하게 만들어주면 끝이다.

 

   public string GetString(string key)
    {
        return this.DB.StringGet(key);
    }
    public bool SetString(string key, string val)
    {
        return this.DB.StringSet(key, val);
    }
    public RedisValue GetHASH(string key, string val)
    {
        return this.DB.HashGet(key, val);
    }
    public bool GetHASH_Bool(string key, string val)
    {
        var data = this.DB.HashGet(key, val);
        if (data.ToString()[0] == 't' || data.ToString()[0] == 'T')
        {
            return true;
        }
        return false;
    }
    public int GetHASH_Int(string key, string val)
    {
        var data = this.DB.HashGet(key, val);
        int Idata = 0;
        if (data.HasValue == true)
        {
            int DataSize = data.ToString().Length - 1;
            int sizenum = (int)Math.Pow(10, DataSize);
            foreach (var d in data.ToString())
            {
                if ('0' <= d && d <= '9')
                {
                    Idata += ((d - 48) * sizenum);
                    sizenum /= 10;
                }
                else
                {
                    return -int.MaxValue;
                }
            }
        }
        return Idata;
    }
    public double GetHASH_Double(string key, string val)
    {
        var data = this.DB.HashGet(key, val);
        if (data.HasValue == true)
        {
            double Idata = Double.Parse(data);
            return Idata;
        }
        return -Double.MaxValue;
    }
    public void SetHASH(string key, HashEntry[] val)
    {
        this.DB.HashSet(key, val);
    }
    public void DestroyHash(string key, RedisValue field)
    {
        this.DB.HashDelete(key, field);
    }

또한 Redis 서버에 메시지를 따로보내는 방법이 있는데 

그게 아까 보여주었던 sub 로 가능하다

    public void Meseage(string Channel, string Meseage)
    {
        sub.Publish(Channel, Meseage);
    }

특정 채널에 메시지를 보낼수있다.

또한 채널의 메시지를 구독하여 올라올때마다 확인받을수 있다.

 

    public void Setsubscrib(string _channel, CallBack_Funtc _CallBack_Funtc)
    {
        if (redisConnection.IsConnected)
        {
            sub.Subscribe(_channel, (channel, message) =>
            {
                try
                {
                    _CallBack_Funtc?.Invoke(channel+" "+message);
                    Debug.Log(message);
                }
                catch
                {

                }
            });
        }
    }

 

 

 

 

 

 

위에서 만들었던 클래스 사용

  private string Key;
    public string RedisIP_Num;
    public int PortNum;
    public bool GetDataLoop;
    public int ThreadDelay;

    private void Start()
    {
     // 따로 XMl로 받아오는 데이터들
        Key = Datas.data.DataKey;
        RedisIP_Num = Datas.data.RedisIP_Num;
        PortNum = Datas.data.PortNum;
        GetDataLoop = Datas.data.GetDataLoop;
        ThreadDelay = Datas.data.ThreadDelay;

        redis = new Redis();
        if (redis.Init(RedisIP_Num, PortNum, delegate
         {
             while (GetDataLoop)
             {
                 GEtD(); // redis.GetHASH_Bool(Key, "KeyData") 데이터들을 받아오는 함수
                 Thread.Sleep(ThreadDelay);

             }
         }))
        {
            Debug.Log("connect");
        }
        else
        {
            Debug.Log("Non_connect");
        }

 GEtD()함수 내부 코드는 이렇게 데이터를 받는다.

 

또한 Init 의 델리게이트에 데이터를 받아오는 함수와 스레드.Sleep(변수)

를 이용하여 연결이 완료되었을때 데이터를 주기적으로 받아오게 만들었다.

 

 

 

전체코드

더보기

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using StackExchange.Redis;
using System.Threading;
using System;
using System.Threading.Tasks;

namespace TStory
{
    static public class Global
    {
        public static bool Dnet_Connection;
        public static bool Dnet_readwrite;
        public static bool Dnet_error;
        public static double server_cache_alive;
        public static int client_connection_count;

    }
}

public class RDS : MonoBehaviour
{
    private Redis redis;
    public RedisValue redisValue;

    private string Key;
    public string RedisIP_Num;
    public int PortNum;
    public bool GetDataLoop;
    public int ThreadDelay;

    private void Start()
    {
        Key = Datas.data.DataKey;
        RedisIP_Num = Datas.data.RedisIP_Num;
        PortNum = Datas.data.PortNum;
        GetDataLoop = Datas.data.GetDataLoop;
        ThreadDelay = Datas.data.ThreadDelay;

        redis = new Redis();
        if (redis.Init(RedisIP_Num, PortNum, delegate
        {
            while (GetDataLoop)
            {
                GEtD();
                Thread.Sleep(ThreadDelay);

            }
        }))
        {
            Debug.Log("connect");
        }
        else
        {
            Debug.Log("Non_connect");
        }


    }

    private void OnApplicationQuit()
    {
        GetDataLoop = false;
        //redis.T.Join();
    }

    public void GEtD()
    {
        TStory.Global.Dnet_Connection = (redis.GetHASH_Bool(Key, "TStory-connection"));
        TStory.Global.Dnet_readwrite = (redis.GetHASH_Bool(Key, "TStory-readwrite"));
        TStory.Global.Dnet_error = (redis.GetHASH_Bool(Key, "device-net-error"));
        TStory.Global.server_cache_alive = (redis.GetHASH_Double(Key, "server-cache-alive"));
        TStory.Global.client_connection_count = (redis.GetHASH_Int(Key, "client-connection-count"));

    }

}

public class Redis
{
    private ConnectionMultiplexer redisConnection;
    private IDatabase DB;
    private ISubscriber sub;
    public delegate void Events();
    public Thread T;
    public bool Init(string host, int port)
    {

        this.redisConnection = ConnectionMultiplexer.Connect(host + ":" + port);
        if (redisConnection.IsConnected)
        {
            this.DB = this.redisConnection.GetDatabase();
            sub = redisConnection.GetSubscriber();
            return true;
        }

        return false;
    }

    public bool Init(string host, int port, Events LoopEvents)
    {


        T = new Thread(new ThreadStart(LoopEvents));
        try
        {
            ConfigurationOptions option = new ConfigurationOptions
            {
                ConnectTimeout = 1000,
                AbortOnConnectFail = false,
                EndPoints = { $"{host}:{port}" },
            };
            redisConnection = ConnectionMultiplexer.Connect(option);
        }
        catch (Exception e)
        {
            Debug.Log(e);
        }

        if (redisConnection.IsConnected)
        {
            this.DB = this.redisConnection.GetDatabase();
            sub = redisConnection.GetSubscriber();
            T.Start();

            return true;
        }

        return false;
    }
    public string GetString(string key)
    {
        return this.DB.StringGet(key);
    }
    public bool SetString(string key, string val)
    {
        return this.DB.StringSet(key, val);
    }
    public RedisValue GetHASH(string key, string val)
    {
        return this.DB.HashGet(key, val);
    }
    public bool GetHASH_Bool(string key, string val)
    {
        var data = this.DB.HashGet(key, val);
        if (data.ToString()[0] == 't' || data.ToString()[0] == 'T')
        {
            return true;
        }
        return false;
    }
    public int GetHASH_Int(string key, string val)
    {
        var data = this.DB.HashGet(key, val);
        int Idata = 0;
        if (data.HasValue == true)
        {
            int DataSize = data.ToString().Length - 1;
            int sizenum = (int)Math.Pow(10, DataSize);
            foreach (var d in data.ToString())
            {
                if ('0' <= d && d <= '9')
                {
                    Idata += ((d - 48) * sizenum);
                    sizenum /= 10;
                }
                else
                {
                    return -int.MaxValue;
                }
            }
        }
        return Idata;
    }
    public double GetHASH_Double(string key, string val)
    {
        var data = this.DB.HashGet(key, val);
        if (data.HasValue == true)
        {
            double Idata = Double.Parse(data);
            return Idata;
        }
        return -Double.MaxValue;
    }
    public void SetHASH(string key, HashEntry[] val)
    {
        this.DB.HashSet(key, val);
    }
    public void DestroyHash(string key, RedisValue field)
    {
        this.DB.HashDelete(key, field);
    }
    public void Meseage(string Channel, string Meseage)
    {
        sub.Publish(Channel, Meseage);
    }

}

 

'엔진 > 유니티' 카테고리의 다른 글

Unity Spline 기능 추가!  (0) 2023.06.01
Unity Simulator  (0) 2023.01.20
Unity ObjectPool Api  (0) 2022.11.02
unity _Prefab Variants  (0) 2022.03.17
Unity Inspector 창 정리  (2) 2022.02.24

+ Recent posts