Unity выдает сразу 2 ошибки:
NullReferenceException: Object reference not set to an instance of an object
TreeTile.StartUp (Vector3Int position, UnityEngine.Tilemaps.ITilemap tilemap, UnityEngine.GameObject go) (at Assets/Scripts/TileScripts/TreeTile.cs:12)
Error running StartUp for Tile.NullReferenceException: Object reference not set to an instance of an object
TreeTile.StartUp (Vector3Int position, UnityEngine.Tilemaps.ITilemap tilemap, UnityEngine.GameObject go) (at Assets/Scripts/TileScripts/TreeTile.cs:12)
которые указывают на строку
go.GetComponent<SpriteRenderer>().sorting = -position.y * 2;
Понимаю, что где-то ссылаюсь на null, но где - понять не могу.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEngine.Tilemaps;
[RequireComponent(typeof(SpriteRenderer))]
public class TreeTile : Tile
{
public override bool StartUp(Vector3Int position, ITilemap tilemap, GameObject go)
{
go.GetComponent<SpriteRenderer>().sortingOrder = -position.y * 2;
return base.StartUp(position, tilemap, go);
}
#if UNITY_EDITOR
[MenuItem("Assets/Create/Tiles/Treetile")]
public static void CreateTreetile()
{
string path = EditorUtility.SaveFilePanelInProject("Save Treetile", "New Treetile", "asset", "Save Treetile", "Assets");
if (path == "")
{
return;
}
AssetDatabase.CreateAsset(ScriptableObject.CreateInstance<TreeTile>(), path);
}
#endif
}
Для справки: я пытаюсь добавить в тайловую палитру (Tile Palette) префаб дерева с колайдером и объектом. Это мне, вроде, удалось, но деревья ставились друг на друга. Я использую новый скрипт, чтобы они не наслаивались и сортировались. Проект компилируется, всё запускается и отображается без проблем. Но вот сама ошибка печатается, и это напрягает.
Ниже приведены картинки для наглядности.
Очевидно, null вы получаете от метода GetComponent<T>(), т.к. к объекту не прикреплен искомый компонент:
GetComponent Unity API
Returns the component of Type type if the game object has one attached, null if it doesn't.
Скорее всего банальная человеческая ошибка, чтобы "не забывать" вешать необходимые компоненты на префабы - пользуйтесь RequireComponent:
[RequireComponent(typeof(SpriteRenderer))]
public class TreeTile : Tile
...
Причем данный атрибут можно установить на базовый класс Tile, и он, очевидно, будет работать и для всех его потомков.
UPDATE
Изучив документацию по теме тайлов в Unity стало ясно, что метод StartUp используется для кастомного кода для кастомных спрайтов. Причем этот метод вызывается, видимо, для инициализации самой TilePallete, а значит не для инстанциированных объектов.
Другими словами Unity за кулисами не передает никакой объект параметром в StartUp, что в этой строке:
go.GetComponent<SpriteRenderer>().sorting = ...;
Равносильно
null.GetComponent<SpriteRenderer>().sorting = ...;
Если посмотреть на пример реализации собственных тайлов в API, видно, что в переопределенном StartUp методе нужно вручную проверять условие go != null:
public override bool StartUp(Vector3Int location, ITilemap tilemap, GameObject go)
{
if (go != null)
{
go.transform.rotation = Random.rotation;
}
return true;
}
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости