1121 words
6 minutes
ROS2 & Unity TCP Tutorial

ROS TCP#

ROS2 is often seen as the robot’s brain, while Unity serves as the eyes and environment. To simulate realistic robotics behavior, we need a bridge between them. That bridge is the ROS-TCP Endpoint/Connector. By connecting both, we can test navigation, visualization, and SLAM in a controlled environment before deploying to real hardware.


Understanding the Basics#

ROS TCP Endpoint/Connector rostcp

  • Def: A ROS node that enables message passing over TCP between ROS2 and external systems like Unity
  • Purpose: : Facilitates real-time communication for robotics simulations and visualizations
  • Example: A ROS node sends robot position data to Unity, which renders the robot in a 3D environment

ROS-Unity Communication rosUnityComm

Image Source: MDPI

  • Def: The broader process of how ROS 2 and Unity interact, using the TCP Endpoint/Connector to exchange data via topics, services, or actions.
  • Example: Unity subscribes to a ROS topic (/robot_color) to change a robot’s color, or ROS responds to a Unity service request with a robot’s pose.

SLAM (Simultaneous Localization & Mapping) slam

Image Source: LASER_Scanning and KODIFLY

  • Def: A method for robots to build a map of an unknown environment while tracking their location within it.
  • Applications: Autonomous navigation, 3D map reconstruction, obstacle avoidance.
  • Example: A robot uses LIDAR to create a 2D occupancy grid in RViz, visualized in Unity.

Materials#


Tutorial#

Since I used ROS2, this tutorial is written based on ROS2 (especially ROS2 Humble).

Setup#

ROS#

download

  1. Download ROS TCP Endpoint
  2. In your src folder of ROS TCP Endpoint, navigate to your Colcon worspace and run the following commands:
Terminal window
source install/setup.bash
colcon build
source install/setup.bash
  1. In your Colcon workspace, run the following command, replacing <your IP address> with your ROS machine’s IP or hostname.
Terminal window
ros2 run ros_tcp_endpoint default_server_endpoint --ros-args -p ROS_IP:=192.168.0.5
  • If you’re running ROS in a Docker container, 0.0.0.0 is a valid incoming address, so you can write ros2 run ros_tcp_endpoint default_server_endpoint --ros-args -p ROS_IP:=0.0.0.0
  • On Linux you can find out your IP address with the command hostname -I
  • On MacOS you can find out your IP address with ipconfig getifaddr en0

Once the server_endpoint has started, it will print something similar to [INFO] [1603488341.950794]: Starting server on 192.168.50.149:10000. (Alternative) If you need the server to listen on a port that’s different from the default 10000, here’s the command line to also set the ROS_TCP_PORT parameter:

Terminal window
ros2 run ros_tcp_endpoint default_server_endpoint --ros-args -p ROS_IP:=127.0.0.1 -p ROS_TCP_PORT:=10000

Unity#

  1. Open the Package Manager (Window > Package Manager)
  2. Click the + button in the upper lefthand corner of the window. Select Add package from git URL...
  3. Enter the git URL for the package.
  4. For the ROS-TCP-Connector, enter https://github.com/Unity-Technologies/ROS-TCP-Connector.git?path=/com.unity.robotics.ros-tcp-connector.
  • (not necessary)For Visualizations, enter https://github.com/Unity-Technologies/ROS-TCP-Connector.git?path=/com.unity.robotics.visualizations.
  1. Click Add.
  2. open Robotics/ROS Settings from the Unity menu bar, and set the ROS IP Address variable to the IP you set earlier. (If you’re using Docker, leave it as the default 127.0.0.1.)
  3. in the ROS Settings window, ROS2 users should switch the protocol to ROS2 now.

ROS Unity Integration#

Publisher#

Unity publishes data (e.g., robot position coordinates) to a ROS 2 topic, which a ROS subscriber receives.

Concept: Unity can act as a Publisher, sending data continuously to a ROS topic. Typical Use Case: Streaming an object’s position, velocity, or any sensor-like data from Unity to ROS. Unity Side: You use the ROSConnection component to define the topic and message type, then call Publish() inside a Unity script. ROS Side: A ROS node subscribes to the same topic to consume Unity’s data.

Subscriber#

ROS2 publishes a topic to change the color, and Unity subscribes to that topic to update it.

Concept: Unity can also subscribe to ROS topics and react when messages arrive. Typical Use Case: ROS publishes sensor data or control commands, and Unity updates its simulation accordingly (e.g., changing color, triggering animations). Unity Side: In Unity, you register a callback for a topic using Subscribe(). ROS Side: A ROS node publishes messages to that topic.

Service#

service

Unity (Service Client) request an object’s pose in Unity. ROS (Service Server) calculates its pose and responds to Unity.

Concept: Unlike Publishers/Subscribers, a Service works as a request–response pattern. Typical Use Case: When Unity needs a precise answer at a specific moment. Unity as Service Client: Unity sends a request, e.g., “What’s the pose of this object?” ROS as Service Server: ROS computes the answer and returns it.

Service Call#

1. Start at current position 2. Move toward destination 3. Near target → Request update from ROS 4. Get new destination 5. Repeat

Concept: A Service Call can be repeated in sequence to drive a process step by step. Typical Use Case: Unity moves an object toward a goal. Once near the target, Unity requests a new goal from ROS, receives it, and continues.

Note: While Publisher and Subscriber cover most real-time data flows, Services shine when you need precise, one-off information. The Service Call tutorial illustrates how even a simple request–response can orchestrate dynamic behavior when chained together.

In practice, you’ll often combine these: Publishers for streaming state, Subscribers for reacting to commands, and Services for exact queries. The key is to choose the right communication model for the task at hand.

Robotics Nav2 SLAM Example#

Running#

Terminal window
git clone https://github.com/Unity-Technologies/Robotics-Nav2-SLAM-Example.git
cd Robotics-Nav2-SLAM-Example/ros2_docker/colcon_ws

➡️ Expected Output: A 2D occupancy grid in RViz showing the robot’s map, with real-time updates as it navigates. You can extend this with custom visualization (e.g., battery status, camera feeds).

Visualization & Custom Visualizer#

DefaultVisualizationSuite includes:

  • GoalPose → Robot position (topic-based).
  • OccupancyGridVisualizer → SLAM map.
  • LaserScanSensor → LiDAR scan.

You also need to add the following code in your Unity.

using System;
using System.Collections.Generic;
using RosMessageTypes.Geometry; // Generated message classes
using Unity.Robotics.Visualizations; // Visualizations
using Unity.Robotics.ROSTCPConnector.ROSGeometry; // Coordinate space utilities
using UnityEngine;
public class PoseTrailVisualizer : HistoryDrawingVisualizer<PoseStampedMsg>
{
[SerializeField]
Color m_Color = Color.white;
[SerializeField]
float m_Thickness = 0.1f;
[SerializeField]
string m_Label = "";
public override Action CreateGUI(IEnumerable<Tuple<PoseStampedMsg, MessageMetadata>> messages)
{
return () =>
{
var count = 0;
foreach (var (message, meta) in messages)
{
GUILayout.Label($"Goal #{count}:");
message.pose.GUI();
count++;
}
};
}
public override void Draw(Drawing3d drawing, IEnumerable<Tuple<PoseStampedMsg, MessageMetadata>> messages)
{
var firstPass = true;
var prevPoint = Vector3.zero;
var color = Color.white;
var label = "";
foreach (var (msg, meta) in messages)
{
var point = msg.pose.position.From<FLU>();
if (firstPass)
{
color = VisualizationUtils.SelectColor(m_Color, meta);
label = VisualizationUtils.SelectLabel(m_Label, meta);
firstPass = false;
}
else
{
drawing.DrawLine(prevPoint, point, color, m_Thickness);
}
prevPoint = point;
}
drawing.DrawLabel(label, prevPoint, color);
}
}

Errors#

ROS Error#

Colcon Build

  • Wrong package name: ROS-TCP-Endpoint-main → ros_tcp_endpoint
  • Wrong build location: colcon build inside Robotics-Nav2-SLAM-Example → Robotics-Nav2-SLAM-Example/ros2_docker/colcon_ws

Not Connected to Unity

  • Wrong Wi-Fi
  • Wrong ROS IP Address

Unity Error#

DeserializationException: Cannot deserialize message

  • Rebuild msg files
ROS2 & Unity TCP Tutorial
https://eun346.github.io/eunha_choi/posts/3tcp-ro2-unity/
Author
Eunha Choi
Published at
2025-07-24