Ошибка в Unity NullReferenceException: Object reference not set to an instance of an object

Сама ошибка вот такая:NullReferenceException: Object reference not set to an instance of an objectGameContoller.MoveLevelTop (Level level) (at Assets/Scripts/GameContoller.cs:107)Level.LateUpdate () (at Assets/Scripts/Level.cs:48)

107 строчка - level.Setup(new Vector3(0, lastLevel.AnchoredPosition.y + lastLevel.Size.y), colors[CurrentLevel % colors.Count], CurrentLevel);

48 строчка - OnFinishLevel?.Invoke(this);

using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class Level : MonoBehaviour { public System.Action OnStartNewLevel; public System.Action<Level> OnFinishLevel; private RectTransform rect; private Image image; private bool newLevelFired; [SerializeField] Text levelText; public Vector3 AnchoredPosition { get { return rect.anchoredPosition3D; } set { rect.anchoredPosition3D = value;}} public Vector2 Size { get { return rect.sizeDelta; } set { rect.sizeDelta = value; } } public Color BackColor { get {return image.color; } set { image.color = value; } } private void Awake() { image = GetComponent<Image>(); rect = GetComponent<RectTransform>(); } void Start() { } // Update is called once per frame void Update() { if (GameContoller.Instance.State == GameContoller.GameState.PLAY) { AnchoredPosition += Vector3.down * Time.deltaTime * 400; } } private void LateUpdate() { if (!newLevelFired && AnchoredPosition.y < 500) { OnStartNewLevel?.Invoke(); newLevelFired = true; } if (AnchoredPosition.y < -Size.y - 100) { OnFinishLevel?.Invoke(this); } } public void Setup(Vector3 pos, Color color, int level) { newLevelFired = false; AnchoredPosition = pos; BackColor = color; levelText.text = level.ToString(); } }
using System.Collections; using System.Collections.Generic; using UnityEngine; using System.Linq; public class GameContoller : MonoBehaviour { public enum GameState { START, PLAY, LOSE, GAME_OVER}; public event System.Action<GameState> OnStateChanged; public event System.Action<int> OnCurrentLevelChanged; public event System.Action<int> OnScoreChanged; public System.Action<int> OnGameOver; private GameState state; private int currentLevel; private int score; [SerializeField] private Transform levelRegion = null; [SerializeField] private Level LevelPrefab = null; [SerializeField] private List<Color> colors = new List<Color>(); [SerializeField] private Player player; private List<Level> levels = new List<Level>(); private List <GameObject> ObstaclePrefabs ; public GameState State { get => state; set { state = value; OnStateChanged?.Invoke(state);} } public int CurrentLevel { get => currentLevel; set { currentLevel = value; OnCurrentLevelChanged?.Invoke(value); } } public int Score { get => score; set { score = value; OnScoreChanged?.Invoke(value); } } public static GameContoller Instance; [SerializeField] private Transform spawnRegion; private Level lastLevel; private void Awake() { Instance = this; } private void Start() { ObstaclePrefabs = Resources.LoadAll<GameObject>("GroupObstacles").ToList(); for (int i=0; i<2;i++) { levels.Add(SpawnNewLevel1()); } ResetLevels(); player.OnGameOver += GameOver; } private void GameOver() { State = GameState.LOSE; StartCoroutine(DelayAction(1.5f,()=> { State = GameState.GAME_OVER; ResetGame(); OnGameOver.Invoke(Score); })); } public void ResetGame() { ClearObstacle(); ResetLevels(); player.Reset(); } private void ClearObstacle() { foreach (Transform child in spawnRegion.transform) { Destroy(child.gameObject); } } private IEnumerator DelayAction(float delay, System.Action action) { yield return new WaitForSeconds(delay); action(); } private void ResetLevels() { levels[0].AnchoredPosition = new Vector3(0, -levels[0].Size.y / 2); for ( int i = 1; i < levels.Count; i ++) { levels[i].AnchoredPosition = new Vector3(0, levels[i - 1].AnchoredPosition.y + levels[ i- 1].Size.y); } } private Level SpawnNewLevel1() { Level level = Instantiate(LevelPrefab, Vector3.zero, Quaternion.identity, levelRegion); level.AnchoredPosition =Vector3.zero; level.BackColor = colors[UnityEngine.Random.Range(0, colors.Count)]; level.Size = new Vector2 (levelRegion.parent.GetComponent<RectTransform>().sizeDelta.x, levelRegion.parent.GetComponent<RectTransform>().sizeDelta.y * 2 ); level.OnFinishLevel += MoveLevelTop; level.OnStartNewLevel += () => { CurrentLevel++; }; return level; } private void MoveLevelTop (Level level) { level.Setup(new Vector3(0, lastLevel.AnchoredPosition.y + lastLevel.Size.y), colors[CurrentLevel % colors.Count], CurrentLevel); lastLevel = level; SpawnObstacle(ObstaclePrefabs[UnityEngine.Random.Range(0, ObstaclePrefabs.Count )], spawnRegion); //level.AnchoredPosition = new Vector3(0, lastLevel.AnchoredPosition.y + lastLevel.Size.y); } public void StartGame() { CurrentLevel = 1; Score = 0; State = GameState.PLAY; SpawnObstacle(ObstaclePrefabs[UnityEngine.Random.Range(0, ObstaclePrefabs.Count)], spawnRegion); StartCoroutine(ScoreCoroutine()); } private IEnumerator ScoreCoroutine() { while (State == GameState.PLAY) { Score++; yield return new WaitForSeconds(0.2f); } } private void SpawnObstacle(GameObject gameObject, Transform spawnRegion, bool isFirst= false) { Instantiate(gameObject, spawnRegion.transform.position * (isFirst ? 0.5f : 1), Quaternion.identity, spawnRegion); } }

Хочу чтобы префаб Level спавнился, когда проходим границы Level. Мы перемещаем новый уровень вверх, пересоздавая его. Но вот скрипт не работает , вылазит вот такая ошибка, когда прохожу границы Level

0
8 комментариев
Написать комментарий...
Иван Колчин

Код ужасный, а ошибке все написано. Ты в LateUpdate-MoveLevelUp() работаешь с объектом, которого нет

Ответить
Развернуть ветку
Александр Волков
Автор

Т.е когда я указал this< он не понимает что это объект на котором висит скрипт?

Ответить
Развернуть ветку
Иван Колчин

This возвращает объект шарпов, а не объект юнити. Если умеешь пользоваться дебагом, можешь в методе MoveLevelUp поставить брейкпоинты и посмотреть, что не так. Если не умеешь, можешь этот метод Debug.Log обложить, проверяя, какой элемент null

Ответить
Развернуть ветку
Иван Колчин

Подозреваю, что при первом вызове lastLevel не существует

Ответить
Развернуть ветку
Александр Волков
Автор

Да,, благодарю. Я не вызывал lastLevel при первом вызове. Дописал строчку lastLevel = levels.Last(); в функцию private void ResetLevels() скрипта GameController, после цикла for.

Ответить
Развернуть ветку
Dmitry

тесты бы написать

Ответить
Развернуть ветку
Gleb Lebedev

больше лайков этому господину

Ответить
Развернуть ветку
L8OLOOE

Ты где то объект не вставил в скрипт

Ответить
Развернуть ветку
Читать все 8 комментариев
null