2016-04-03 132 views
0

我有一個名爲Weapon的基類和幾個派生類,例如Weapon_Rifle,Weapon_Pistol等。Unity遊戲引擎:獲取動態添加腳本的參考

在另一個類中,我需要引用有關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(); 
    } 
} 

麻煩是當然的,因爲編譯器抱怨,我嘗試在腳本一樣的訪問方法我不能使用虛擬型狀物品爲SCRIPT_I_WANT_TO_REFERENCE ShootWeapon()。

任何方式可以做到這一點?

非常感謝。

回答

2

你可以嘗試使用一個接口。就像IWeapon那裏你有ShootWeapon的定義。

interface IWeapon 
{ 
    void ShootWeapon(); 
} 

然後,您只需在類定義的頭中實現接口。

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

這樣你就可以用「is a」關係引用Rifle接口了。您需要從兩個類訪問的任何其他方法也可以定義,然後(必須)在類中實現。你可以使用的類型是IWeapon來引用這兩個類。

+0

感謝您的支持。由於IWeapon不能從Monobehaviour派生出來,因此我需要使用Monobehaviour方法來如何使用Weapon作爲基類?我會像公共類Weapon:MonoBehaviour,IWeapon和派生類像public class Weapon_Rifle:Weapon? – Absinthe

+0

實際上,在Unity中,一個類不能從其他兩個類派生出來,但是您可以實現儘可能多的接口,以及從MonoBehaviour派生的接口。這兩個武器類仍然繼承MonoBehaviour,以便仍然是組件,所以它們都是Weapon_X:MonoBehaviour,IWeapon。如果你願意的話,你可以在Unity的網站[這裏](https://unity3d.com/learn/tutorials/modules/intermediate/scripting/interfaces)查看關於界面的介紹。 – cjmarsh

+0

謝謝,所以我會設置類似武器類型的狀態機 – Absinthe

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