使用字符串 Unity 从游戏对象获取脚本
Getting a script from a gameobject using a string Unity
我正在为我的 FPS 游戏开发一个简单的武器控制器,但在尝试使其动态化时遇到了一个问题。当玩家拿起武器时,我想要发生的是将武器统计数据和效果设置为默认值。为此,每种武器都有一个脚本
weapon.name + "Stats"
但我在引用上述脚本时遇到问题。现在,这就是我的代码:
string weaponScriptName = weapon.name + "Stats";
weapon.GetComponent<weaponScriptName>().UseWeapon();
其中weapon
代表当前装备的武器gameobject
。显然,这是行不通的,我在 Unity 帮助页面上找到的各种实现只会导致更多错误。我该怎么做才能解决这个问题?
谢谢。
如果我没记错的话,你想做类似 GetComponent<"Transform">()
的事情吗?
如果是这样,您应该 GetComponent("Transform");
而不是
GetComponent
有多个重载。
有你所指的generic版本-最常用的
T GetComponent<T>()
只能与编译时常量类型参数一起使用,例如
var renderer = GetComponent<Renderer>();
有一个使用动态Type
Component GetComponent (Type type)
喜欢
// Just an example, there are many ways of getting a type
var type = typeof(Renderer);
var renderer = (Renderer) GetComponent(type);
终于有人拿了 string
Component GetComponent (string typeName);
喜欢
// Again just an example, there are many ways of getting type names
// Especially when dealing with multiple assemblies you might even have to use the AssemblyQualifiedName
var renderer = (Renderer) GetComponent("Renderer");
请注意,对于任何动态版本,您都必须 键入 cast 或者如果仅具有通用 Component
引用就足够了,您可以使用它当然。
但是,如前所述,如果可能的话根本不要使用string
版本!
它总是很慢而且容易出错。而是使用例如一些共同的基础 class 或 interface,或使用枚举或 Dictionary
来决定对哪个状态做什么。
所以我宁愿有例如
public interface IWeapon
{
void UseWeapon();
}
然后你的每一个不同的武器都可以实现这个接口
public class WeaponA : MonoBehaviour, IWeapon
{
public void UseWeapon ()
{
Debug.Log("Used Weapon A");
}
}
public class WeaponB : MonoBehaviour, IWeapon
{
public void UseWeapon ()
{
Debug.Log("Used Weapon B");
}
}
而您的代码将只是
var weapon = someObject.GetComponent<IWeapon>(). UseWeapon();
或者如果你的武器都有一些共同的实现,比如拾取等,而不是有一个共同的基础 class
public abstract class BaseWeapon : MonoBehaviour
{
// Everything that all weapons share as behavior and properties
// every subclass HAS TO implement and override this method
public abstract void UseWeapon ();
// Alternatively if there even is some common behavior
// subclasses CAN but don't have to override this
//public virtual void UseWeapon ()
//{
// // Implementation that is the default behavior
//}
}
然后
public class WeaponA : BaseWeapon
{
public override void UseWeapon ()
{
Debug.Log("Used Weapon A");
// If using virtual before then this class IGNORES and fully overwrites the default implementation
}
}
public class WeaponB : BaseWeapon
{
public override void UseWeapon ()
{
// If using virtual and you WANT the default behavior then add
//base.UseWeapon();
Debug.Log("Used Weapon B");
}
}
而您的代码将只是
var weapon = someObject.GetComponent<BaseWeapon>(). UseWeapon();
我正在为我的 FPS 游戏开发一个简单的武器控制器,但在尝试使其动态化时遇到了一个问题。当玩家拿起武器时,我想要发生的是将武器统计数据和效果设置为默认值。为此,每种武器都有一个脚本
weapon.name + "Stats"
但我在引用上述脚本时遇到问题。现在,这就是我的代码:
string weaponScriptName = weapon.name + "Stats";
weapon.GetComponent<weaponScriptName>().UseWeapon();
其中weapon
代表当前装备的武器gameobject
。显然,这是行不通的,我在 Unity 帮助页面上找到的各种实现只会导致更多错误。我该怎么做才能解决这个问题?
谢谢。
如果我没记错的话,你想做类似 GetComponent<"Transform">()
的事情吗?
如果是这样,您应该 GetComponent("Transform");
而不是
GetComponent
有多个重载。
有你所指的generic版本-最常用的
T GetComponent<T>()
只能与编译时常量类型参数一起使用,例如
var renderer = GetComponent<Renderer>();
有一个使用动态
Type
Component GetComponent (Type type)
喜欢
// Just an example, there are many ways of getting a type var type = typeof(Renderer); var renderer = (Renderer) GetComponent(type);
终于有人拿了
string
Component GetComponent (string typeName);
喜欢
// Again just an example, there are many ways of getting type names // Especially when dealing with multiple assemblies you might even have to use the AssemblyQualifiedName var renderer = (Renderer) GetComponent("Renderer");
请注意,对于任何动态版本,您都必须 键入 cast 或者如果仅具有通用 Component
引用就足够了,您可以使用它当然。
但是,如前所述,如果可能的话根本不要使用string
版本!
它总是很慢而且容易出错。而是使用例如一些共同的基础 class 或 interface,或使用枚举或 Dictionary
来决定对哪个状态做什么。
所以我宁愿有例如
public interface IWeapon
{
void UseWeapon();
}
然后你的每一个不同的武器都可以实现这个接口
public class WeaponA : MonoBehaviour, IWeapon
{
public void UseWeapon ()
{
Debug.Log("Used Weapon A");
}
}
public class WeaponB : MonoBehaviour, IWeapon
{
public void UseWeapon ()
{
Debug.Log("Used Weapon B");
}
}
而您的代码将只是
var weapon = someObject.GetComponent<IWeapon>(). UseWeapon();
或者如果你的武器都有一些共同的实现,比如拾取等,而不是有一个共同的基础 class
public abstract class BaseWeapon : MonoBehaviour
{
// Everything that all weapons share as behavior and properties
// every subclass HAS TO implement and override this method
public abstract void UseWeapon ();
// Alternatively if there even is some common behavior
// subclasses CAN but don't have to override this
//public virtual void UseWeapon ()
//{
// // Implementation that is the default behavior
//}
}
然后
public class WeaponA : BaseWeapon
{
public override void UseWeapon ()
{
Debug.Log("Used Weapon A");
// If using virtual before then this class IGNORES and fully overwrites the default implementation
}
}
public class WeaponB : BaseWeapon
{
public override void UseWeapon ()
{
// If using virtual and you WANT the default behavior then add
//base.UseWeapon();
Debug.Log("Used Weapon B");
}
}
而您的代码将只是
var weapon = someObject.GetComponent<BaseWeapon>(). UseWeapon();