下一场景未加载

时间:2019-05-08 12:07:52

标签: visual-studio unity3d unityscript

我的问题是,当所有敌人都被杀死后,应该加载的场景没有加载。我确实将场景添加到Build设置(索引为3)中,但仍未加载。我创建的脚本被附加到一个空对象,而不是直接附加到精灵(可以吗?)。有人可以告诉我为什么场景没有加载吗?谢谢。

此图像用于向您显示EnemySpawner空对象检查器 enter image description here

EnemySpawner脚本:

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

public class EnemySpawner : MonoBehaviour {

[SerializeField] GameObject EnemyPreFab;
[SerializeField] int MaxEnemies = 30;
[SerializeField] float EnemySpawnTime = 1.00001f;
[SerializeField] GameObject FirstWaypoint;
int CurrentNumOfEnemies = 0;
public LevelManager myLevelManager;
public int maximumnumberofhits = 0;
int timesEnemyHit;



IEnumerator SpawningEnemies()
{
    while(CurrentNumOfEnemies <= MaxEnemies)
    {
        GameObject Enemy = Instantiate(EnemyPreFab, this.transform.position, Quaternion.identity);
        CurrentNumOfEnemies++;
        yield return new WaitForSeconds(EnemySpawnTime);
    }
}

void Start()
{
    StartCoroutine(SpawningEnemies());
    timesEnemyHit = 0;
    if (this.gameObject.tag == "EnemyHit")
    {
        CurrentNumOfEnemies++;
    }


}

void OnCollisionEnter2D()
{
    timesEnemyHit++;
    if (timesEnemyHit == maximumnumberofhits)
    {
        CurrentNumOfEnemies--;
        Destroy(this.gameObject);
    }

    if (CurrentNumOfEnemies == 0)
    {
        myLevelManager.LoadLevel("NextLevelMenu");
        Debug.Log("LevelLoaded");
    }
   }

}

LevelManger脚本:

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

public class LevelManager : MonoBehaviour {
 public void LoadLevel(string name)
 {
    print("Level loading requested for" + name);
    SceneManager.LoadScene(name);
  }
}

EnemyShooting脚本:

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

public class EnemyShooting : MonoBehaviour {


[SerializeField] float EnemyLaserSpeed = 10f;
[SerializeField] float EnemyLaserFireTime;
[SerializeField] GameObject LaserBulletEnemyPreFab;
[SerializeField] int MaxNumberOfHits = 1;
int CurrentNumberOfHits = 0;
Coroutine FireCoroutine;

void OnTriggerEnter2D(Collider2D collider)
{
    if(collider.gameObject.tag == "PlayerLaser")
    {
        if(CurrentNumberOfHits < MaxNumberOfHits)
        {
            CurrentNumberOfHits++;
            Destroy(collider.gameObject);
            Score.ScoreValue += 2;//The user will be rewarded 1 point
        }
    }
}



void DestroyEnemy()
{
    if(CurrentNumberOfHits >= MaxNumberOfHits)
    {
        Destroy(gameObject);
    }
}

private void Fire()
{
    FireCoroutine = StartCoroutine(ShootContinuously());
}

void BecomeVisible()
{
    Fire();
}

IEnumerator ShootContinuously()
{
    while (true)
    {
        GameObject LaserBulletEnemy = Instantiate(LaserBulletEnemyPreFab, this.transform.position, Quaternion.identity) as GameObject;
        LaserBulletEnemy.GetComponent<Rigidbody2D>().velocity = new Vector2(0, EnemyLaserSpeed);
        EnemyLaserFireTime = Random.Range(0.5f, 0.9f);
        yield return new WaitForSeconds(EnemyLaserFireTime);
    }
}
// Use this for initialization
void Start () {

    BecomeVisible();
}

// Update is called once per frame
void Update () {

    DestroyEnemy();

   }
}

EnemyPathing脚本:

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

public class EnemyPathing : MonoBehaviour {
[SerializeField] List<Transform> WayPoints;
[SerializeField] float EnemyMovingSpeed = 5f;
int WayPointIndex = 0; 

void EnemyMoving()
{
    if (WayPointIndex <= WayPoints.Count - 1)
    {
        var TargetedPosition = WayPoints[WayPointIndex].transform.position; //The position of where the enemy needs to go
        TargetedPosition.z = 0f;
        var MoveThisFrame = EnemyMovingSpeed * Time.deltaTime;
        transform.position = Vector2.MoveTowards(this.transform.position, TargetedPosition, MoveThisFrame);

        if(transform.position == TargetedPosition)
        {
            WayPointIndex++;
        }
    }

    else
    {
        Destroy(gameObject);
    }
}
// Use this for initialization
void Start () {

    transform.position = WayPoints[WayPointIndex].transform.position;

}

// Update is called once per frame
void Update () {

    EnemyMoving();

 }
}

2 个答案:

答案 0 :(得分:2)

myLevelManager.LoadLevel("NextLevelMenu");永远不会执行,因为您在上面的if-test中破坏了对象。

答案 1 :(得分:2)

问题

您正在检查SPAWNER上是否有碰撞;当有人击中Spawner时,它会倒数敌人。但是Spawner在屏幕快照中没有碰撞盒,因此它永远不会被击中。永远无法调用场景更改代码。

因此,基于代码的游戏如下所示:

  1. 产生X个敌人,
  2. 点击Spanner X次,
  3. (已删除:销毁扳手,)
  4. 更改场景。

我猜这从概念上来说是不正确的,您实际上是想检查生成的敌人的碰撞,然后才能计算出被摧毁的敌人的数量,并在他们全部死亡时改变场景。


解决方案

从概念上讲,您想要的是:

  1. 产生X个敌人
  2. 为每个敌人计数变量
  3. 在敌人死亡时,倒计时
  4. 当为0时,更改场景

那我们该如何编码呢?​​

好吧,每个敌人都需要引用保存计数的对象。您可以通过多种方式执行此操作,当我亲自执行此操作时,通常只有一个对每个人都负责的生成器,因此我将其设置为Singleton,可以在任何地方进行引用:

EnemySpawner

public class EnemySpawner : MonoBehaviour 
{
    public static Spawner Instance = null;
    int CurrentNumOfEnemies = 0;
    // ... etc

    void Start() 
    {
        if (Instance == null)
             Instance = this;

        // Spawn enemies like you do already, CurrentNumOfEnemies++ for every spawned
    }

    public OnEnemyDeath() {
        CurrentNumOfEnemies--;
        if (CurrentNumOfEnemies < 1) 
        {
            // You killed everyone, change scene: 
            LevelManager.LoadLevel("Your Level");
        }
    }

}

敌人的脚本(我不知道您当前的代码看起来如何,但这是根据我认为您的代码看起来如何的最小解决方案):

void OnDestroy() 
{
    // This will run automatically when you run Destroy() on this gameObject
    EnemySpawner.Instance.OnEnemyDeath(); // Tell the EnemySpawner that someone died
}

这仅在您只有一个生成器的情况下起作用。如果有多个副本,则必须将其生成者实例的引用发送给每个生成的敌人。如果您愿意,我也可以告诉您如何做。


奖励内容

LevelManager不需要在GameObject上,而可以是静态的:

  1. 从任何GameObject中删除LevelManager脚本
  2. 将您的LevelManager代码更改为此:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public static class LevelManager 
{
    public static void LoadLevel(string name)
    {
        Debug.Log("Level loading requested for" + name);
        SceneManager.LoadScene(name);
    }
}

现在,您可以从任何地方使用它,而无需初始化对任何脚本或GameObject的引用:

LevelManager.LoadLevel("My Level");