|
27.04.2012, 14:04
|
#1
|
Unity/C# кодер
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений (для 5,323 пользователей)
|
Как скрипты общаются
Мне часто задают вопрос о том, как обратиться из какого-либо скрипта к переменной другого скрипта, или как вызвать метод (функцию) другого скрипта. В этой маленькой статейке я бы хотел описать способы, которые можно для этого использовать.
Публичные переменные и доступ к компонентам
Допустим есть у нас такой скрипт
using UnityEngine;
// скрипт, к переменной которого мы хотим получить доступ public class ScriptWithVariable { // переменная, к которой мы хотим получить доступ public int myPublicVariable; }
Далее мы хотим из другого скрипта на том же объекте менять эту переменную. Есть несколько способов это сделать: - Назначить ссылку на скрипт ScriptWithVariable в редакторе через публичную переменную
- Получить ссылку на скрипт ScriptWithVariable в начале работы скрипта
- Получать скрипт перед изменением
Первый вариант подразумевает, что вы создадите публичную
using UnityEngine;
public class VariableChanger { // переменная, которая отобразится в редакторе Unity // и на которую надо перетащить скрипт ScriptWithVariable с того же или иного объекта сцены public ScriptWithVariable scriptWithVariable;
public void Update() { // изменение нужной нам переменной scriptWithVariable.myPublicVariable++; } }
Второй вариант подразумевает поиск скрипта у объекта и сохранение ссылки на него.
Допустим мы забыли указать скрипт с помощью редактора, но знаем что он должен быть, тогда можно написать код, который его найдет в начале работы скрипта.
using UnityEngine;
public class VariableChanger { // переменная, которая отобразится в редакторе Unity // и на которую надо перетащить скрипт ScriptWithVariable с того же или иного объекта сцены public ScriptWithVariable scriptWithVariable;
// добавляем код поиска public void Awake() { scriptWithVariable = GetComponent<ScriptWithVariable>(); }
public void Update() { // изменение нужной нам переменной scriptWithVariable.myPublicVariable++; } }
Третий вариант самый не оптимальный для использования в каждом кадре (Update вызывается каждый кадр). Но зато эффективен для разового использования т.к. нет необходимости в создании переменной-ссылки на нужный нам скрипт.
using UnityEngine;
public class VariableChanger { public void Start() { // изменение нужной нам переменной GetComponent<ScriptWithVariable>().myPublicVariable = 100500; } }
Вызов методов других скриптов
Все что описано про публичные переменные относится и к вызову методов.
Имеем скрипт:
using UnityEngine;
// скрипт, метод которого мы хотим вызвать public class ScriptWithVariable { public int myPublicVariable;
// метод который надо вызвать public void ChangeVariable() { myPublicVariable++; } }
Ну и собственно пример вызова:
using UnityEngine;
public class VariableChanger { public void Start() { // изменение нужной нам переменной путем вызова метода скрипта GetComponent<ScriptWithVariable>().ChangeVariable(); } }
Сообщения
Вызвать метод скрипта объекта можно так же послав сообщение этому объекту (не скрипту). Но данный способ медленнее описанного выше.
using UnityEngine;
public class VariableChanger { public void Start() { // изменение нужной нам переменной путем вызова сообщения SendMessage("ChangeVariable"); } }
Данный способ вызовет метод ChangeVariable на всех скриптах текущего объекта, в которых он объявлен с тем же именем.
Ну вот и все что хотел рассказать. Данная статья так же есть на wiki
|
(Offline)
|
|
Эти 5 пользователя(ей) сказали Спасибо pax за это полезное сообщение:
|
|
31.07.2012, 00:19
|
#2
|
|
Ответ: Как скрипты общаются
Спасибо pax! В очередной раз отлично прояснил ситуацию.
Попутный вопрос в догонку насчет функции\метода SendMessage()... А как обьекту послать помимо сообщения еще и контекст сообщения ?
В БМаксе - все просто - SendMessage:Object(message:Object, context:Object)
Конечно, можно контекст "впихнуть" в саму мессагу, но хотелось бы как в БлицМаксе =)
|
|
|
31.07.2012, 00:47
|
#3
|
Unity/C# кодер
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений (для 5,323 пользователей)
|
Ответ: Как скрипты общаются
функция SendMessage принимает вторым параметром object, т.е. что угодно. Следовательно можно написать например такой класс
public class MessageData { public GameObject context; }
и посылать сообщение например так:
SendMessage("LogContext", new MessageData{context = this.gameObject});
принимающая функция изменилась бы так:
public void LogContext(MessageData messageData) { Debug.Log(messageData.context); }
|
(Offline)
|
|
Сообщение было полезно следующим пользователям:
|
|
23.01.2013, 21:51
|
#4
|
AnyKey`щик
Регистрация: 23.01.2013
Адрес: Беларусь, Борисов
Сообщений: 8
Написано 0 полезных сообщений (для 0 пользователей)
|
Ответ: Как скрипты общаются
Всем привет!
А подскажите как быть, если переменную нужно взять из скрипта другой сцены, т.е. есть сцена со скриптом там переменная bool, мы можем ее менять на true и false, и такоеже значение она должна иметь в другой сцене. Зарание спасибо.
|
(Offline)
|
|
23.01.2013, 22:18
|
#5
|
Знающий
Регистрация: 08.01.2013
Адрес: Самара
Сообщений: 284
Написано 104 полезных сообщений (для 180 пользователей)
|
Ответ: Как скрипты общаются
В скрипте, переменная которого нужна в другой сцене нужно в Start использовать Object.DontDestroyOnLoad . ТОгда объект на котором этот скрипт не удалится при загрузке следующего уровня и скрипт будет доступен.
|
(Offline)
|
|
23.01.2013, 23:23
|
#6
|
AnyKey`щик
Регистрация: 23.01.2013
Адрес: Беларусь, Борисов
Сообщений: 8
Написано 0 полезных сообщений (для 0 пользователей)
|
Ответ: Как скрипты общаются
Большое спасибо!
А сам объект отобразится в новой сцене? Он то мне не нужен. И если не тяжело, можно ссылку на мануал с этой функцией. Я так понял ее так вот писать:
void Start() {Object.DontDestroyOnLoad;}
а потом вызывать одним из описаных методов?
|
(Offline)
|
|
23.01.2013, 23:54
|
#7
|
AnyKey`щик
Регистрация: 23.01.2013
Адрес: Беларусь, Борисов
Сообщений: 8
Написано 0 полезных сообщений (для 0 пользователей)
|
Ответ: Как скрипты общаются
ссылку не нужно, уже нашел....
|
(Offline)
|
|
24.01.2013, 16:37
|
#8
|
AnyKey`щик
Регистрация: 23.01.2013
Адрес: Беларусь, Борисов
Сообщений: 8
Написано 0 полезных сообщений (для 0 пользователей)
|
Ответ: Как скрипты общаются
Извените, а немогли бы краткий пример написать, а то чета не могу понять, а в справке всего один пример?
|
(Offline)
|
|
24.01.2013, 16:48
|
#9
|
Бывалый
Регистрация: 24.05.2011
Адрес: Украина,Харьков
Сообщений: 890
Написано 359 полезных сообщений (для 880 пользователей)
|
Ответ: Как скрипты общаются
Переменные, к которым вы обращаетесь в разных сценах лучше хранить на каком нибуть донт дестрой обьекте. У вас этот обьект будет просто перемещаться между сценами и к переменным всегда будет доступ.
__________________
Нам суждено построить мосты и храмы,которых никогда не существовало и не могло существовать в природе.
|
(Offline)
|
|
24.01.2013, 16:54
|
#10
|
AnyKey`щик
Регистрация: 23.01.2013
Адрес: Беларусь, Борисов
Сообщений: 8
Написано 0 полезных сообщений (для 0 пользователей)
|
Ответ: Как скрипты общаются
Пробавал как-так, ScriptName это имя скрипта на объекте
void Start() {
ScriptName other;
other = gameObject.GetComponent("ScriptName") as ScriptName;
other.DontDestroyOnLoad()
}
|
(Offline)
|
|
24.01.2013, 17:15
|
#11
|
Unity/C# кодер
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений (для 5,323 пользователей)
|
Ответ: Как скрипты общаются
|
(Offline)
|
|
25.01.2013, 20:12
|
#12
|
AnyKey`щик
Регистрация: 23.01.2013
Адрес: Беларусь, Борисов
Сообщений: 8
Написано 0 полезных сообщений (для 0 пользователей)
|
Ответ: Как скрипты общаются
Всем спасибо, разобрался, теперь тока одна проблема : когда в сцене меняю значение bool переменной, все работает как нужно, перехожу в след. сцену моя переменная с правильным значением тоже(радости нет предела), все работает как нужно, возвращаюсь в исходную сцену и (радость кончилась) значение переменной осталось исходным. Че с этими клонами объектов то делать, я так понял скрипт берет значение переменной с оригинала, а не с клона скрипта.Объекта.
|
(Offline)
|
|
25.01.2013, 20:41
|
#13
|
Бывалый
Регистрация: 24.05.2011
Адрес: Украина,Харьков
Сообщений: 890
Написано 359 полезных сообщений (для 880 пользователей)
|
Ответ: Как скрипты общаются
Сделать проверку на существование обьекта. Обьект не просто вставить в сцену, а инстансить его в старте и при этом проверять существование клонов.
__________________
Нам суждено построить мосты и храмы,которых никогда не существовало и не могло существовать в природе.
|
(Offline)
|
|
25.01.2013, 21:32
|
#14
|
AnyKey`щик
Регистрация: 23.01.2013
Адрес: Беларусь, Борисов
Сообщений: 8
Написано 0 полезных сообщений (для 0 пользователей)
|
Ответ: Как скрипты общаются
У меня в сцене1 два объекта, однин со скриптом действия, в нем тогглам меняется значение бул переменной. Второй со скриптом в котором я нахожу первый объект и беру зна.чение переменной, пока все хорошо, значения меняются синхронно в переменных обоих скриптов. Второй скрипт сделал донтдистракт. Переходим во вторую сцену : изночально в ней был только один объект со скриптом который находит появившийся донтдистракт объект и берет значение переменной(значение переменной из первой сцены, после изменения, а не дефолтное) и корректно выполняет свое предназначение(поко все хорошо), но перейдя из сцены2 в 1, мы имеем уже два донтдистройт объекта и значение переменной берецца из первого, а если снова перейти в сцену 2, то там тоже появился еще один донтдистройт объект, но значение переменной осталось такоеже, как при первом переходе.
Так вот как этого избежать? Чтобы донтдистракт объект был как-бы один, а не копировался, и перемесчался из сцены в сцену?
|
(Offline)
|
|
25.01.2013, 21:51
|
#15
|
Бывалый
Регистрация: 24.05.2011
Адрес: Украина,Харьков
Сообщений: 890
Написано 359 полезных сообщений (для 880 пользователей)
|
Ответ: Как скрипты общаются
Написал же выше.
Сообщение от Lestar
Обьект не просто вставить в сцену, а инстансить его в старте и при этом проверять существование клонов.
|
public GameObject Main;
Gameobject main;
void Start()
{
if(main==null) main = (GameObject)Instantiate(Main);
}
Создайте префаб, повесьте на него ваш скрипт, засуньте в паблик поле Main. Вызывайте инстанс обьекта в вашей первой сцене.
__________________
Нам суждено построить мосты и храмы,которых никогда не существовало и не могло существовать в природе.
|
(Offline)
|
|
Ваши права в разделе
|
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 11:42.
|