Mirror框架中修改名称后客户端无报错断开连接问题求助
解决Mirror框架客户端修改名称断开连接的问题
你的问题核心是对Command方法的执行上下文理解错误:[Command]标记的方法是在服务器端执行的,而你在CmdChangeName里直接访问客户端的TMP_InputField组件tmpf——服务器上不存在这个UI对象,会触发空引用异常,导致客户端被强制断开,这就是你看到“客户端未执行逻辑就终止”的原因。
解决方案
不要在Command方法中访问客户端本地UI组件,而是将输入的名字作为参数传递给Command,服务器端接收参数后直接赋值给SyncVar,通过SyncVar的Hook自动同步到所有客户端。
修改后的完整代码:
using System.Collections; using System.Collections.Generic; using UnityEngine; using Mirror; using TMPro; public class PlayerMovement : NetworkBehaviour { public float speed; float x, y; Rigidbody2D rb; Animator animator; public TMP_InputField tmpf; public TMP_Text nameText; [SyncVar(hook = nameof(DisplayName))] public string _name = "00"; void DisplayName(string oldName, string newName) { nameText.text = newName; } void Start() { if (!isLocalPlayer) return; rb = GetComponent<Rigidbody2D>(); animator = GetComponent<Animator>(); tmpf = GameObject.Find("NameIF").GetComponent<TMP_InputField>(); } void Update() { if (!isLocalPlayer) return; x = Input.GetAxis("Horizontal"); y = Input.GetAxis("Vertical"); rb.velocity = new Vector2(x * speed, y * speed); animator.SetFloat("horizontal", x); animator.SetFloat("vertical", y); if (Input.GetKeyDown(KeyCode.KeypadEnter)) { // 将输入框文本作为参数传入Command if (!string.IsNullOrEmpty(tmpf.text)) { CmdChangeName(tmpf.text); } } } [Command] public void CmdChangeName(string newName) { // 服务器端直接使用传入的参数,避免访问客户端UI // 可选:添加输入验证,比如限制长度、过滤非法字符 if (newName.Length > 10) { newName = newName.Substring(0, 10); } _name = newName; } }
关键改动说明
- 传递参数给Command:客户端调用
CmdChangeName时,把tmpf.text作为参数传入,让服务器直接使用这个字符串,避免访问客户端本地UI组件。 - 服务器端输入验证:增加了简单的长度限制,避免过长名字导致显示问题,你可以根据需求扩展验证逻辑(比如过滤特殊字符)。
- 保留SyncVar同步逻辑:SyncVar的Hook方法
DisplayName会在_name值改变时自动在所有客户端(包括服务器)执行,确保名字文本同步更新。
额外注意事项
- 开启客户端权限后,本地玩家可以直接调用Command方法,但服务器永远无法访问客户端的本地GameObject或组件,所有需要传递给服务器的数据都必须通过参数传递。
- 确保
NameIF这个UI对象在每个客户端的场景中都存在,且只有本地玩家会执行Start里的初始化逻辑(因为有!isLocalPlayer判断)。
内容的提问来源于stack exchange,提问作者SostumeTermApplaudSpeaker
相关产品推荐
相关产品推荐

