LoginSignup
9
5

More than 1 year has passed since last update.

UnityでArtNetを受け取りたかった話

Last updated at Posted at 2021-03-09

前置き

現在所属しているライブサークルで、今まで照明をdmxで光らせていたのをUnity上の仮装灯台を光らせるようにしなくちゃいけなくなった。そこでArtnetを使ったプラグインをつくったので投稿します。(今回のソースコードはこちら)
※注意: DaLight4でArtnetを使うには専用のデバイスの購入が必要です

内容

ArtNetはUDP通信を用いてdmxのデータを送信できる照明界隈で使われているプロトコル。これ使えば実際の照明もUnityとかUE4なんかで作ったバーチャル照明を同様に光らせることができます。

今回やりたかったことを図で説明するとこんな感じ。現在サークルで使っているDasLightというソフト側からイーサネット経由でUnityに信号を送った。
image.png

実装について

ArtNetのプロトコルについてはwikiとドキュメントを読みました

こいつによると受け取ったバイト列は次の表のようになるとのこと

index 中身
0 ~ 7 Protocol (Art-Net)
8, 9 Opcode ArtDMX (0x5000) little endian
10 Protocol Version Hi (0)
11 Protocol Version Lo (14)
12 Sequence (255周期)
13 Physical
14,15 Universe little endian
16 Length Hi
17 Length Lo (2 to 512, even)
18 ~ Data

あとはこの表に従ってUdp通信で受け取ったデータをArtnetDataクラスを作成し、コトラクタで初期化を行いました。

/*!
 * Copyright (c) 2021 Takuya Isaki
 *
 * Released under the MIT license.
 * see https://opensource.org/licenses/MIT
 */

using System;
using UnityEditorInternal;
using UnityEngine;

namespace ArtNet.Runtime
{
    public readonly struct ArtNetData
    {
        #region public filed

        public readonly ArtNetOpCode OpCode;
        public readonly int Sequence, Physical, Universe;
        public readonly int[] Channels;
        public readonly int ProtocolVersionHi, ProtocolVersionLo, LengthHi, LengthLo;

        #endregion

        #region public method

        /// <summary>
        /// コンストラクタ
        /// Art-Net Structure
        /// 0 ~ 7 : id 「Art-Net」
        /// 8 ~ 9 : Opcode ArtDMX (0x5000) little endian
        /// 10 : Protocol Version Hi (0)
        /// 11 : Protocol Version Lo (14)
        /// 12 : Sequence (255周期)
        /// 13 : Physical
        /// 14 ~ 15 : Universe little endian
        /// 16 : Length Hi
        /// 17 : Length Lo (2 to 512, even)	
        /// 18 ~ 530 : Data
        /// </summary>
        /// <param name="buf">受信したbyte列</param>
        public ArtNetData(byte[] buf)
        {
            var buffer = new byte[530];
            Buffer.BlockCopy(buf, 0, buffer, 0, buf.Length);
            OpCode = (ArtNetOpCode)BitConverter.ToInt16(new byte[2] { buffer[8], buffer[9] }, 0);
            ProtocolVersionHi = buffer[10];
            ProtocolVersionLo = buffer[11];
            Sequence = buffer[12];
            Physical = buffer[13];
            Universe = BitConverter.ToInt16(new byte[2] { buffer[14], buffer[15] }, 0);
            LengthHi = buffer[16];
            LengthLo = buffer[17];
            Channels = new int[512];
            for (int i = 18; i < buffer.Length; i++)
                Channels[i - 18] = buffer[i];
        }

        public static bool IsArtNet(byte[] buffer)
            => buffer[0] == 'A' &&
               buffer[1] == 'r' &&
               buffer[2] == 't' &&
               buffer[3] == '-' &&
               buffer[4] == 'N' &&
               buffer[5] == 'e' &&
               buffer[6] == 't' &&
               buffer[7] == 0x00;

        public void Logger()
        {
            string str = "";
            str += $"Opcode : {this.OpCode}\n";
            str += $"ProtocolVersionHi : {ProtocolVersionHi}\n";
            str += $"ProtocolVersionLo : {ProtocolVersionLo}\n";
            str += $"Sequence : {Sequence}\n";
            str += $"Physical : {Physical}\n";
            str += $"Universe : {Universe}\n";
            str += $"LengthHi : {LengthHi}\n";
            str += $"LengthLo : {LengthLo}\n";
            foreach (var t in Channels) str += t + "\n";
            Debug.Log(str);
        }

        #endregion
    }
}

受信時はOpCodeをOpDmxのものを扱いたいので、下のようにコードを書く。

using ArtNet.Runtime;
using UnityEngine;

public class SampleLightReceiver : MonoBehaviour
{
    [SerializeField] private ArtNetClient client;
    [SerializeField] private new Light light;

    private void Start()
    {
        this.client.onDataReceived += data =>
        {
            if (data.OpCode == ArtNetOpCode.OpDmx)
            {
                light.color = new Color(
                    data.Channels[0],
                    data.Channels[1],
                    data.Channels[2]);
            }
        };
    }
}

DasLight4からArtnetを送れた
dzfY3oK8wE.gif

参考文献

9
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
5