UDP command logic
This commit is contained in:
41
README.md
41
README.md
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
#### Key Scripts
|
#### Key Scripts
|
||||||
- **`TaskTimer.cs`** - Configurable countdown timer with UI display, color warnings when time is low, and auto-return to Lobby on expiration
|
- **`TaskTimer.cs`** - Configurable countdown timer with UI display, color warnings when time is low, and auto-return to Lobby on expiration
|
||||||
- **`TaskButtonManager.cs`** - Scene navigation using number keys (1-8 for tasks, L/0 for Lobby)
|
- **`TaskButtonManager.cs`** - Scene navigation using number keys (1-8 for tasks, L/0 for Lobby) and UDP remote control (default port 5555)
|
||||||
- **`PositionTracker.cs`** - Records Transform positions to CSV at configurable intervals for data collection
|
- **`PositionTracker.cs`** - Records Transform positions to CSV at configurable intervals for data collection
|
||||||
|
|
||||||
#### Technologies
|
#### Technologies
|
||||||
@ -46,6 +46,45 @@
|
|||||||
- **L or 0** - Return to Lobby
|
- **L or 0** - Return to Lobby
|
||||||
- VR controllers for interaction within tasks
|
- VR controllers for interaction within tasks
|
||||||
|
|
||||||
|
#### UDP Remote Control
|
||||||
|
The Unity application listens for UDP commands on **port 5555** (configurable in Unity Inspector) for remote scene switching.
|
||||||
|
|
||||||
|
**Command Format:**
|
||||||
|
```
|
||||||
|
SWITCH:SceneName
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example Commands:**
|
||||||
|
```bash
|
||||||
|
# Switch to VR Task 1
|
||||||
|
echo "SWITCH:VR-Task1" | nc -u localhost 5555
|
||||||
|
|
||||||
|
# Switch to AR Task 2
|
||||||
|
echo "SWITCH:AR-Task2" | nc -u localhost 5555
|
||||||
|
|
||||||
|
# Return to Lobby
|
||||||
|
echo "SWITCH:Lobby" | nc -u localhost 5555
|
||||||
|
```
|
||||||
|
|
||||||
|
**Python Example:**
|
||||||
|
```python
|
||||||
|
import socket
|
||||||
|
|
||||||
|
def switch_scene(scene_name, host='localhost', port=5555):
|
||||||
|
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
|
message = f"SWITCH:{scene_name}"
|
||||||
|
sock.sendto(message.encode('utf-8'), (host, port))
|
||||||
|
sock.close()
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
switch_scene("VR-Task1")
|
||||||
|
```
|
||||||
|
|
||||||
|
**Available Scene Names:**
|
||||||
|
- `VR-Task1`, `VR -Task2`, `VR -Task3`, `VR -Task4`
|
||||||
|
- `AR-Task1`, `AR-Task2`, `AR-Task3`, `AR-Task4`
|
||||||
|
- `Lobby`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Chat Application (`Chat-App/`)
|
### Chat Application (`Chat-App/`)
|
||||||
|
|||||||
BIN
Unity/Assets/Scenes/VR/VR -Task2.unity
(Stored with Git LFS)
BIN
Unity/Assets/Scenes/VR/VR -Task2.unity
(Stored with Git LFS)
Binary file not shown.
BIN
Unity/Assets/Scenes/VR/VR -Task3.unity
(Stored with Git LFS)
BIN
Unity/Assets/Scenes/VR/VR -Task3.unity
(Stored with Git LFS)
Binary file not shown.
BIN
Unity/Assets/Scenes/VR/VR -Task4.unity
(Stored with Git LFS)
BIN
Unity/Assets/Scenes/VR/VR -Task4.unity
(Stored with Git LFS)
Binary file not shown.
BIN
Unity/Assets/Scenes/VR/VR-Task1.unity
(Stored with Git LFS)
BIN
Unity/Assets/Scenes/VR/VR-Task1.unity
(Stored with Git LFS)
Binary file not shown.
@ -1,10 +1,42 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.SceneManagement;
|
using UnityEngine.SceneManagement;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
public class TaskButtonManager : MonoBehaviour
|
public class TaskButtonManager : MonoBehaviour
|
||||||
{
|
{
|
||||||
|
[Header("UDP Settings")]
|
||||||
|
[SerializeField] private int udpPort = 5555;
|
||||||
|
[SerializeField] private bool enableUDPControl = true;
|
||||||
|
|
||||||
|
private UdpClient udpClient;
|
||||||
|
private Thread udpListenerThread;
|
||||||
|
private bool isListening = false;
|
||||||
|
private string pendingSceneName = null;
|
||||||
|
private readonly object sceneLock = new object();
|
||||||
|
|
||||||
|
private void Start()
|
||||||
|
{
|
||||||
|
if (enableUDPControl)
|
||||||
|
{
|
||||||
|
StartUDPListener();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void Update()
|
private void Update()
|
||||||
{
|
{
|
||||||
|
// Check for pending UDP scene changes (must be done on main thread)
|
||||||
|
lock (sceneLock)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(pendingSceneName))
|
||||||
|
{
|
||||||
|
LoadSceneByName(pendingSceneName);
|
||||||
|
pendingSceneName = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// VR Tasks (Keys 1-4)
|
// VR Tasks (Keys 1-4)
|
||||||
if (Input.GetKeyDown(KeyCode.Alpha1) || Input.GetKeyDown(KeyCode.Keypad1))
|
if (Input.GetKeyDown(KeyCode.Alpha1) || Input.GetKeyDown(KeyCode.Keypad1))
|
||||||
LoadSceneByName("VR-Task1");
|
LoadSceneByName("VR-Task1");
|
||||||
@ -30,9 +62,101 @@ public class TaskButtonManager : MonoBehaviour
|
|||||||
LoadSceneByName("Lobby");
|
LoadSceneByName("Lobby");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void StartUDPListener()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
isListening = true;
|
||||||
|
udpClient = new UdpClient(udpPort);
|
||||||
|
udpListenerThread = new Thread(new ThreadStart(ListenForUDPCommands));
|
||||||
|
udpListenerThread.IsBackground = true;
|
||||||
|
udpListenerThread.Start();
|
||||||
|
Debug.Log($"UDP Listener started on port {udpPort}");
|
||||||
|
}
|
||||||
|
catch (System.Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogError($"Failed to start UDP listener: {e.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ListenForUDPCommands()
|
||||||
|
{
|
||||||
|
IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, udpPort);
|
||||||
|
|
||||||
|
while (isListening)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
byte[] data = udpClient.Receive(ref remoteEndPoint);
|
||||||
|
string message = Encoding.UTF8.GetString(data);
|
||||||
|
ProcessUDPCommand(message);
|
||||||
|
}
|
||||||
|
catch (System.Exception e)
|
||||||
|
{
|
||||||
|
if (isListening)
|
||||||
|
{
|
||||||
|
Debug.LogError($"UDP receive error: {e.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessUDPCommand(string message)
|
||||||
|
{
|
||||||
|
Debug.Log($"Received UDP command: {message}");
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(message))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Parse command format: SWITCH:SceneName
|
||||||
|
string[] parts = message.Split(':');
|
||||||
|
if (parts.Length == 2 && parts[0].Trim().ToUpper() == "SWITCH")
|
||||||
|
{
|
||||||
|
string sceneName = parts[1].Trim();
|
||||||
|
lock (sceneLock)
|
||||||
|
{
|
||||||
|
pendingSceneName = sceneName;
|
||||||
|
}
|
||||||
|
Debug.Log($"Scheduled scene switch to: {sceneName}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogWarning($"Invalid UDP command format: {message}. Expected format: SWITCH:SceneName");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void LoadSceneByName(string sceneName)
|
private void LoadSceneByName(string sceneName)
|
||||||
{
|
{
|
||||||
Debug.Log($"Loading scene: {sceneName}");
|
Debug.Log($"Loading scene: {sceneName}");
|
||||||
SceneManager.LoadScene(sceneName);
|
SceneManager.LoadScene(sceneName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnDestroy()
|
||||||
|
{
|
||||||
|
StopUDPListener();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnApplicationQuit()
|
||||||
|
{
|
||||||
|
StopUDPListener();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StopUDPListener()
|
||||||
|
{
|
||||||
|
isListening = false;
|
||||||
|
|
||||||
|
if (udpClient != null)
|
||||||
|
{
|
||||||
|
udpClient.Close();
|
||||||
|
udpClient = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (udpListenerThread != null && udpListenerThread.IsAlive)
|
||||||
|
{
|
||||||
|
udpListenerThread.Abort();
|
||||||
|
udpListenerThread = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.Log("UDP Listener stopped");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user