Unity中.GetComponent获取StripeNum变量值异常为0的问题
问题描述
StripeNum脚本挂载在按钮对象上,点击红色按钮时,Debug.Log显示stripe1的值为20;但在FinalCalc脚本中,通过GetComponent<StripeNum>()获取该变量时,Debug.Log显示stripe1.stripe1的值为0。两个脚本引用的是同一个游戏对象(该对象同时作为按钮的载体)。
相关代码:
StripeNum.cs
using UnityEngine; public class StripeNum : MonoBehaviour { public void black() { stripe1 = 0; } public void brown() { stripe1 = 10; } public void red() { stripe1 = 20; Debug.Log(stripe1); } public void orange() { stripe1 = 30; } public void yellow() { stripe1 = 40; } public void green() { stripe1 = 50; } public void blue() { stripe1 = 60; } public void purple() { stripe1 = 70; } public void grey() { stripe1 = 80; } public void white() { stripe1 = 90; } public float stripe1; }
FinalCalc.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; public class FinalCalc : MonoBehaviour { Scene c_scene; float TwoStripesAdded; float FinalR; public Text FinalNum; void Start(){ c_scene = SceneManager.GetActiveScene(); GameObject gameobject = GameObject.Find("GameObject"); StripeNum stripe1 = gameobject.GetComponent<StripeNum>(); Stripe2Num stripe2 = gameobject.GetComponent<Stripe2Num>(); Stripe3Num stripe3 = gameobject.GetComponent<Stripe3Num>(); Stripe4Num stripe4 = gameobject.GetComponent<Stripe4Num>(); if (c_scene.buildIndex == 6){ TwoStripesAdded = stripe1.stripe1 + stripe2.stripe1; Debug.Log($"Added {stripe1.stripe1} and {stripe2.stripe1} and got {TwoStripesAdded}"); FinalR = TwoStripesAdded * stripe3.stripe1; FinalNum.text = FinalR.ToString() + "Ω " + "±" + stripe4.stripe1 + "%"; } } }
问题原因与解决方法
核心原因
FinalCalc的Start()方法在场景加载完成时立即执行,而你点击红色按钮修改stripe1的操作是在Start执行之后发生的,所以此时获取到的是变量的初始默认值0。
解决方法
方法1:延迟计算,通过按钮触发
不在Start()里直接计算,而是在用户完成所有颜色选择后,通过一个“计算”按钮触发计算逻辑:
修改FinalCalc脚本,新增公开方法并绑定到按钮点击事件:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; public class FinalCalc : MonoBehaviour { Scene c_scene; float TwoStripesAdded; float FinalR; public Text FinalNum; // 提前缓存组件引用,避免重复查找 private StripeNum stripe1; private Stripe2Num stripe2; private Stripe3Num stripe3; private Stripe4Num stripe4; void Start(){ c_scene = SceneManager.GetActiveScene(); GameObject gameobject = GameObject.Find("GameObject"); stripe1 = gameobject.GetComponent<StripeNum>(); stripe2 = gameobject.GetComponent<Stripe2Num>(); stripe3 = gameobject.GetComponent<Stripe3Num>(); stripe4 = gameobject.GetComponent<Stripe4Num>(); } // 新增方法,绑定到计算按钮的点击事件 public void CalculateFinalValue(){ if (c_scene.buildIndex == 6){ TwoStripesAdded = stripe1.stripe1 + stripe2.stripe1; Debug.Log($"Added {stripe1.stripe1} and {stripe2.stripe1} and got {TwoStripesAdded}"); FinalR = TwoStripesAdded * stripe3.stripe1; FinalNum.text = FinalR.ToString() + "Ω " + "±" + stripe4.stripe1 + "%"; } } }
方法2:实时监听值变化,自动更新结果
如果需要用户点击颜色按钮时立即更新结果,可以给条纹脚本添加事件通知机制:
首先修改StripeNum脚本(Stripe2Num、Stripe3Num、Stripe4Num同理修改):
using UnityEngine; using UnityEngine.Events; public class StripeNum : MonoBehaviour { // 定义值变化事件 public UnityEvent<float> OnStripeValueChanged; public void black() { UpdateStripeValue(0); } public void brown() { UpdateStripeValue(10); } public void red() { UpdateStripeValue(20); } // 其他颜色方法同理替换为UpdateStripeValue调用 private void UpdateStripeValue(float value){ stripe1 = value; Debug.Log(stripe1); // 触发事件通知订阅者 OnStripeValueChanged?.Invoke(value); } public float stripe1; }
然后修改FinalCalc脚本监听事件:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; public class FinalCalc : MonoBehaviour { Scene c_scene; float TwoStripesAdded; float FinalR; public Text FinalNum; private StripeNum stripe1; private Stripe2Num stripe2; private Stripe3Num stripe3; private Stripe4Num stripe4; void Start(){ c_scene = SceneManager.GetActiveScene(); GameObject gameobject = GameObject.Find("GameObject"); stripe1 = gameobject.GetComponent<StripeNum>(); stripe2 = gameobject.GetComponent<Stripe2Num>(); stripe3 = gameobject.GetComponent<Stripe3Num>(); stripe4 = gameobject.GetComponent<Stripe4Num>(); // 订阅所有条纹的值变化事件 stripe1.OnStripeValueChanged.AddListener(UpdateFinalValue); stripe2.OnStripeValueChanged.AddListener(UpdateFinalValue); stripe3.OnStripeValueChanged.AddListener(UpdateFinalValue); stripe4.OnStripeValueChanged.AddListener(UpdateFinalValue); // 初始计算一次 if (c_scene.buildIndex == 6){ UpdateFinalValue(0); } } private void UpdateFinalValue(float _){ if (c_scene.buildIndex != 6) return; TwoStripesAdded = stripe1.stripe1 + stripe2.stripe1; Debug.Log($"Added {stripe1.stripe1} and {stripe2.stripe1} and got {TwoStripesAdded}"); FinalR = TwoStripesAdded * stripe3.stripe1; FinalNum.text = FinalR.ToString() + "Ω " + "±" + stripe4.stripe1 + "%"; } // 取消订阅避免内存泄漏 void OnDestroy(){ stripe1.OnStripeValueChanged.RemoveListener(UpdateFinalValue); stripe2.OnStripeValueChanged.RemoveListener(UpdateFinalValue); stripe3.OnStripeValueChanged.RemoveListener(UpdateFinalValue); stripe4.OnStripeValueChanged.RemoveListener(UpdateFinalValue); } }
额外优化建议
- 避免使用
GameObject.Find("GameObject"),可以直接在Inspector面板拖拽赋值目标对象,减少性能开销且更可靠。 - StripeNum、Stripe2Num等脚本结构高度重复,可以合并为一个通用脚本,通过参数区分不同条纹,减少代码冗余。
内容的提问来源于stack exchange,提问作者Freaky
相关产品推荐
相关产品推荐

