[英]Bullet not getting Instantiated when destroyed - Unity2D
我是使用統一的新手,我仍在學習 C#。 因此,如果下面提到的問題看起來有點奇怪或容易解決,請多多包涵。
我正在創建一個項目以嘗試從炮塔發射子彈,我在我的子彈腳本中包含了一個 function,它會在子彈越過某些邊界后摧毀子彈,並在我的 bulletSpawner 腳本中包含一個 function 來實例化子彈,如果它被摧毀了。 出於某種原因,每當我播放和射擊子彈並且它越過邊界時,它都不會被克隆
這是子彈腳本;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Bullet : MonoBehaviour
{
[SerializeField]
private float Power = 50f;
private Rigidbody2D myBody;
private SpriteRenderer sr;
private float posX;
private float posY;
private void Awake()
{
myBody = GetComponent<Rigidbody2D>();
sr = GetComponent<SpriteRenderer>();
}
void Update()
{
Shoot();
destroyBullet();
}
void Shoot()
{
if (Input.GetKeyDown(KeyCode.Space))
{
myBody.AddForce(new Vector2(Power, Power - myBody.gravityScale),
ForceMode2D.Impulse);
}
}
void destroyBullet()
{
posX = transform.position.x;
posY = transform.position.y;
if (posX > 100 || posX < -100 || posY > 100 || posY < -100)
Destroy(gameObject);
}
}//class
這是 BulletSpawner 腳本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BulletSpawner : MonoBehaviour
{
public Transform bullet;
void Update()
{
StartCoroutine(SpawnBullet());
}
IEnumerator SpawnBullet()
{
while (!GameObject.FindWithTag("Bullet"))
{
yield return new WaitForSeconds(3);
Instantiate(bullet);
}//while
}//Ienum
}//class
注意:我已將 Bullet Prefab 附加到檢查器面板中的項目符號上
每當子彈超出范圍或被破壞時,我都會收到此錯誤:
MissingReferenceException:“Transform”類型的 object 已被破壞,但您仍在嘗試訪問它。
我知道它已被破壞,但我想找到一種方法來訪問它,以便它可以克隆子彈(可以再次發射,破壞等等......)
請告知我可以做些什么來修復此代碼或任何替代方法,以防止將來發生此類錯誤。 對於任何反饋,我們都表示感謝:)...
提前致謝!
因此,如前所述,主要問題是您使用原始場景實例作為Instantiate
的原始bullet
,但隨后銷毀了該原始項目。
如果您要使用銷毀和實例化,您寧願將預制資產作為bullet
原始資產。
然而,在 MickyD 提到之后:無論如何,你總是一次只有一顆子彈,所以你可能根本不需要摧毀它。 只需重用相同的項目符號實例。
然后關於Update
中的射擊和你的協程,這是我寧願做的
子彈本身根本不做任何事情,而只是被動的。
然后做
public class BulletSpawner : MonoBehaviour
{
// Now again the one from the Scene!
public Rigidbody2D bullet;
// Yes if Start is IEnumerator it is automatically run as Coroutine by Unity
IEnumerator Start ()
{
// Disable the Rigidbody of the bullet so it doesn't fall down
bullet.isKinematic = true;
// Huh?! This is okey in an IEnumerator as long as you yield inside
while(true)
{
// wait until Space is pressed
yield return new WaitUntil (() => Input.GetKeyDown(KeyCode.Space));
// enable the Rigidbody
bullet.isKinematic = false;
// shoot the bullet
bullet.AddForce(new Vector2(Power, Power - bullet.gravityScale), ForceMode2D.Impulse);
// Now wait until it is out of bounds
//TODO: .. or it hits something ;)
yield return new WaitUntil (() => bullet.position.magnitude > 100f /*TODO || hasHitSomething */);
// Then reset it's movement
bullet.velocity = Vector2.zero;
bullet.angularVelocity = 0;
// Reset position
bullet.position = Vector2.zero;
bullet.rotation = 0;
bullet.transform.position = Vector2.zero;
bullet.transform.rotation = Quaternion.identity;
// disable the Rigidbody for the next iteration
bullet.isKinematic = true;
// Disable the entire object
bullet.gameObject.SetActive(false);
// Wait for the cooldown
yield return new WaitForSeconds (3);
// enable the object (but not yet the Rigidbody)
bullet.gameObject.SetActive(true);
}
}
}
為了檢查hasHitSomething
我會在子彈上放一個專用組件,例如
public class Bullet : MonoBehaviour
{
public bool hasCollided;
private void OnCollisionEnter2D(Collision2D collision)
{
hasCollided = true;
}
}
廣告然后
yield return new WaitUntil (() => bullet.position.magnitude > 100f || bullet.GetComponent<Bullet>().hasCollided);
// reset the flag
bullet.GetComponent<Bullet>().hasCollided = false;
當然,您通常應該存儲Bullet
引用而不是重復使用GetComponent
。
這個答案只是對 derHugo 上面寫的代碼稍作修正,
這是編輯后的版本,更改在下面的**中標記...
public class BulletSpawner : MonoBehaviour
{
public Rigidbody2D bullet;
public Transform bulletPos;//change**
[SerializeField]
private float Power = 50f;
void Start()
{
StartCoroutine(SpawnBullets());
}
void Update() {
}
IEnumerator SpawnBullets()
{
bullet.simulated = false;
while (true)
{
yield return new WaitUntil(() => Input.GetKeyDown(KeyCode.Space));
bullet.simulated = true;
bullet.AddForce(new Vector2(Power, Power - bullet.gravityScale),
ForceMode2D.Impulse);
yield return new WaitUntil(() => bullet.position.magnitude > 100f
|| hasHitSomething */);
bullet.velocity = Vector2.zero;
bullet.angularVelocity = 0;
bulletPos.position = Vector2.zero;//change**
bullet.rotation = 0;
bullet.simulated = false;
bullet.gameObject.SetActive(false);
yield return new WaitForSeconds(3);
bullet.gameObject.SetActive(true);
}
}
}
我已經完成了兩項更改,因為當子彈被發射並出界時,子彈的 position 不會 go 回到原來的 position (因為這是代碼,子彈被聲明為)我的 Bullet object 的剛體(這意味着剛體將把它的 position 恢復到原點,而不是 Bullet object itelf 的剛體...聲明組件沒有意義。項目符號 object 並將項目符號更改為項目符號位置
bullet.position = Vector2.zero;
這是為了確保子彈 object 而不是子彈剛體將其 position 恢復到原點。
不要忘記在bulletSpawner中把子彈的transform組件附加到腳本上,這樣就可以順利運行了……
只是想包括這個,以免再次犯同樣的錯誤。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.