我遇到的问题是丢弃的物品,我拿起弹药加枪。
使用所有方法和变量构建Gun类。 构建了一个源自Gun类的Rifle类 步枪完美无问题
我现在正在添加一个" PickUp"系统中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;
}
我得到的对象引用未设置为实例
步枪脚本位于游戏层次结构的步枪上,因此它应该找到它。 有没有人看错了什么?
这是完整的Gun脚本
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 :(得分:3)
FindObjectOfType可能返回null有三个原因:
让我们说要查找的脚本名称为Rifle
:
FindObjectOfType<Rifle>()
正在返回null
。
1 。附加Rifle
脚本的GameObject处于非活动状态。您必须确保GameObject处于活动状态。
2 。步枪根本没有附加到任何GameObject。确保Rifle脚本附加到GameObject。。
如果启用或禁用脚本并不重要,只要它附加的GameObject处于活动状态,它就应该找到它。见#1 。
3 。加载新场景时:
使用SceneManager.LoadScene
等功能触发场景加载时
并且Application.LoadLevel
,FindObjectOfType
在加载完成后才能找到任何内容。
请参阅here了解如何检查场景何时加载。
如果您仍然遇到问题,那么只需找到GameObject,然后从中获取Rifle
组件即可。假设GameObject的名称也是&#34; Rifle&#34; 。
GameObject.Find("Rifle").GetComponent<Rifle>();
答案 1 :(得分:0)
我想出了如何为遇到类似问题的人解决这个问题。 问题是当敌人放弃该项目时,Awake()方法运行。当它运行时,枪在场景中处于非活动状态,因此FindObjectOfType没有找到引用脚本,因为如上所述,它必须在要找到的场景中处于活动状态。
所以我做的是创建一个名为EnemyDrops的Holder脚本,这个脚本调用了枪的findobjectoftypes。这样就可以在最初的游戏开始时完成调用。
然后我更改了拾取器以找到EnemyDrops脚本(在空的游戏对象上)并将调用发送给它。
EnemyDrops Script
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);
}
}
}
正如你所看到的那样,通过这些方法传递价值仍然只需要一个中间人&#34;转发信息。但这很好用
感谢大家的反馈,我希望这有助于某人