Код, в котором возникла проблема:
using UnityEngine;
using TMPro;
public class SpeakerNameInputHandler : MonoBehaviour
{
public Speaker speaker;
public TMP_InputField nameInputField;
public TMP_Text speakerNameTextMeshPro; // Reference to the TextMeshPro object where speaker name will be displayed
public void SetSpeakerCustomName()
{
string newName = nameInputField.text;
speaker.SetCustomName(newName);
// Update TextMeshPro text with the new speaker name
if (speakerNameTextMeshPro != null)
{
speakerNameTextMeshPro.text = newName;
}
}
}
Я хотел сделать раскрывающийся список при последовательном редактировании, чтобы иметь команду SetSpeakerCustonName, но когда я попробовал это с этим кодированием, оно не отображалось, и есть только имя и имя строки. Я ожидал, что это изменит название моих динамиков, динамики, которые я сделал, основаны на кодах.
Коды, соответствующие приведенному выше коду:
using UnityEngine;
using System.Collections.Generic;
[CreateAssetMenu(fileName = "NewSpeaker", menuName = "Data/New Speaker")]
[System.Serializable]
public class Speaker : ScriptableObject
{
public string speakerName;
public Color textColor;
public List<Sprite> sprites;
public SpriteController prefab;
public void SetCustomName(string newName)
{
speakerName = newName;
}
}
Обновлять
Да, есть более 1 докладчика, они указаны в папке с историями (я делаю визуальную новеллу)
Папка динамиков:
Изображение состояло из инспектора, сцены и иерархии:
Изображение функции в режиме непрерывного редактирования:
Макмейл-инспектор:
Да, здесь более 1 динамика. Коды, которые я сделал выше, предназначены для изменения имени говорящих после того, как игрок вводит их имя. Но в инспекторе полей ввода не удалось зарегистрировать код для изменения их имени в режиме On End Edit, поскольку он не отображал функцию SetSpeakerCustomName, которую я намеревался реализовать, он показывает только строку и имя строки.
Хорошо, во-первых, не создавайте производные от Unity объекты [System.Serializable]. Поверьте мне, это приносит больше вреда, чем пользы (да, есть ситуации, когда вам нужно его использовать, но в большинстве случаев вы этого не делаете). Любой объект Unity (да, включая SO и MB) по умолчанию сериализуется (в C++), но другим способом, чем сериализатор C# (System.Serializable). То есть, когда вы открываете список функций, вы не видите функцию? Вы также нажимали на объект сценария mcmale хотя бы один раз? (именно так его загружает редактор, иначе он не будет «индексироваться» внутри). Выложите скриншот списка, пожалуйста
Хорошо, я приму это к сведению. И да, функции есть только на изображении [3], поэтому другой функции, кроме этой, нет. Извините, но я не совсем понимаю, что вы имели в виду, нажимая на значок mcmale. Но сам объект создан из скрипта динамиков, поэтому я сделал его из Unity, которому нужно только назначить имена и ресурсы [4]
Когда вы впервые создаете объект сценария в редакторе (то есть с помощью контекстного меню через вызов CreateAssetMenu()), а не во время выполнения, даже если ресурс существует в вашем проекте, он не загружается. Это означает, что использование чего-то вроде класса Resources для динамической загрузки ресурса никогда не будет работать и приведет к сбою. Поэтому вам также нужно нажать на него и выбрать в папке «Активы». Только один раз после его создания. Я предполагаю, что внутри движка есть какая-то внутренняя логика, но я всегда так делаю, потому что иногда получаю исключения NullReferenceException. Это рекомендация, чтобы не иметь никаких проблем.
Что касается Serializable, поскольку мы не видим исходный код Unity на C++, мы не знаем, как работает внутренний сериализатор, поэтому конфликт может вызвать неожиданное поведение, поэтому я попросил вас удалить его и позволить Unity сделать все самостоятельно. встроенная сериализация. Спасибо за фотографии. На изображении «Изображение функции в последовательном редактировании:» вы добавили файл ScriptableObject C# (скрипт из каталога Scripts) в слот для OnEditEnd()?
да, я сделал, но он ничего не сделал и показывает только то, что на изображении 3
Хорошо, думаю, я знаю, в чем проблема :) Я составлю рукопись по Красному морю, но также включу TLDR, если вас не волнует история, начиная с эпохи динозавров и до наших дней :) Если у вас есть дополнительные вопросы или что-то неясно, напишите комментарий. Короче говоря, вам нужно ссылаться на сами экземпляры SO (ресурсы), а не на скрипт. Код «бесполезен», поскольку у него нет никаких реальных свойств игры, поскольку он не является реальным GameObject, Компонентом или SO.





Хорошо, я думаю, что могу понять эту путаницу и попытаюсь немного объяснить. Но сначала, поскольку это будет немного длинно, я начну с противоположного способа структурирования ответов, включающих исторические события, и сначала начну с TLDR, а потом сделаю TSNMI (слишком короткий, нужно больше информации).
В случае сценариев вы не можете ссылаться на реальный MonoScript (т. е. на внутреннее представление как на ресурс исходного кода C#), а скорее на его используемые экземпляры. Подробнее об этом в ЦНМИ.
В случае MB (MonoBehaviours) вам необходимо перетащить Компонент GameObject, который использует сценарий (который на самом деле будет косвенно ссылаться на GameObject как постоянную ссылку на этот Компонент.
В случае SO (ScriptableObjects), поскольку они не «прикрепляются» к GO и не существуют как реальные объекты в сцене, вам нужно будет использовать один из созданных SO (то есть один из тех, которые создается с помощью контекстного меню).
Обоснование:
Поскольку это означает, что вы используете экземпляр, следствием этого является то, что он применяется только к этому объекту. Короче говоря, предположим, что у вас есть событие, которое устанавливает имя юнита в игре, например героя в ролевой игре, и этот юнит, очевидно, является GameObject (поэтому к нему прикреплен МБ). Допустим, вы создаете группу и у вас более одного героя. В игре говорится: «Пожалуйста, напишите имя каждого героя в вашей группе» (действие аналогично тому, что у вас есть в визуальном романе). Вам нужно будет сослаться на одного героя для события InputField, иначе вам придется назвать всех героев в вашей группе одним и тем же именем, верно?
Теперь предположим, что у вас более статичный игровой процесс, например визуальный роман. У вас есть несколько персонажей (аналогичная ситуация, как в моем примере с ролевой игрой), но они представлены как SO. Ну как назвать одного из них, а не всех? Если бы вы могли использовать сценарий, то у всех ваших персонажей были бы одинаковые имена. Таким образом, чтобы игра узнала, что вы хотите назвать только второго персонажа, нужно сослаться на второй ресурс SO.
Хорошо, но как мне обработать множественный выбор?
Ну, вы можете дублировать объекты, использующие события (например, текстовое поле), скрывать их все и использовать некоторую логику, чтобы отображать каждый по отдельности. Или можно полениться и показать, например, все 4 поля по 4 символа одно под другим, потом иметь одну единственную кнопку "Далее" или что там сохранить. Если вам нужно более чистое решение, вы можете изменить цель события программно, если хотите, например, использовать только одно текстовое поле. В случае первого решения (несколько текстовых полей) вы можете реализовать логику без большого количества кода, используя события (то есть для одного события добавьте несколько целей, одна из которых имеет enable = false), если вы не заинтересованы в кодировании.
Экзотические случаи?
Да. Имейте в виду, что SO — это контент, хранящийся как актив. Это означает, что это сохраняется во всем проекте, а не в одной сцене. Это означает, что на него можно ссылаться повсюду. С другой стороны, создание собственного Unity Event внутри SO не позволит вам ссылаться практически ни на что. Давайте рассмотрим пример: как игра будет обрабатывать SO, используемый MB из сцены 2, когда SO ссылается на MB из сцены 1? Технически это невозможно, так как сцены больше не существует и все объекты из нее удалены. Но могут ли ГО быть активами? Да. Использование префабов.
Но эти два случая сами по себе представляют собой весьма долгую дискуссию.
Исключения для экзотических случаев?
И да, есть несколько способов справиться с этим: либо с помощью нескольких сцен, либо с помощью UnityEngine.Object.DontDestroyOnLoad(), который создает специальную постоянную сцену, которая будет «хранить» все ваши постоянные объекты. Но эти случаи сами по себе представляют собой совершенно долгую дискуссию. Это также положило бы начало долгому обсуждению.
"динамики"? Значит, больше одного? А пока, пожалуйста, опубликуйте изображение ресурсов, где находятся SO-спикеры, изображение инспектора с MB динамикаInputHandler и изображение представления сцены (или игры). Я немного понимаю вашу попытку, но не могу полностью ее представить. Кроме того, для текстовых меток
TMP_Text— это не то, что вам нужно. Я думаюTextMeshProUGUIэто то, что вам нужно.