使用Unity字符串从游戏对象中获取脚本



我正在为我的FPS游戏制作一个简单的武器控制器,并在尝试使其动态时遇到了一个问题。当玩家拿起武器时,我想让武器的属性和效果设置为默认值。为此,每个武器都有一个脚本

weapon.name + "Stats"

但我有问题引用说的脚本。现在,我的代码是这样的:

string weaponScriptName = weapon.name + "Stats";
weapon.GetComponent<weaponScriptName>().UseWeapon();

其中weapon表示当前装备武器的gameobject。显然,这不起作用,我在Unity帮助页面上发现的各种实现只会导致更多错误。我能做些什么来解决这个问题?

谢谢。

GetComponent有多个过载

  • 这是你提到的通用版本-最常用的一个

    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");
    

请注意,对于任何动态版本,您都必须对进行类型转换或者如果只有一个通用的Component引用就足够了,你当然可以使用它。


然而,如果可能的话,根本不要使用string版本!

它总是很慢而且容易出错。而应该使用一些公共基类或接口,或者使用enum或Dictionary来决定在哪个状态下做什么。

所以我宁愿有e.g.

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();

或者如果你的武器都有一些共同的实现,比如拾取等等,而不是有一个共同的基类

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();

如果我得到了正确的,你想做一些像GetComponent<"Transform">()?如果是这样,你应该用GetComponent("Transform");来代替