Unity-Technologies / Unity-Technologies/com.unity.netcode.gameobjects

Add a single unified “OnNetworkStarted” event to NetworkManager

未关闭
#3,706 5 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

priority:medium stat:imported type:feature type:feature-2.x
主要语言
C#
星标
2.3k
派生
461
平均合并
3 天 16 小时
30 天内合并 PR
20

描述

The problem

There’s no single event that fires once when networking starts, regardless of mode
Currently you need to handle both OnServerStarted and OnClientConnectedCallback, which leads to redundant or missing calls depending on the mode (client/server)
Using per-connection callbacks for this is unreliable, and managing timing around the singleton or validation properties(e.g IsListening) adds unnecessary complexity

Unless i am missing something, to me this dont feels right

Current workflow

The current workaround is using coroutines or polling to wait until the singleton exists and the NetworkManager is listening.
This adds overhead and makes initialization logic fragile, even more for singleplayer sessions where the code may keep waiting forever as no connections are made

Example (based on forums suggestions):

void OnEnable()
{
   StartCoroutine(SubscribeToNetworkManagerEvents());
}

IEnumerator SubscribeToNetworkManagerEvents()
{
   yield return new WaitUntil(() => NetworkManager.Singleton); //This is fragile, and may add other problems, and no mention to cancelations
   NetworkManager.Singleton.OnClientConnectedCallback += OnClientConnectedCallback; //called on clients but unclear about standalone server
   NetworkManager.Singleton.OnServerStarted += OnServerStarted; //never called on non host client
}

void OnDestroy()
{
   if (NetworkManager.Singleton)
   {
      NetworkManager.Singleton.OnClientConnectedCallback -= OnClientConnectedCallback;
      NetworkManager.Singleton.OnServerStarted -= OnServerStarted;
   }
   initialized = false;
}

void OnClientConnectedCallback(parameters)
{
   RegisterMessageHandler();
}

void OnServerStarted(parameters)
{
   RegisterMessageHandler();
}

bool initialized;
//Both on client connected callback and server started calls this other method
void RegisterMessageHandler()
{
   if(initialized)
      return;
//For example
		NetworkManager.Singleton.CustomMessagingManager.RegisterNamedMessageHandler("a", B);
// In this case, Singleton can be null and CustomMessagingManager also can be null, thats why we need the yield
   initialized = true;
}

These yields are required only because there is no dedicated lifecycle event indicating when the NetworkManager and its subsystems (like CustomMessagingManager) are fully initialized
As result, developers must manually simulate this missing initialization phase using coroutines or polling, which makes code more complex

Posible solution

Add new public static Action<NetworkManager> OnNetworkStarted event to NetworkManager
Triggered once when the network stack has been initialized and the transport is ready, regardless of whether it’s running as server, client, or host.
Passing the Network manager initialized (as after working on the last pull request, i saw on the tests part and other parts of code might exist more than one NetworkManager)

This would change the workflow to a much more convenient one like this

NetworkManager networkManager;

void OnEnable()
{
   NetworkManager.OnNetworkStarted += OnNetworkStarted;
}

void OnNetworkStarted(NetworkManager networkManager) 
{
   this.networkManager = networkManager; 
   networkManager.CustomMessagingManager.RegisterNamedMessageHandler("a", B);
}


void OnDestroy()
{
   if (networkManager)
      networkManager.CustomMessagingManager.UnregisterNamedMessageHandler("a");
}

[!NOTE]
While NetworkBehaviour.OnNetworkSpawn can be used for components, this event would support use cases where no scene objects are involved (e.g ScriptableObjects or systems initialized outside scene contexts). It provides a clean, unified hook for all modes.

This change would mostly take 2 lines

  1. public static Action<NetworkManager> OnNetworkStarted on NetworkManager class
  2. OnNetworkStarter?.Invoke(This); at the very end of NetworkManager's internal void Initialize(bool server) method

It only may cause problems on having it static with the editor reloading feature, but that could be arranged cleaning the event with the [RuntimeInitializeOnLoadAttribute]

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

调研方向

从 NetworkManager 开始,重点检查 internal Initialize(bool server),并检查现有的 OnServerStarted 和 OnClientConnectedCallback 生命周期路径及相关测试。完成标准是在 server、client 和 host 模式下,网络堆栈和传输层准备就绪后仅触发一次单个事件,同时覆盖多个 NetworkManager 实例和编辑器重新加载的行为。

由索引模型根据 Issue 内容生成。

评估

技术栈
csharp, unity
领域
api, networking
Issue 类型
功能
难度
4/5
预计耗时
3-5 天
活跃度
停滞
描述清晰度
基本清楚
新手友好度
42/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。