Skip to content

Instantly share code, notes, and snippets.

@pedrofracassi
Created April 8, 2026 14:59
Show Gist options
  • Select an option

  • Save pedrofracassi/a7ba2d42ca15d7baad23b70aea5c1860 to your computer and use it in GitHub Desktop.

Select an option

Save pedrofracassi/a7ba2d42ca15d7baad23b70aea5c1860 to your computer and use it in GitHub Desktop.
ArtNet Unity Minion
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using UnityEngine;
public class ArtNetManager : MonoBehaviour
{
public static ArtNetManager Instance { get; private set; }
private void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(this.gameObject);
return;
}
Instance = this;
DontDestroyOnLoad(this.gameObject);
}
// -------------------------
[Header("Network Settings")]
public string remoteIP = "127.0.0.1";
public float targetFPS = 40f;
private Dictionary<int, byte[]> _universes = new Dictionary<int, byte[]>();
private UdpClient _udpClient;
private IPEndPoint _remoteEndPoint;
private bool _isSending = false;
void Start()
{
_udpClient = new UdpClient();
_remoteEndPoint = new IPEndPoint(IPAddress.Parse(remoteIP), 6454);
StartCoroutine(ArtNetLoop());
}
public void CreateUniverse(int universeId)
{
if (!_universes.ContainsKey(universeId)) {
Debug.Log("Creating universe: " + universeId);
_universes.Add(universeId, new byte[512]);
}
}
public void SetDmxValue(int universeId, int channel, byte value)
{
if (!_universes.ContainsKey(universeId)) CreateUniverse(universeId);
if (channel >= 0 && channel < 512)
_universes[universeId][channel] = value;
}
public void SetDmxValues(int universeId, int startChannel, byte[] values)
{
if (!_universes.ContainsKey(universeId)) CreateUniverse(universeId);
if (startChannel >= 0 && startChannel + values.Length < 512)
System.Array.Copy(values, 0, _universes[universeId], startChannel, values.Length);
else
Debug.LogError("Invalid start channel or values length for universe: " + universeId);
}
IEnumerator ArtNetLoop()
{
_isSending = true;
var wait = new WaitForSeconds(1f / targetFPS);
while (_isSending)
{
foreach (var kvp in _universes)
{
Debug.Log("Sending ArtNet for universe: " + kvp.Key);
SendArtNet(kvp.Key, kvp.Value);
}
yield return wait;
}
}
private void SendArtNet(int universeId, byte[] dmxValues)
{
byte[] packet = new byte[18 + dmxValues.Length];
System.Array.Copy(System.Text.Encoding.ASCII.GetBytes("Art-Net\0"), 0, packet, 0, 8);
packet[8] = 0x00; packet[9] = 0x50;
packet[10] = 0x00; packet[11] = 0x0e;
packet[14] = (byte)(universeId & 0xFF);
packet[15] = (byte)((universeId >> 8) & 0xFF);
packet[16] = (byte)((dmxValues.Length >> 8) & 0xFF);
packet[17] = (byte)(dmxValues.Length & 0xFF);
System.Array.Copy(dmxValues, 0, packet, 18, dmxValues.Length);
_udpClient.Send(packet, packet.Length, _remoteEndPoint);
}
void OnDisable()
{
_isSending = false;
_udpClient?.Close();
}
}
using UnityEngine;
public class MinionBehavior : MonoBehaviour
{
[Header("Health Bar")]
[SerializeField] private int healthBarPixelAddress = 0;
[SerializeField] private int healthBarPixelCount = 4;
private float health = 100f;
private float healthLossPerSecond = 60f;
void Start()
{
UpdateHealthBarPixels();
}
void Update()
{
health -= healthLossPerSecond * Time.deltaTime;
UpdateHealthBarPixels();
if (health < 0f)
{
health = 0f;
GameObject.Destroy(gameObject);
}
}
void UpdateHealthBarPixels()
{
// Luz do botão
if (health / 100f < 0.25f && health / 100f > 0.0f)
{
ArtNetManager.Instance.SetDmxValues(16, 0, new byte[] { 255 });
}
else
{
ArtNetManager.Instance.SetDmxValues(16, 0, new byte[] { 0 });
}
// Luzes da barrinha
for (int i = 0; i < healthBarPixelCount; i++)
{
if (i < healthBarPixelCount * (health / 100f))
{
ArtNetManager.Instance.SetDmxValues(0, healthBarPixelAddress + i * 3, new byte[] { 0, 255, 0 });
}
else
{
ArtNetManager.Instance.SetDmxValues(0, healthBarPixelAddress + i * 3, new byte[] { 0, 0, 0 });
}
}
}
}
using UnityEngine;
public class MinionSpawner : MonoBehaviour
{
[Header("Minion Prefab")]
[SerializeField] private GameObject minionPrefab;
[Header("Minion Spawn Rate")]
[SerializeField] private float minionSpawnRate = 1f;
private float minionSpawnTimer = 0f;
void Start()
{
minionSpawnTimer = minionSpawnRate;
}
void Update()
{
minionSpawnTimer -= Time.deltaTime;
if (minionSpawnTimer <= 0f)
{
Instantiate(minionPrefab, transform.position, Quaternion.identity);
minionSpawnTimer = minionSpawnRate;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment