Unity 2d:被销毁后在场景重新加载时重新实例化的对象

Unity 2d : Objects being reinstantiated on scene reload after being destroyed

目标
所以我正在创建一个自上而下的竞技场战斗类型游戏,我希望你能够通过按 R 重新启动游戏。

问题
当我按下 R 键时,整个场景会按原样重置,除了所有先前实例化(然后被销毁)的敌人会再次生成,全部一次。

代码
这是生成敌人的代码:

using System.Collections.Generic;
using UnityEngine;

public class EnemySpawn : MonoBehaviour
{
    private float nextActionTime = 0.0f;
    public float period = 5f;

    public GameObject enemy;

    void Update()
    { 
        if (Time.time > nextActionTime ) {
            nextActionTime += period;
            GameObject clone = Instantiate(enemy, new Vector3(-1, 3, 0), Quaternion.identity);
            clone.tag = "enemy";
        }  
    }
}

这是玩家代码,负责重新启动场景(我用破折号标记了我认为是相关的部分):

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class PlayerController : MonoBehaviour
{
    public Rigidbody2D rb;

    public GameObject Shield;
    public GameObject ShieldInstance;

    public float moveSpeed = 4.3f;
    public float sheildSpeed = 5f;
    
    Vector2 movement;

    AudioSource woop;
    AudioSource waa;

----------------------------

    GameObject[] enemies;

----------------------------

    bool isDead = false;

    void Start() {
        woop = GameObject.Find("Main Camera/ShieldSFX").GetComponent<AudioSource>();
        waa = GameObject.Find("Main Camera/DefeatSFX").GetComponent<AudioSource>();
    }

    void Update()
    {
--------------------------------------------------------------
        enemies = GameObject.FindGameObjectsWithTag("enemy");
--------------------------------------------------------------
        movement.x = Input.GetAxisRaw("Horizontal");
        movement.y = Input.GetAxisRaw("Vertical");

        Vector3 mouseScreen = Input.mousePosition;
        Vector3 mouse = Camera.main.ScreenToWorldPoint(mouseScreen);

        transform.rotation = Quaternion.Euler(0, 0, Mathf.Atan2(mouse.y - transform.position.y, mouse.x - transform.position.x) * Mathf.Rad2Deg - 90); 

        if (Input.GetMouseButtonDown(0))
        {
            if (ShieldInstance != null || transform.GetChild(0).GetComponent<SpriteRenderer>().enabled == false) { return; }
            woop.Play();
            ShieldInstance = Instantiate(Shield, transform.position + transform.forward + transform.up, transform.rotation);
            ShieldInstance.transform.parent = transform;
        }

        if (Input.GetMouseButtonUp(0))
        {
            if (ShieldInstance == null) { return; }
            ShieldInstance.transform.parent = null;
            ShieldInstance.GetComponent<ShieldController>().LaunchForward(sheildSpeed);
            Destroy(ShieldInstance, 2.3f);
        }
-------------------------------------------------------------------------------
        if (Input.GetKey("r")) {
            SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
            foreach (GameObject one in enemies) {
                Destroy(one);
            }
        }
-------------------------------------------------------------------------------
    }

    void FixedUpdate() {
        if (!isDead) {
            rb.MovePosition(rb.position + movement * moveSpeed * Time.fixedDeltaTime);
        }
    }

    void OnCollisionEnter2D(Collision2D other) {
        if (other.gameObject.tag == "enemy") {
            waa.Play();
            GameObject.Find("Canvas/gameover").GetComponent<Text>().enabled = true;
            transform.GetChild(0).GetComponent<SpriteRenderer>().enabled = false;
            GetComponent<PolygonCollider2D>().enabled = false;
        }
    }
}

这是敌方代码 :

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EnemyFollow : MonoBehaviour
{
    public float moveSpeed;
    public ParticleSystem explode;

    AudioSource boom;

    Vector2 movement;

    GameObject player;
    Rigidbody2D rb;

    SpriteRenderer sr;
    PolygonCollider2D pc;


    void Start() {
        rb = GetComponent<Rigidbody2D>();
        sr = transform.GetChild(0).GetComponent<SpriteRenderer>();
        pc = GetComponent<PolygonCollider2D>();
        player = GameObject.Find("Player");
        boom = GameObject.Find("Main Camera/ExplodeSFX").GetComponent<AudioSource>();
    }

    void Update()
    {
        Vector2 difference = (player.transform.position - new Vector3(2, .5f, 0)) - transform.position;

        if (difference.x > 0) {
            movement.x = 1;
        } else if (difference.x < 0){
            movement.x = -1;
        } else {
            movement.x = 0;
        }

        if (difference.y > 0) {
            movement.y = 1;
        } else if (difference.y < 0){
            movement.y = -1;
        } else {
            movement.y = 0;
        }

        rb.MovePosition(rb.position + movement * moveSpeed * Time.fixedDeltaTime);
    }

    void OnCollisionEnter2D(Collision2D other) {
        if (other.gameObject.tag == "shield") {
            StartCoroutine(ExplodeF());
        }
    }

    private IEnumerator ExplodeF() {
        explode.Play();
        boom.Play();
        sr.enabled = false;
        pc.enabled = false;
        yield return new WaitForSeconds(explode.main.startLifetime.constantMax);
        Destroy(gameObject);
    }
}

如果有任何帮助,我将不胜感激! 如果您想要/需要更多详细信息,请发表评论:)

问题出在Time.time,是应用启动后的时间,不是场景启动后的时间。因此,如果您在游戏中停留了 30 秒,那么 Time.time 就是 30 秒。如果重新加载场景,它仍然是 30 秒。

你得数一数从进入场景到现在的时间。然后它不会在场景重新加载时重生所有敌人。

当你重新启动场景时,除了时间之外,所有的东西都被销毁并重置。

您的代码中的问题出在敌人生成器中。 Time.time returns 从您开始游戏开始(而不是从场景加载开始)过去的时间。因此,在重新启动后,if 条件为真并且生成了敌人。

如果你想计算自场景加载以来的时间(以秒为单位),你可以做的是在敌人生成器中添加一个变量 class 来计算时间

using System.Collections.Generic;
using UnityEngine;

public class EnemySpawn : MonoBehaviour
{
    private float nextActionTime = 0.0f;
    private float timeSinceStart = 0;
    public float period = 5f;

    public GameObject enemy;

    void Update()
    { 
        if (timeSinceStart > nextActionTime ) {
            nextActionTime += period;
            GameObject clone = Instantiate(enemy, new Vector3(-1, 3, 0), Quaternion.identity);
            clone.tag = "enemy";
        }  
        timeSinceStart += Time.deltaTime;
    }
}

Time.deltaTime