Unity中找到自定义组件后无法访问其内部变量的问题求助
我遇到一个问题,尝试访问脚本组件里存储的变量。玩家可以对GameObject执行约8种操作,用户会给GameObject附加对应的Action脚本来控制操作逻辑。
游戏运行时,我需要遍历GameObject的组件,把选中的操作和附加的组件匹配。我已经成功找到对应的Action脚本组件,但没法访问里面的变量……
// 遍历当前对象的所有组件 var thisElComps = thisEl.GetComponents<Component>(); for (var i = 0; i < thisElComps.Length; i++) { var thisComp = thisElComps[i].GetType(); // 如果组件匹配当前选中的操作 if (activeVerb.name == thisComp.ToString()) { print("找到组件"); // 这里需要访问组件内的设置! // if(thisComp.myVar){}; // 未找到匹配的选中操作组件 } else { print("未找到组件"); } }
“找到组件”和“未找到组件”能正常打印,但我试了各种方法都没法访问组件里的变量:/ 抱歉这是新手问题,我刚接触C#,之前用的是其他语言,感谢帮忙。
更新1:组件脚本示例
为了方便说明,附上附加的组件脚本示例:
public class ActionClassName: MonoBehaviour { public string myVar; }
用thisComp.myVar;会报错:“不存在myVar的定义”。执行print(thisElComps[i] is Component);返回true。
更新2:GetType调用问题
typeName="myAction"; var myComp=thisEl.GetComponent("myAction");
这段代码能成功找到组件!但换成下面的代码就报错:“type cannot be null”(类型不能为空)
var myComp=thisEl.GetComponent(System.Type.GetType(typeName));
1. 访问组件变量的正确姿势
你现在的核心问题是:thisComp是类型(Type),不是组件的实例对象,自然没法直接访问变量。得用组件实例来操作,而非它的类型信息。
方法一:强制类型转换(已知具体Action类时)
如果明确目标组件的类型,直接把组件实例转成对应类型即可:
if (activeVerb.name == thisComp.ToString()) { print("找到组件"); // 将组件实例转换为目标Action类 var actionComp = thisElComps[i] as ActionClassName; if (actionComp != null) { // 现在可以正常访问变量 print(actionComp.myVar); } }
方法二:动态类型(多Action类通用)
如果有多个不同的Action类,且都包含myVar这类公共变量,可以用dynamic跳过编译时类型检查:
if (activeVerb.name == thisComp.ToString()) { print("找到组件"); dynamic actionComp = thisElComps[i]; // 直接访问变量,注意:若组件无此变量会触发运行时错误 print(actionComp.myVar); }
2. 解决Type.GetType(typeName)返回null的问题
System.Type.GetType需要完整类型名(包含命名空间),如果你的myAction类在自定义命名空间下,比如Game.Actions,就要写成"Game.Actions.myAction"。
另外,Unity脚本默认编译在Assembly-CSharp程序集里,也可以直接指定程序集来获取类型:
typeName = "myAction"; var actionType = System.Type.GetType($"{typeName}, Assembly-CSharp"); if (actionType != null) { var myComp = thisEl.GetComponent(actionType); // 同样用dynamic访问变量 dynamic compInstance = myComp; print(compInstance.myVar); }
3. 更简洁的组件遍历方式
其实不用遍历所有Component,直接获取所有MonoBehaviour(你的Action脚本都继承自它)再筛选更高效:
var allActions = thisEl.GetComponents<MonoBehaviour>(); foreach (var action in allActions) { // 用GetType().Name代替ToString(),避免命名空间干扰 if (action.GetType().Name == activeVerb.name) { dynamic actionComp = action; print(actionComp.myVar); break; // 找到目标后直接跳出循环 } }
内容的提问来源于stack exchange,提问作者makeITwork

