繁体   English   中英

Unity游戏引擎:获取对动态添加脚本的引用

[英]Unity game engine: get reference to dynamically added script

我有一个名为Weapon的基类和一些派生类,例如Weapon_Rifle,Weapon_Pistol等。

在另一类中,我需要引用有问题的GameObject上存在的任何武器衍生类。 在pseduocode中,我想做的是:

public class OtherClass : MonoBehaviour
{

     public string weaponType;
     public SCRIPT_I_WANT_TO_REFERENCE;

     void Awake(){
          if(weaponType =="Rifle"){
               SCRIPT_I_WANT_TO_REFERENCE = GetComponent<Weapon_Rifle>();
          } else {
              SCRIPT_I_WANT_TO_REFERENCE = GetComponent<Weapon_Pistol>(); // etc etc
          }
     }

     void DoStuff(){
          SCRIPT_I_WANT_TO_REFERENCE.ShootWeapon();
     }
}

麻烦当然是我不能将像Object这样的伪类型用于SCRIPT_I_WANT_TO_REFERENCE,因为编译器抱怨我试图在何处访问该脚本方法(如ShootWeapon())。

有什么办法可以做到吗?

非常感谢。

您可以尝试使用界面。 像IWeapon这样的东西,在其中定义了ShootWeapon。

interface IWeapon
{
    void ShootWeapon();
}

然后,您只需在类定义的标头中实现接口。

public class Weapon_Rifle : MonoBehaviour, IWeapon
{
    void ShootWeapon()
    {
       ...
    }
}

这样,您可以使用“是一个”关系中的界面来引用步枪。 您还可以定义需要从这两个类访问的任何其他方法,然后(必须)在这些类中实现。 您可以使用的类型是IWeapon来引用这两个类。

您可以使用反射来做您想做的事情:

var method = typeof(GameObject).GetMethod("GetComponent", new Type[] {});
var specific = method.MakeGenericMethod(typeof(Rifle));
var instance = specific.Invoke(shooter, null) as IWeapon;

例如。

using UnityEngine;
using System;
using System.Reflection;
using NUnit.Framework;

public interface IWeapon
{
    void ShootAt(GameObject target);
}

public class Rifle : MonoBehaviour, IWeapon
{
    public void ShootAt(GameObject target)
    {
        Debug.Log("Rifle");
    }
}

public class Shotgun : MonoBehaviour, IWeapon
{
    public void ShootAt(GameObject target)
    {
        Debug.Log("Shotgun");
    }
}

public class WeaponTests
{
    private GameObject Shooter()
    {
        var foo = new GameObject();
        foo.AddComponent<Shotgun>();
        foo.AddComponent<Rifle>();
        return foo;
    }

    private MethodInfo method = null;
    private IWeapon GetWeaponByName(GameObject shooter, string name)
    {
        if (method == null)
        {
            // This is slow, cache the result
            method = typeof(GameObject).GetMethod("GetComponent", new Type[] {});
        }
        if (name == "Rifle")
        {
            MethodInfo specific = method.MakeGenericMethod(typeof(Rifle));
            return specific.Invoke(shooter, null) as IWeapon;
        }
        else if (name == "Shotgun")
        {
            MethodInfo specific = method.MakeGenericMethod(typeof(Shotgun));
            return specific.Invoke(shooter, null) as IWeapon;
        }
        return null;
    }

    [Test]
    public void TestGetWeaponByName()
    {
        var target = new GameObject();
        var fixture = Shooter();
        IWeapon weapon;

        weapon = GetWeaponByName(fixture, "Rifle");
        Assert.True(weapon != null);
        weapon.ShootAt(target);

        weapon = GetWeaponByName(fixture, "Shotgun");
        Assert.True(weapon != null);
        weapon.ShootAt(target);

        weapon = GetWeaponByName(fixture, "Laster");
        Assert.True(weapon == null);
    }
}

还请注意,不需要IWeapon 您可以轻松地直接加载特定实例:

MethodInfo specific = method.MakeGenericMethod(typeof(Rifle));
var rifle = specific.Invoke(shooter, null) as Rifle;
rifle.RifleSpecificThing();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM