2017-05-20 88 views
1

我遇到的問題是丟棄的物品,我拿起彈藥添加到槍中。FindObjectOfType返回null

構建了一個包含所有方法和變量的Gun類。 建從槍類派生的類步槍的 步槍完美的作品沒有任何問題

我現在加入了「皮卡」系統的敵人在哪裏的X量下降皮卡。

這是關於該項目的腳本拿起

public class AddARAmmo : MonoBehaviour 
{ 
    private Rifle rifle; 
    private void Awake() 
    { 
     rifle = FindObjectOfType<Rifle>(); 
    } 
    private void OnTriggerEnter(Collider other) 
    { 
     if (other.tag == string.Format("Player")) 
     { 
      rifle.AddAmmo(30); 
      Destroy(gameObject); 
     } 

    } 
} 

步槍和手槍腳本是一種長,但這裏是從槍的基類相關的東西是公共抽象類..... 。

public int bulletsInStock; 
public void AddAmmo(int ammoToAdd) 
{ 
    bulletsInStock += ammoToAdd; 
    UpdateAmmo();// updates on screen Ammo 
} 
...... 
在步槍類

public override void Modifiers() // This is where the guns starts are stored 
{ 
    bulletSpeed = 2777f; 
    bulletsInStock = 200; 
    bulletsInMag = 30; 
    bulletPoolSize = 40; 
    desiredRPS = 15; 
    muzzleFlashPoolSize = 10; 
} 

然後我得到一個對象引用未設置實例

步槍腳本在遊戲層次結構的步槍上,因此它應該找到它。 有沒有人看到任何錯誤?

以下是完整的槍腳本

public abstract class Gun : MonoBehaviour 
{ 
    [SerializeField] protected GameObject muzzleFlash;// spawns on barrelEnd 
    [SerializeField] protected Transform muzzleFlashFolder; 
    [SerializeField] protected Transform bulletFolder;// is the parent of bullets 
    [SerializeField] protected Transform barrelEnd;// Gameobject at the end of barrel 
    [SerializeField] protected Rigidbody bullet; // The bullet Prefab 
    [SerializeField] protected Text ammo; // OSD 
    [SerializeField] protected Text weaponType; // OSD 
    [HideInInspector] protected float bulletSpeed; 
    [HideInInspector] public int bulletsInStock; 
    [HideInInspector] protected int bulletsInMag; 
    [HideInInspector] protected float desiredRPS;// Rounds Per Second 
    [HideInInspector] protected List<Rigidbody> poolOfBullets; // Make pool for bullets 
    [HideInInspector] protected int bulletPoolSize; // The size off the buletpool 10 works really well 
    [HideInInspector] protected List<GameObject> muzzleFlashPool;// pool for muzzleflash 
    [HideInInspector] protected int muzzleFlashPoolSize; // size of the muzzle pool 
    [HideInInspector] protected int bulletsLeft; // In mag 
    [HideInInspector] protected bool isReloading = false; 
    [HideInInspector] protected float timeLeft;// for fire speed 
    [HideInInspector] protected float fireSpeedTimer; 
    [HideInInspector] protected Weapons weaponsScript; 
    [HideInInspector] protected PlayerController playerController; 
    protected void FixedUpdateStuff() 
    { 
     if (playerController.canMove && Input.GetAxisRaw(string.Format("Fire1")) > 0) 
     { 
      FireSpeedControl();// call the fire timer controller 
     } 
     if (playerController.canMove && Input.GetAxisRaw(string.Format("Fire1")) == 0) 
     { 
      timeLeft = 0f; 
     } 
     if (playerController.canMove && Input.GetKeyDown(KeyCode.R) && !isReloading) 
     { 
      Reload(); 
     } 
     UpdateAmmoOnInput(); 
    } 
    protected void UpdateStuff() 
    { 
     if (gameObject.activeInHierarchy)// when a gun become active it updates OSD 
     { 
      UpdateWeaponType();// With its Name 
     } 
    } 
    protected void RPSFinder()// finds the Rounds Per Second the gun will fire 
    { 
     fireSpeedTimer = (100/desiredRPS)/100; 
     timeLeft = fireSpeedTimer; 
    } 

    protected void Fire()// Instatiates a clone of the desired bullet and fires it at bulletSpeed 
    { 
     if (!Empty()) 
     { 
      Rigidbody bulletClones = GetPooledBullet(); 
      if (bulletClones != null) 
      { 

bulletClones.transform.SetPositionAndRotation(barrelEnd.position, barrelEnd.rotation); 
       bulletClones.gameObject.SetActive(true); 
      } 
      GameObject muzzleFlashClone = GetMuzzleFlash(); 
      if (muzzleFlashClone != null) 
      { 
       muzzleFlashClone.transform.position = barrelEnd.position; 
       muzzleFlashClone.gameObject.SetActive(true); 
      } 
      bulletClones.AddForce(-bulletClones.transform.up * bulletSpeed * .304f); //add the force in FPS * .304 = MPS 
      bulletsLeft--;// the holder to know how many bullets are left in the magazine 
      isReloading = false;// Gun cannot reload unless it has been fired 
      UpdateAmmo();// Updates the on screen ammo count and the stock usage 
      return; 
     } 
    } 

    protected void Reload() 
    {// this removes full magazine from the stock and the stock can still go negitive FIX FIX FIX FIX FIX FIX FIX 
     if (bulletsInStock > 0) 
     { 
      isReloading = true; 
      bulletsInStock -= bulletsInMag; 
      bulletsLeft = bulletsInMag; 
      UpdateAmmo(); 
     } 
    } 

    protected bool Empty()// Checks the magazine to see if there are bullets in it 
    { 
     if (bulletsLeft == 0) 
      return true; 
     else 
      return false; 
} 

    protected void FireSpeedControl()// controls the RPS fired by the gun Controled by Update() Input 
    { 
     if (timeLeft > 0f) 
     { 
      timeLeft -= Time.deltaTime; 
     } 
     else if (timeLeft <= 0f) 
     { 
      Fire(); 
      timeLeft = fireSpeedTimer; 
     } 
    } 

    protected Rigidbody GetPooledBullet()// retrieve a preInstatiated bullet from the pool to use when shooting 
    { 
     for (int i = 0; i < poolOfBullets.Count; i++) 
     { 
      if (!poolOfBullets[i].gameObject.activeInHierarchy) 
      { 
       return poolOfBullets[i]; 
      } 
     } 
     return null; 
    } 

    protected GameObject GetMuzzleFlash() 
    { 
     for (int i = 0; i < muzzleFlashPool.Count; i++) 
     { 
      if (!muzzleFlashPool[i].gameObject.activeInHierarchy) 
      { 
       return muzzleFlashPool[i]; 
      } 
     } 
     return null; 
    } 

    protected void UpdateAmmo()// Update the on screen ammo information 
    { 
     ammo.text = bulletsLeft + string.Format(" : ") + bulletsInStock; 
    } 

    protected abstract void UpdateWeaponType(); 

    protected void UpdateAmmoOnInput() 
    { 
     if (weaponsScript.updateAmmo) 
     { 
      UpdateAmmo(); 
      weaponsScript.updateAmmo = false; 
     } 
    } 


    public abstract void Modifiers(); 

    protected void StartStuff() 
    { 
     Modifiers();// Call first to store indvidual gun stats 
     playerController = FindObjectOfType<PlayerController>(); 
     weaponsScript = FindObjectOfType<Weapons>(); 
     poolOfBullets = new List<Rigidbody>(); 
     for (int i = 0; i < bulletPoolSize; i++) 
     { 
      Rigidbody bulletClone = (Rigidbody)Instantiate(bullet); 
      bulletClone.gameObject.SetActive(false);// Builds the Inspector list 
      poolOfBullets.Add(bulletClone); //and populates the elements with clones 
      bulletClone.transform.parent = bulletFolder.transform; 
     } 
     muzzleFlashPool = new List<GameObject>(); 
     for (int i = 0; i < muzzleFlashPoolSize; i++) 
     { 
      GameObject muzzleFlashClone = (GameObject)Instantiate(muzzleFlash); 
      muzzleFlashClone.gameObject.SetActive(false); 
      muzzleFlashPool.Add(muzzleFlashClone); 
      muzzleFlashClone.transform.parent = muzzleFlashFolder.transform; 
     } 
      bulletsLeft = bulletsInMag; 
      ammo.text = string.Format(" 0 : 0 "); 
      RPSFinder();// Run last to set the RPS of the gun 
     } 
     public void AddAmmo(int ammoToAdd) 
     { 
      bulletsInStock += ammoToAdd; 
      UpdateAmmo(); 
     } 

    } 
} 

,這裏是全步槍腳本

public class Rifle : Gun 
{ 
    //All variables are stored in the "Gun" Script 
    //Copy this onto guns 

    void Start() 
    { 
     StartStuff(); 
    } 
    private void FixedUpdate() 
    { 
     FixedUpdateStuff(); 
    } 

    void Update() 
    { 
     UpdateStuff(); 
    } 

    public override void Modifiers() // This is where the guns starts are stored 
    { 
     bulletSpeed = 2777f; 
     bulletsInStock = 200; 
     bulletsInMag = 30; 
     bulletPoolSize = 40; 
     desiredRPS = 15; 
     muzzleFlashPoolSize = 10; 
    } 

    protected override void UpdateWeaponType() 
    { 
     weaponType.text = string.Format("Assault Rifle"); 
    } 


} 
+0

,你能否告訴我們'Rifle'腳本? – Programmer

+1

_ Where Where is thrown? – Abion47

+0

rifle.AddAmmo(30);在AddARAmmo腳本中 – Melsy

回答

3

有三個原因FindObjectOfType可能返回null:

假設腳本名稱找到是Rifle

And FindObjectOfType<Rifle>()正在返回null

。附加的GameObject Rifle腳本處於非活動狀態。您必須確保GameObject處於活動狀態。 enter image description here

。步槍並沒有附加到任何遊戲對象上。確保Rifle腳本附加到GameObject。 enter image description here

腳本啓用或禁用無關緊要,只要它附加的GameObject處於活動狀態,就應該找到它。見#1

。當加載新的場景:

當你觸發場景加載與功能,如SceneManager.LoadSceneApplication.LoadLevelFindObjectOfType將無法​​找到任何東西,直到場景加載完成它。

請參閱here瞭解如何檢查場景何時完成加載。


如果您仍然有問題,你不應該,只是覺得有個遊戲對象從中得到Rifle組件。假設遊戲對象的名稱也是「步槍」

GameObject.Find("Rifle").GetComponent<Rifle>(); 
+0

遊戲對象在場景加載時處於非活動狀態。但是當我調用引用時,對象可以處於活動狀態或非活動狀態,並且它將爲空。但我會做一些測試,考慮到這一點 – Melsy

+0

我有一個部分,在發現禁用之前將槍設置爲非活動狀態,現在它可以工作。有時候不得不回到基礎。 – Melsy

+0

是的,非活動是這種情況發生的原因。很高興你發現了這個問題。 – Programmer

0

我想出瞭如何解決這個問題,任何人都有類似的問題。 問題出在敵人放棄物品時,Awake()方法運行。當它運行時,槍在場景中處於非活動狀態,所以FindObjectOfType找不到參考腳本,因爲如上所述,它必須在要找到的場景中處於活動狀態。

所以我做的是創建一個Holder腳本,我叫做EnemyDrops,這個腳本調用槍的findobjectoftypes。這種方式在最初的遊戲開始時完成。

然後我改變皮卡來找到EnemyDrops腳本(這是在空的遊戲對象上)並將呼叫發送給它。

EnemyDrops腳本

private Handgun handgun; 

private void Awake() 
{ 
    handgun = FindObjectOfType<Handgun>(); 
} 

public void AddHandgunAmmo(int x) 
{ 
    handgun.AddAmmo(x); 
} 

和新的皮卡腳本

public class AddHandgunAmmo : MonoBehaviour 
{ 
    private EnemyDrops enemyDrops; 
    private void Awake() 
    { 
     enemyDrops = FindObjectOfType<EnemyDrops>(); 
    } 

    private void OnTriggerEnter(Collider other) 
    { 
     if (other.tag == string.Format("Player")) 
     { 
      enemyDrops.AddHandgunAmmo(50); 
      Destroy(gameObject); 
     } 
    } 
} 

正如你可以看到這一切仍然工作通過方法傳遞值只是必須有一個「中間人」中繼信息。但是,這只是正常

感謝大家的反饋,我希望這可以幫助別人