Пятница, 15 Ноября 2024, 04:44

Приветствую Вас Гость

[ Новые сообщения · Игроделы · Правила · Поиск ]
  • Страница 1 из 1
  • 1
Объясните пожалуйста как сделать систему рассылки и слушаний
Jlexa123Дата: Пятница, 26 Апреля 2019, 18:44 | Сообщение # 1
частый гость
Сейчас нет на сайте
Здравствуйте, я нуб в с# и в Unity, однако учусь по Unity в действии, Джозеф Хокинг. Книга написана для юнити 4+, однако в юнити 5 все изменилось и я не могу понять, как сделать тоже самое в юнити 5. Кому целиком лень читать, читайте с середины.
-------------задание из книги--------------

6.4.1. Интегрирование системы сообщений
Для оповещения UI о происходящем в сцене мы создадим систему широковещательной рассылки сообщений. Хотя в Unity нет подходящей для выполнения такой задачи встроенной функции, мы можем скачать нужный сценарий. Вики-сообщества Unify представляют собой репозиторий бесплатного кода от различных разработчиков. Их система для службы сообщений дает несвязанный способ взаимодействия с остальной частью программы посредством событий. Рассылающий сообщения код может ничего не знать о подписчиках, что позволяет легко менять или добавлять взаимодействующие объекты.
Создайте сценарий с именем Messenger и скопируйте в него одноименный код со страницы http://wiki.unity3d.com/index.php/CSharpMessenger_Extended.
Далее вам понадобится еще один сценарий, который называется GameEvent. Его код приведен в следующем листинге.
Листинг 6.7. Сценарий GameEvent, который будет использоваться вместе со сценарием Messenger
public static class GameEvent {
public const string ENEMY_HIT = "ENEMY_HIT";
public const string SPEED_CHANGED = "SPEED_CHANGED";
}
6.4. Обновление игры в ответ на события 157
Этот сценарий задает константу для пары сообщений о событиях, что позволяет систематизировать сообщения, одновременно избавляя вас от необходимости вводить строку сообщения в разных местах.
Система оповещений о событиях готова, давайте ею воспользуемся. Начнем мы с сообщений от сцены к проекционному дисплею, а затем запрограммируем взаимодействие в противоположном направлении.
6.4.2. Рассылка и слушание сообщений сцены
До текущего момента вместо набранных игроком очков отображались значения времени — мы использовали таймер для тестирования функциональности нашего текстового дисплея. Нам же нужно, чтобы там отображалось количество пораженных игроком врагов, поэтому давайте отредактируем код сценария UIController. Первым делом удалите метод Update(), так как именно там находился тестовый код. В момент своей смерти враг генерирует событие. Следующий листинг заставит сценарий UIController слушать это событие.
Листинг 6.8. Добавление подписчиков на событие в сценарий UIController
...
private int _score;
void Awake() {
Messenger.AddListener(GameEvent.ENEMY_HIT, OnEnemyHit); ¬
}
void OnDestroy() {
Messenger.RemoveListener(GameEvent.ENEMY_HIT, OnEnemyHit); ¬
}
void Start() {
_score = 0;
scoreLabel.text = _score.ToString(); ¬ Присвоение переменной score начального значения 0.
settingsPopup.Close();
}
private void OnEnemyHit() {
_score += 1; ¬ Увеличение переменной score на 1 в ответ на данное событие.
scoreLabel.text = _score.ToString();
}
...
Первым делом обратите внимание на методы Awake() и OnDestroy(). Как и методы Start() и Update(), все члены класса MonoBehaviour автоматически реагируют на активацию или удаление объекта. Подписчик добавляется в методе Awake() и удаляется в методе OnDestroy(). Будучи частью системы широковещательной рассылки сообщений, при получении данного сообщения он вызывает метод OnEnemyHit(), который увеличивает переменную score на 1 и выводит новое значение на текстовый дисплей.
Подписчик события задан в коде UI, поэтому каждое поражение врага должно сопровождаться рассылкой соответствующего сообщения. Реагирующий на смерть врага
Объявляем, какой метод отвечает на событие ENEMY_HIT.При разрушении объекта удаляйте подписчика, чтобы избежать ошибок.
158 Глава 6. Двухмерный GUI для трехмерной игры
код находится в сценарии RayShooter.cs, поэтому добавьте туда код отправки сообщения из следующего листинга.
Листинг 6.9. Рассылка сообщения о событии в сценарии RayShooter
...
if (target != null) {
target.ReactToHit();
Messenger.Broadcast(GameEvent.ENEMY_HIT); ¬ К реакции на попадания добавлена рассылка сообщения.
} else {
...
Запустите игру и убедитесь, что теперь текстовый дисплей отображает количество пораженных врагов.
--------------------------------------------------------------------------

Кому лень читать, смысл в том, что у нас есть один скрипт с двумя стринговыми переменными, которые содержат в себе название события, есть второй скрипт, который добавляет слушатель событий, который запускает некий метод, а после удаляет этот слушатель событий и есть третий скрипт, который отправляет сообщение с названием события из первого скрипта второму скрипту. А теперь вопрос, в котором мы все не много упростим:
------------------вопрос----------------------------
У нас есть движущаяся сфера, которая при timer = 5 отправляет сообщение кубу:

public class sphere : MonoBehaviour
{
---private int timer = 0;
---private bool controller = true;
---[SerializeField] private GameObject cubee;

---void Update()
---{

------if(controller == true)
------{
---------transform.Translate(0, 0, +0.1f);
---------if(transform.position.z >= 5)
---------{
------------timer++;
------------Debug.Log("Timer = " + timer);
------------controller = false;
---------}
------}
------else if (controller == false)
------{
---------transform.Translate(0, 0, -0.1f);
---------if(transform.position.z <= 0)
---------{
------------controller = true;
---------}
------}

------if (timer == 5 )
------{
---------timer = 0;
---------cubee.BroadcastMessage("Go", SendMessageOptions.DontRequireReceiver);
------}
---}
}

Как добавить к кубу слушателя событий, который услышит событие, запустит метод Go, который начнет двигать куб вперед и удалит этот слушатель, чтобы куб более не реагировал на сообщения сферы, но при этом продолжал двигаться вперед? В коде выше куб всегда реагирует на сообщение и запускает метод Go.


Сообщение отредактировал Jlexa123 - Пятница, 26 Апреля 2019, 18:55
drcrackДата: Пятница, 26 Апреля 2019, 18:57 | Сообщение # 2
старожил
Сейчас нет на сайте
unity 4 вышла году так в 2013, просто найди более актуальную книгу, тысячи их
Jlexa123Дата: Пятница, 26 Апреля 2019, 19:09 | Сообщение # 3
частый гость
Сейчас нет на сайте
На русском их всего штук 5, тем более в этой настолько все разжевано, что даже школьник все поймет.

Добавлено (26 Апреля 2019, 21:14)
---------------------------------------------
Все, я сам разобрался.

Добавлено (27 Апреля 2019, 10:59)
---------------------------------------------
Теперь другая проблема появилась ))) вот у нас есть сериализированный массив [SerializedField] private Respavn[] resp; в него мы добавляем в инспекторе 3 респавнера, которые спавнят мобов. далее пишем Debug.log(resp[0]);
------------ВОПРОС-------------

Почему во время игры выскакивает ошибка IndexOutOfRangeException: Index was outside the bounds of the array.
SceneController.Update () (at Assets/Scripts/SceneController.cs:38) индекс вне границ массива. Хотя консоль отображает что resp 0 = объекту? Ошибка выскакивает даже если инициализировать массив с 3 объектами.


Сообщение отредактировал Jlexa123 - Суббота, 27 Апреля 2019, 11:01
seamanДата: Суббота, 27 Апреля 2019, 12:03 | Сообщение # 4
старожил
Сейчас нет на сайте
Цитата
Почему во время игры выскакивает ошибка

Приводите скрипты с такими вопросами. Все может быть и гадать тут сложно.


Сообщение отредактировал seaman - Суббота, 27 Апреля 2019, 12:03
Jlexa123Дата: Суббота, 27 Апреля 2019, 13:35 | Сообщение # 5
частый гость
Сейчас нет на сайте
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SceneController : MonoBehaviour
{
---private int r;
---private bool spawn;
---[SerializeField] private Respavner[] resp; --- в инспекторе присоединено 3 объекта Respavner

---void Start()
---{
------for(int i = 0; i<resp.Length; i++)
------{
------r = Random.Range(0, 2);
------if(r == 0)
------{
----------spawn = false;
------}
------else
------{
----------spawn = true;
------}
------Debug.Log("i: " + i + " "+ "r: " + r + " " + "spawn: " + spawn);
------Debug.Log(resp[i]);
------resp[i].spawnStart(spawn);
------}
---}

---void Update()
---{
-------Debug.Log(resp[0]); ----- выдает ошибку
---}
}

Если брать любой стандартный тип: int, string или Sprite какой-нибудь, то все нормально, а если свой, то пишет индекс вне границ массива, при этом консоль отображает объект Respavner


Сообщение отредактировал Jlexa123 - Суббота, 27 Апреля 2019, 13:44
web_sstasДата: Суббота, 27 Апреля 2019, 14:07 | Сообщение # 6
частый гость
Сейчас нет на сайте
Jlexa123, попробуй [SerializeField] private Respavner[] resp = new Respavner[3];
Jlexa123Дата: Суббота, 27 Апреля 2019, 14:09 | Сообщение # 7
частый гость
Сейчас нет на сайте
Вычитал где-то, что помогает проверка длинны массива, если написать if(0<resp.Length) Debug.Log(resp[0 или любой элемент массива]) то все работает, но это же баян какой-то. Почему так, кто знает?

Добавлено (27 Апреля 2019, 14:09)
---------------------------------------------
web_sstas уже пробовал, тоже самое выдает.


Сообщение отредактировал Jlexa123 - Суббота, 27 Апреля 2019, 14:10
web_sstasДата: Суббота, 27 Апреля 2019, 14:16 | Сообщение # 8
частый гость
Сейчас нет на сайте
Jlexa123, когда ошибка выскакивает, Respawner`ы всё ещё в массиве? Может ты их удаляешь?
Jlexa123Дата: Суббота, 27 Апреля 2019, 14:25 | Сообщение # 9
частый гость
Сейчас нет на сайте
Не, респавнеры всегда находятся в сцене, они спавнят кубы если spawn = true, и код-то тоже работает постоянно, постоянно показывает, что resp[0] = Respavner, но при этом выдает ошибку все время, что 0 вне границ массива.
drcrackДата: Суббота, 27 Апреля 2019, 15:00 | Сообщение # 10
старожил
Сейчас нет на сайте
скорее всего у тебя этот скрипт висит на какой-то другом обьекте, где его быть не должно
может на префабе куба который ты respaWnишь

в Hierarchy вверху в поиске напиши t:SceneController


Сообщение отредактировал drcrack - Суббота, 27 Апреля 2019, 15:01
Jlexa123Дата: Суббота, 27 Апреля 2019, 16:12 | Сообщение # 11
частый гость
Сейчас нет на сайте
Там очень простая сценка, скрипт висит на пустом объекте, который просто висит в воздухе, спавнеры расположены в трех местах сцены, все это постоянно присутствует в сцене и никогда не удаляется. Спавнеры такие же пустые объекты, они просто создают куб на своем месте.

Сообщение отредактировал Jlexa123 - Суббота, 27 Апреля 2019, 16:13
drcrackДата: Суббота, 27 Апреля 2019, 16:17 | Сообщение # 12
старожил
Сейчас нет на сайте
покажи скриншот иерархии с фильтром t:SceneController
Jlexa123Дата: Суббота, 27 Апреля 2019, 16:34 | Сообщение # 13
частый гость
Сейчас нет на сайте
http://s1.uploadpics.ru/images/WyS6BZ-Q9N.jpg
web_sstasДата: Суббота, 27 Апреля 2019, 16:41 | Сообщение # 14
частый гость
Сейчас нет на сайте
Jlexa123, скинь проект ассетом, так проще будет)
Jlexa123Дата: Суббота, 27 Апреля 2019, 17:06 | Сообщение # 15
частый гость
Сейчас нет на сайте
https://yadi.sk/d/kg7BefoHnv_qng попробуй отсюда скачать ) Для простоты из сцен контроллера можно все удалить из start и update, и написать в update Debug.Log(resp[0]); код будет работать, но при этом одновременно выдавать ошибку, почему так? )

Сообщение отредактировал Jlexa123 - Суббота, 27 Апреля 2019, 17:42
web_sstasДата: Суббота, 27 Апреля 2019, 17:44 | Сообщение # 16
частый гость
Сейчас нет на сайте
Jlexa123, зачем же ты на Spawner`ы scenecontroller кинул?) У тебя из-за этого проблемы, удали и всё.

Добавлено (27 Апреля 2019, 17:45)
---------------------------------------------
Jlexa123, на будущее, нажимая на ошибку в логе, выделяется GameObject, скрипт на котором содержит эту самую ошибку.

Jlexa123Дата: Суббота, 27 Апреля 2019, 17:53 | Сообщение # 17
частый гость
Сейчас нет на сайте
Блииин! Во я лошара =D я пол дня на этот баг с индексом убил ))) думал что за ерунда ) А то что на респавнерах сцен контроллер я чет как-то и не увидел ) Дело в том, что сначала респавнер был сцен контроллером, потом я его переделал в респавнер и скопировал ) Сорь, что я вас так помучил ^_^ а t:SceneController я чет подумал, что он респавнеры показал, потому что они со скриптом связаны )) А оно оказывается вот как работает )

Сообщение отредактировал Jlexa123 - Суббота, 27 Апреля 2019, 17:54
web_sstasДата: Суббота, 27 Апреля 2019, 17:56 | Сообщение # 18
частый гость
Сейчас нет на сайте
Jlexa123, бывают такие косяки, по себе знаю)
Jlexa123Дата: Суббота, 27 Апреля 2019, 18:00 | Сообщение # 19
частый гость
Сейчас нет на сайте
"Jlexa123, на будущее, нажимая на ошибку в логе, выделяется GameObject, скрипт на котором содержит эту самую ошибку."
Ты мне Америку открыл ))) Я так кучу раз делал, чтобы ошибку скопировать и перевести, но яркого желтого пятна со скриптом так и не заметил. Спасибо большое )
  • Страница 1 из 1
  • 1
Поиск:

Все права сохранены. GcUp.ru © 2008-2024 Рейтинг