为何给实例化的GameObject添加TextMesh后变量仍为空?
问题:为实例化的GameObject添加TextMesh组件显示旋转速度
需求:给每个实例化生成的GameObject添加TextMesh组件,用于显示其旋转速度。
尝试的代码及问题
代码1
private void CreateObject() { Vector3 position = new Vector3(Random.Range(-10f, 10f), Random.Range(-5f, 5f), Random.Range(-10f, 10f)); GameObject go = Instantiate(objectPrefab, position, Quaternion.identity); createdObjects.Add(go); rotationSpeeds.Add(Random.Range(minRotationSpeed, maxRotationSpeed)); rotationTimers.Add(rotationSpeedChangeInterval); currentObjectCount++; // Add a TextMesh component to display the rotation speed TextMesh textMesh = go.GetComponentInChildren<TextMesh>(); if (textMesh == null) { textMesh = go.AddComponent<TextMesh>(); } textMesh.text = rotationSpeeds[currentObjectCount - 1].ToString(); textMesh.anchor = TextAnchor.MiddleCenter; textMesh.alignment = TextAlignment.Center; textMesh.fontSize = 12; textMesh.color = Color.white; }
问题:执行GetComponentInChildren<TextMesh>()并添加组件后,textMesh变量仍为空。
代码2
private void CreateObject() { Vector3 position = new Vector3(Random.Range(-10f, 10f), Random.Range(-5f, 5f), Random.Range(-10f, 10f)); GameObject go = Instantiate(objectPrefab, position, Quaternion.identity); createdObjects.Add(go); rotationSpeeds.Add(Random.Range(minRotationSpeed, maxRotationSpeed)); rotationTimers.Add(rotationSpeedChangeInterval); currentObjectCount++; TextMesh textMesh = go.GetComponentInChildren<TextMesh>(); if (textMesh == null) { textMesh = go.AddComponent<TextMesh>(); } textMesh = go.GetComponent<TextMesh>(); textMesh.text = rotationSpeeds[currentObjectCount - 1].ToString(); textMesh.anchor = TextAnchor.MiddleCenter; textMesh.alignment = TextAlignment.Center; textMesh.fontSize = 12; textMesh.color = Color.white; }
问题:编辑器抛出异常:
MissingComponentException: There is no 'TextMesh' attached to the "Cube(Clone)" game object, but a script is trying to access it.
You probably need to add a TextMesh to the game object "Cube(Clone)". Or your script needs to check if the component is attached before using it.
问题原因分析
GetComponentInChildren<TextMesh>()默认仅查找活跃状态的子物体组件,如果prefab中存在非活跃的子物体,可能会漏查;另外,若实例化的GameObject结构复杂,可能出现查找逻辑的意外问题。- 代码2中额外调用
textMesh = go.GetComponent<TextMesh>()会覆盖之前的赋值,如果AddComponent操作因某些原因未成功(比如GameObject被锁定、组件依赖缺失),就会导致textMesh变为null,触发异常。
解决方案
方案1:确保组件查找和添加的可靠性
修改组件查找逻辑,明确包含非活跃物体,并且直接使用AddComponent的返回值,避免二次查找覆盖:
private void CreateObject() { Vector3 position = new Vector3(Random.Range(-10f, 10f), Random.Range(-5f, 5f), Random.Range(-10f, 10f)); GameObject go = Instantiate(objectPrefab, position, Quaternion.identity); createdObjects.Add(go); float currentSpeed = Random.Range(minRotationSpeed, maxRotationSpeed); rotationSpeeds.Add(currentSpeed); rotationTimers.Add(rotationSpeedChangeInterval); currentObjectCount++; // 查找当前物体及所有子物体的TextMesh,包含非活跃物体 TextMesh textMesh = go.GetComponentInChildren<TextMesh>(includeInactive: true); if (textMesh == null) { // 直接在当前物体添加组件,并将返回值赋值给textMesh textMesh = go.AddComponent<TextMesh>(); } // 设置TextMesh属性 textMesh.text = currentSpeed.ToString(); textMesh.anchor = TextAnchor.MiddleCenter; textMesh.alignment = TextAlignment.Center; textMesh.fontSize = 12; textMesh.color = Color.white; }
方案2:创建独立子物体放置TextMesh(推荐)
为了避免和原prefab的组件结构冲突,同时防止文本被物体遮挡,专门创建一个子物体来承载TextMesh:
private void CreateObject() { Vector3 position = new Vector3(Random.Range(-10f, 10f), Random.Range(-5f, 5f), Random.Range(-10f, 10f)); GameObject go = Instantiate(objectPrefab, position, Quaternion.identity); createdObjects.Add(go); float currentSpeed = Random.Range(minRotationSpeed, maxRotationSpeed); rotationSpeeds.Add(currentSpeed); rotationTimers.Add(rotationSpeedChangeInterval); currentObjectCount++; // 创建专门的子物体用于显示文本 GameObject textObject = new GameObject("RotationSpeedLabel"); textObject.transform.SetParent(go.transform); textObject.transform.localRotation = Quaternion.identity; // 调整文本位置到物体上方,避免遮挡 Renderer renderer = go.GetComponent<Renderer>(); if (renderer != null) { float offsetY = renderer.bounds.extents.y + 0.5f; textObject.transform.localPosition = new Vector3(0, offsetY, 0); } else { textObject.transform.localPosition = Vector3.up; } // 添加TextMesh组件并设置属性 TextMesh textMesh = textObject.AddComponent<TextMesh>(); textMesh.text = currentSpeed.ToString(); textMesh.anchor = TextAnchor.MiddleCenter; textMesh.alignment = TextAlignment.Center; textMesh.fontSize = 12; textMesh.color = Color.white; }
说明
- 方案1适合需要复用现有TextMesh组件的场景;
- 方案2更灵活,不会影响原物体的组件结构,且文本显示位置更可控,推荐使用。
内容的提问来源于stack exchange,提问作者Daniel Lip
相关产品推荐
相关产品推荐

