|
Общие вопросы вопросы не попадающие ни в один из доступных разделов |
15.10.2020, 00:08
|
#16
|
Терабайт исходников
Регистрация: 05.07.2007
Сообщений: 5,196
Написано 1,721 полезных сообщений (для 5,374 пользователей)
|
Ответ: Очередные вопросы от меня по игровой логике и скриптингу
Короче с небольшими переделками сцена боя переехала на 15 метров
под открытый мир. Запихал сцену боя в ассет, некоторые правки в половину скриптов внёс.
Теперь будет так как есть, это решение лучше постоянного сохранения с загрузкой.
|
(Offline)
|
|
Эти 3 пользователя(ей) сказали Спасибо Crystal за это полезное сообщение:
|
|
17.10.2020, 05:13
|
#17
|
Терабайт исходников
Регистрация: 05.07.2007
Сообщений: 5,196
Написано 1,721 полезных сообщений (для 5,374 пользователей)
|
Ответ: Очередные вопросы от меня по игровой логике и скриптингу
Сообщение от ABTOMAT
Ты имеешь в виду, каждый объект в Update проверяет каждый кадр, не пора ли ему удолиться? Это не самый производительный вариант, потому что проверка будет идти каждый кадр. Это не очень хорошо.
Вообще такое можно сделать 2 способами:
Через эвенты.
1. Создаёшь UnityEvent battleOver и вызываешь его battleOver.Invoke() в момент, когда битва завершена.
2. Каждому объекту, который имеет отношение к, в OnEnable делаешь подписку (лайк, колокольчик) на этот эвент:
battleOver.AddEventListener(() => {Debug.Log("Я отреагировал на завершение битвы!");});
Ну и соответственно в листенере можешь делать то действие, какое надо при завершении битвы (например, удалять этот объект).
Вариант с эвентами хорош тем, что можно создать эвенты на все ключевые события, а потом объекты "подписывать" на них по мере надобности.
Второй способ через списки:
Иметь список всех однотипных объектов и при надобности перебирать их все.
public static List<Monster> allMonsters = new List<Monster>(); // Глобальный список
Monster.allMonsters.Add(this); // Каждого монстра при создании (OnEnable) заносим в список
Monster.allMonsters.Remove(this); // Каждого монстра при удалении (OnDisable) убираем из списка
Соответственно при создании и удалении у тебя автоматом будут заноситься или убираться монстры в список.
Если тебе надо удалить всех монстров (или что-то с ними сделать) то перебираешь список:
Monster.allMonsters.ForEach(monster => {Debug.Log($"А мы тут монстров перебираем: {monster}!");});
Способ со списками более простой, но я бы советовал раздуплить как работают эвенты, полезная штука.
|
Я вымучился уже с этим уродским списком. Эти списки говно ужасное.
В общем создал список:
public static List<GameObject> Units = new List<GameObject>(); // Список монстров + игрок.
Запихиваю в него монстров:
FightScene.Units.Add(Monster); // Монстра заносим в список.
Если я из скрипта самого монстра хочу удалить его из листа и дестройнуть,
то пожалуйста, легко:
FightScene.Units.Remove(Monster);
Destroy(Monster);
но вот если я из другого следящего скрипта хочу
почистить всё из листа, без прямых ссылок на префаб монстра,
просто перебором, то я смогу только дестройнуть монстров,
оставив пустые строки в листе:
private int Listalo;
FightScene.Units.ForEach(Listalo => { if (Listalo == true) { Destroy(Listalo); }});
(да можно без if, не суть)
Так вот, конструкция выше прекрасно выпиливает все объекты в листе,
но оставляет вместо них пустышки, которые никуда из списка не исчезают.
Казалось бы, сделаем вот так и ок:
FightScene.Units.ForEach(Listalo => { if (Listalo == true) { Destroy(Listalo); FightScene.Units.Remove(Listalo); }});
И хрен, всё крашится в ошибку (Коллекция была изменена; операция перечисления может не выполняться.):
InvalidOperationException: Collection was modified; enumeration operation may not execute.
System.ThrowHelper.ThrowInvalidOperationException (System.ExceptionResource resource) (at <437ba245d8404784b9fbab9b439ac908>:0)
System.Collections.Generic.List`1[T].ForEach (System.Action`1[T] action) (at <437ba245d8404784b9fbab9b439ac908>:0)
GAMECONTROL.Update ()
|
Я бился с этим говном 10 часов, и не победил никакими способами.
|
(Offline)
|
|
17.10.2020, 08:59
|
#18
|
Unity/C# кодер
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений (для 5,323 пользователей)
|
Ответ: Очередные вопросы от меня по игровой логике и скриптингу
Сделай так:
FightScene.Units.ForEach(Listalo => { if (Listalo) Destroy(Listalo); }); // удалить все уничтоженные объекты списка FightScene.Units.RemoveAll(Listalo => Listalo == null);
Так же если тебе нужно удалить все элементы, то вызови FightScene.Units.Clear(); после уничтожения объектов. Т.е.
FightScene.Units.ForEach(Listalo => { if (Listalo) Destroy(Listalo);}); // очистить список FightScene.Units.Clear();
Я иногда перебираю список в обратном порядке, чтобы уничтожить только нужные объекты:
for(int i = FightScene.Units.Count-1; i>=0; i--) { if(FightScene.Units[i].IsDead) // проверка юнита на смерть { Destroy(FightScene.Units[i]); FightScene.Units.RemoveAt(i); } }
Т.к. в этом случае не используется foreach, который создает энумератор при переборе элементов списка, то не происходит исключения при изменении коллекции.
|
(Offline)
|
|
Сообщение было полезно следующим пользователям:
|
|
17.10.2020, 15:29
|
#19
|
Терабайт исходников
Регистрация: 05.07.2007
Сообщений: 5,196
Написано 1,721 полезных сообщений (для 5,374 пользователей)
|
Ответ: Очередные вопросы от меня по игровой логике и скриптингу
FightScene.Units.RemoveAll(Listalo => Listalo == null);
Это не работает, ночью я пробовал такой вариант.
Сейчас тоже попробовал, и тоже не работает.
FightScene.Units.Clear();
Это работает. Спасибо, спас.
for(int i = FightScene.Units.Count-1; i>=0; i--)
{
if(FightScene.Units[i].IsDead) // проверка юнита на смерть
{
Destroy(FightScene.Units[i]);
FightScene.Units.RemoveAt(i);
}
}
Здесь "IsDead" это что и откуда? Я тут не понял где это должно быть вбито у объекта.
|
(Offline)
|
|
17.10.2020, 23:40
|
#20
|
Unity/C# кодер
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений (для 5,323 пользователей)
|
Ответ: Очередные вопросы от меня по игровой логике и скриптингу
Сообщение от Crystal
Это не работает, ночью я пробовал такой вариант.
Сейчас тоже попробовал, и тоже не работает.
|
А можешь показать пример как ты это используешь? По идее должно работать...
Сообщение от Crystal
Здесь "IsDead" это что и откуда? Я тут не понял где это должно быть вбито у объекта.
|
Не обратил внимания, что твой список это GameObject. Вот пример при котором я предполагаю, что у тебя на каждом юните висит одноименный класс Unit:
for(int i = FightScene.Units.Count-1; i>=0; i--) { if(FightScene.Units[i] == null || FightScene.Units[i].GetComponent<Unit>().IsDead) { Destroy(FightScene.Units[i]); FightScene.Units.RemoveAt(i); } }
А вот пример класса Unit (свойство IsDead в виде лямбда функции):
using UnityEngine;
public class Unit: MonoBehaviour { public int health = 100;
public bool IsDead => health <= 0;
}
Пример класса Unit (свойство IsDead в виде обычного свойства только для чтения)
using UnityEngine;
public class Unit: MonoBehaviour { public int health = 100;
public bool IsDead { get { return health <= 0; } }
}
|
(Offline)
|
|
Сообщение было полезно следующим пользователям:
|
|
18.10.2020, 11:15
|
#21
|
Терабайт исходников
Регистрация: 05.07.2007
Сообщений: 5,196
Написано 1,721 полезных сообщений (для 5,374 пользователей)
|
Ответ: Очередные вопросы от меня по игровой логике и скриптингу
Сообщение от pax
А можешь показать пример как ты это используешь? По идее должно работать...
Не обратил внимания, что твой список это GameObject. Вот пример при котором я предполагаю, что у тебя на каждом юните висит одноименный класс Unit:
for(int i = FightScene.Units.Count-1; i>=0; i--) { if(FightScene.Units[i] == null || FightScene.Units[i].GetComponent<Unit>().IsDead) { Destroy(FightScene.Units[i]); FightScene.Units.RemoveAt(i); } }
А вот пример класса Unit (свойство IsDead в виде лямбда функции):
using UnityEngine;
public class Unit: MonoBehaviour { public int health = 100;
public bool IsDead => health <= 0;
}
Пример класса Unit (свойство IsDead в виде обычного свойства только для чтения)
using UnityEngine;
public class Unit: MonoBehaviour { public int health = 100;
public bool IsDead { get { return health <= 0; } }
}
|
Пример показать не могу, к сожалению я бэкапнулся на 14 октября,
на момент до соединения двух сцен в одну. Да и собственно тыб там не разобрался,
скрипты содержащие нужные участки огромные. В принципе пост 17 это и есть вырезки из существовавшего кода.
17
Нет у меня на каждом юните класса юнит,
висит отдельный скрипт в монобехавере с переменными,
хранщими в себе нужные цифры. Переменная смерти там есть.
public class MonsterInfo : MonoBehaviour
{
public int MonsterNumber; //Порядковый номер монстра
public int ThreatLevel; //Уровень угрозы монстра
public int MonsterControl = 0; //Статус выделения монстра, по умолчанию "0" не выделен.
public float MAXHP;
public float HP;
public int MonsterDeath = 0; // Смерть монстра, 1 - это труп.
public float SilaMin;
public float SilaMax;
public float Udacha;
public float LEVEL; // Уровень монстра.
public float EXPAMAX; // Максимальная экспа до левелапа.
public float EXPA; // Текущая экспа.
public float VALUATION; // Ценность в экспе за убийство этого монстра
public int Storona; // Чей монстр: 1. Дикий, 2. Вражеский, 3. Наш, 4. Союзнический.
public int NomerHoda; // Номер под которым ходит наш монстр.
public float GKU = 0f; // Готовность монстра к удару
public int MonsterSkill1;
public int MonsterSkill1Range;
public int MonsterSkill1Position;
public int MonsterSkill2;
public int MonsterSkill2Range;
public int MonsterSkill2Position;
public int MonsterSkill3;
public int MonsterSkill3Range;
public int MonsterSkill3Position;
public int MonsterSkill4;
public int MonsterSkill4Range;
public int MonsterSkill4Position;
public int MonsterSkill5;
public int MonsterSkill5Range;
public int MonsterSkill5Position;
public int MonsterSkill6;
public int MonsterSkill6Range;
public int MonsterSkill6Position;
}
З.ы. Меня устроил твой вариант с полной очисткой листа, так и будет когда снова дойду до этого дела.
|
(Offline)
|
|
18.10.2020, 11:41
|
#22
|
Unity/C# кодер
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений (для 5,323 пользователей)
|
Ответ: Очередные вопросы от меня по игровой логике и скриптингу
Тогда просто меняй в моем пример Unit на MonsterInfo. Вот тебе еще пример)
for(int i = FightScene.Units.Count-1; i>=0; i--) { // если в списке уже уничтоженный объект if(FightScene.Units[i] == null) { // просто его удаляем из списка FightScene.Units.RemoveAt(i); } else { // объект в списке не уничтожен // берем с объекта компонент MonsterInfo var monsterInfo = FightScene.Units[i].GetComponent<MonsterInfo>();
// если компонента нет, то это не монстр, если это монстр, то смотрим его жизни, // если сдох, уничтожаем и выкидываем из списка if(monsterInfo != null && monsterInfo.HP <= 0) { Destroy(FightScene.Units[i]); FightScene.Units.RemoveAt(i); } } }
|
(Offline)
|
|
Сообщение было полезно следующим пользователям:
|
|
18.10.2020, 13:51
|
#23
|
Терабайт исходников
Регистрация: 05.07.2007
Сообщений: 5,196
Написано 1,721 полезных сообщений (для 5,374 пользователей)
|
Ответ: Очередные вопросы от меня по игровой логике и скриптингу
Спасибо, на следующей неделе попробую применить.
В данный момент не могу, у меня вчера ОРВИ дало осложнение на глаза
(покраснение, ощущение инородного тела, сморщивание коньюктивы при повороте глаза).
Вчера пришлось отказаться от программирования, закапать глаза, и лечь в постель...
Сегодня наверное тоже не смогу напрягать глаза.
|
(Offline)
|
|
Ваши права в разделе
|
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 07:34.
|