Unity挂载两份相同UDP脚本时端口监听行为异常问题咨询
问题成因
- 核心原因是代码中
UdpClient udp被声明为static静态成员:静态成员属于类所有实例共享,不会为每个实例单独分配存储空间。当挂载第二个脚本实例时,Start方法中对udp的赋值会直接覆盖第一个实例创建的UdpClient对象,最终两个脚本实例操作的是同一个UdpClient。 - 两个脚本实例各自启动了独立的线程读取同一个UdpClient的数据包,线程之间会竞争接收消息:只要共享的UdpClient收到数据,任意一个实例的线程都有可能抢到数据,并更新自身实例的
udp_message字段,因此就会出现监听8889端口的脚本也响应8888端口消息的现象。 - 额外隐患:被覆盖引用的第一个UdpClient对象如果未被回收,会持续占用对应端口,导致后续重复绑定端口时报错。
修复方案
- 移除
UdpClient udp的static修饰符,让每个脚本实例持有独立的UdpClient对象,各自监听对应的端口。 - 补充脚本生命周期结束时的资源释放逻辑,避免线程泄漏和端口残留占用。
修改后的完整代码
using UnityEngine; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; public class TestScript : MonoBehaviour { // 移除static修饰符,改为实例私有成员 private UdpClient udp; private string udp_message = ""; private Thread thread; public int port = 8888; // 增加线程运行标记,用于安全退出线程 private bool isThreadRunning = false; void Start() { udp = new UdpClient(port); isThreadRunning = true; thread = new Thread(new ThreadStart(ThreadMethod)); thread.IsBackground = true; // 设为后台线程,避免程序退出后线程仍残留 thread.Start(); } void Update() { string port_string = port.ToString(); Debug.Log(port_string + ":" + udp_message); } void ThreadMethod() { while (isThreadRunning) { try { IPEndPoint remoteEP = null; byte[] data = udp.Receive(ref remoteEP); udp_message = Encoding.ASCII.GetString(data); } catch { // 忽略异常,避免线程崩溃 } } } // 补充销毁逻辑,释放资源 void OnDestroy() { isThreadRunning = false; udp?.Close(); if (thread != null && thread.IsAlive) { thread.Join(100); // 等待线程退出,超时则强制终止 if (thread.IsAlive) { thread.Abort(); } } } }
内容的提问来源于stack exchange,提问作者taichi
相关产品推荐
相关产品推荐

