2017-05-20 91 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); 
     } 
    } 
} 

正如你可以看到这一切仍然工作通过方法传递值只是必须有一个“中间人”中继信息。但是,这只是正常

感谢大家的反馈,我希望这可以帮助别人