我有一个名为Weapon的基类和几个派生类,例如Weapon_Rifle,Weapon_Pistol等。
在另一个类中,我需要引用游戏对象中存在的任何派生类武器。在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();
}
}
麻烦当然是我不能为SCRIPT_I_WANT_TO_REFERENCE使用像Object这样的虚拟类型,因为编译器抱怨我尝试访问该脚本的方法,如ShootWeapon()。
任何方式都可以做到这一点?
非常感谢。
答案 0 :(得分:2)
您可以尝试使用界面。像IWeapon这样的东西,你的定义就是ShootWeapon。
interface IWeapon
{
void ShootWeapon();
}
然后,您只需在类定义的标题中实现该接口。
public class Weapon_Rifle : MonoBehaviour, IWeapon
{
void ShootWeapon()
{
...
}
}
这样你就可以在“是一种”关系中引用具有界面的步枪。您还需要定义从两个类访问的任何其他方法,然后(必须)在类中实现。你可以使用的类型是IWeapon来引用这两个类。
答案 1 :(得分:0)
您可以使用反射来做您想做的事情:
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();