使用对象池和Coroutines在几秒钟后禁用游戏对象

发布于 2025-02-11 18:05:22 字数 2537 浏览 0 评论 0原文

我正在开发一个统一的简单VR射击游戏,我将对象集合用于子弹(在这里激光) 这是Objectpool脚本,在这里,我会在开始()方法中列出子弹列表并禁用它们。

public class ObjectPool : MonoBehaviour   
{
    public static ObjectPool instance;
    private List<GameObject> pooledObject = new List<GameObject>();
    private int amountToPool = 20;
    [SerializeField] private GameObject laserPrefab;

  

private void Awake()
{
    if (instance == null)
    {
        instance = this;
    }
}
// Start is called before the first frame update
void Start()
{
    for (int i = 0; i < amountToPool; i++)
    {
        GameObject obj = Instantiate(laserPrefab);
        obj.SetActive(false);
        pooledObject.Add(obj);
    }
}

public GameObject GetPooledObject()
{
    for (int i = 0; i < pooledObject.Count; i++)
    {
        if (!pooledObject[i].activeInHierarchy)
        {
            return pooledObject[i];
        }
    }
    return null;
}

}

这是附加在枪支上的脚本,我将其拿到汇总子弹并将其设置为“

   public class FireLaserGun : MonoBehaviour
{        
    public GameObject laserBeamModel;
    public Transform laserSpawnPoint;
   
// Start is called before the first frame update
public void FireGun()
{
    GameObject laser = ObjectPool.instance.GetPooledObject();

    if (laser != null)
    {
        laser.transform.position = laserSpawnPoint.position;
        laser.transform.rotation = laserSpawnPoint.rotation;
        laser.SetActive(true);
      
        Debug.Log("BOOM");
    }
    else
    {
        Debug.Log("Laser is null");
    }                
}
}

public class LaserBeamMove : MonoBehaviour
{
    private Rigidbody rb;
    public float thrust = 10.0f;
    float waitTime = 2.0f;
    private IEnumerator coroutine;

// Start is called before the first frame update

void Start()
{
    rb = GetComponent<Rigidbody>();
    coroutine = WaitToDisable(waitTime);
    StartCoroutine(coroutine);
}

void FixedUpdate()
{
    rb.velocity = transform.forward * thrust;        
}
private IEnumerator WaitToDisable(float waitTime)
{
    yield return new WaitForSeconds(waitTime);
    gameObject.SetActive(false);
    Debug.Log("bullet disabled after " + waitTime + "seconds");

}
}

主动 看起来不错,所有子弹都以无效的效果开始,并且在两秒钟后发射和不活动时,每个子弹都会变得活跃。 几秒钟后,子弹已经不再活跃了(实际上只有其中一些是这样)。 这是控制台日志的屏幕截图,当我开火时,我会打印“繁荣”,当子弹变得不活动时,我会在2秒后打印“子弹禁用子弹” 正如您所看到的那样,这对每个子弹都不适用,我不明白为什么。 我在说prourine上做错了什么?

https://i.sstatic.net/rmjgg.png

I'm developing a simple VR shooter in unity, i use object pooling for the bullets (Lasers here)
this is the ObjectPool script, here i istantiate a list of bullets in the start() method and disable them.

public class ObjectPool : MonoBehaviour   
{
    public static ObjectPool instance;
    private List<GameObject> pooledObject = new List<GameObject>();
    private int amountToPool = 20;
    [SerializeField] private GameObject laserPrefab;

  

private void Awake()
{
    if (instance == null)
    {
        instance = this;
    }
}
// Start is called before the first frame update
void Start()
{
    for (int i = 0; i < amountToPool; i++)
    {
        GameObject obj = Instantiate(laserPrefab);
        obj.SetActive(false);
        pooledObject.Add(obj);
    }
}

public GameObject GetPooledObject()
{
    for (int i = 0; i < pooledObject.Count; i++)
    {
        if (!pooledObject[i].activeInHierarchy)
        {
            return pooledObject[i];
        }
    }
    return null;
}

}

This is the Script attached to the gun where i get the pooled bullet and set it to active

   public class FireLaserGun : MonoBehaviour
{        
    public GameObject laserBeamModel;
    public Transform laserSpawnPoint;
   
// Start is called before the first frame update
public void FireGun()
{
    GameObject laser = ObjectPool.instance.GetPooledObject();

    if (laser != null)
    {
        laser.transform.position = laserSpawnPoint.position;
        laser.transform.rotation = laserSpawnPoint.rotation;
        laser.SetActive(true);
      
        Debug.Log("BOOM");
    }
    else
    {
        Debug.Log("Laser is null");
    }                
}
}

I'm trying to disable the bullet after two seconds was fired using a coroutine in the script that moves the bullets:

public class LaserBeamMove : MonoBehaviour
{
    private Rigidbody rb;
    public float thrust = 10.0f;
    float waitTime = 2.0f;
    private IEnumerator coroutine;

// Start is called before the first frame update

void Start()
{
    rb = GetComponent<Rigidbody>();
    coroutine = WaitToDisable(waitTime);
    StartCoroutine(coroutine);
}

void FixedUpdate()
{
    rb.velocity = transform.forward * thrust;        
}
private IEnumerator WaitToDisable(float waitTime)
{
    yield return new WaitForSeconds(waitTime);
    gameObject.SetActive(false);
    Debug.Log("bullet disabled after " + waitTime + "seconds");

}
}

Strangely first seconds of the game everything seems fine, all the bullets start as inactive and every bullet becomes active when fired and inactive after two seconds.
After some seconds bullets dont become inactive anymore (actually only some of them do).
this is a screenshot of the console log, when i fire i print "BOOM" and when a bullet becomes inactive i print "bullet disabled after 2 seconds"
As you can see this down't work for every bullet and i don't understand why.
Am i doing something wrong with the courutine?

https://i.sstatic.net/rMJgg.png

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

恰似旧人归 2025-02-18 18:05:22

取您在void start()中的代码,然后将其移至新的void oneenable。原因是start仅调用一次,第一次启用持有脚本的对象(例如,当场景加载时,当您实例化bullet等时),OneNable每次启用对象时都称为,这就是您想要的。您也可以使用Awake,但是最好仅保留初始化内容的恕我直言,因此您可以保持代码整洁并将游戏逻辑与Init Logic分开。

Take the code you have in void Start() and move it to a new void OnEnable. The reason is that Start is only called once, the first time the object holding the script is enabled (e.g when the scene loads, when you instantiate a bullet etc), OnEnable is called every time the object is enabled, which is what you want here. You could also use Awake but IMHO that's best kept separately for initialisation stuff only so you can keep the code tidy and separate out game logic from init logic.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文