Извините, ничего не найдено.

Не расстраивайся! Лучше выпей чайку!
Регистрация
Справка
Календарь

Вернуться   www.boolean.name > Программирование игр для компьютеров > Unity > Общие вопросы

Общие вопросы вопросы не попадающие ни в один из доступных разделов

Ответ
 
Опции темы
Старый 15.10.2020, 00:08   #16
Crystal
Терабайт исходников
 
Аватар для Crystal
 
Регистрация: 05.07.2007
Сообщений: 4,896
Написано 1,546 полезных сообщений
(для 4,958 пользователей)
Ответ: Очередные вопросы от меня по игровой логике и скриптингу

Короче с небольшими переделками сцена боя переехала на 15 метров
под открытый мир. Запихал сцену боя в ассет, некоторые правки в половину скриптов внёс.
Теперь будет так как есть, это решение лучше постоянного сохранения с загрузкой.

(Offline)
 
Ответить с цитированием
Эти 3 пользователя(ей) сказали Спасибо Crystal за это полезное сообщение:
ABTOMAT (15.10.2020), pax (15.10.2020), St_AnGer (15.10.2020)
Старый 17.10.2020, 05:13   #17
Crystal
Терабайт исходников
 
Аватар для Crystal
 
Регистрация: 05.07.2007
Сообщений: 4,896
Написано 1,546 полезных сообщений
(для 4,958 пользователей)
Ответ: Очередные вопросы от меня по игровой логике и скриптингу

Сообщение от 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
pax
Unity/C# кодер
 
Аватар для pax
 
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,550
Написано 2,991 полезных сообщений
(для 5,297 пользователей)
Ответ: Очередные вопросы от меня по игровой логике и скриптингу

Сделай так:
FightScene.Units.ForEach(Listalo => { if (Listalo)  Destroy(Listalo); });
// удалить все уничтоженные объекты списка
FightScene.Units.RemoveAll(Listalo => Listalo == null); 
Так же если тебе нужно удалить все элементы, то вызови FightScene.Units.Clear(); после уничтожения объектов. Т.е.
FightScene.Units.ForEach(Listalo => { if (ListaloDestroy(Listalo);});
// очистить список
FightScene.Units.Clear(); 
Я иногда перебираю список в обратном порядке, чтобы уничтожить только нужные объекты:
for(int i FightScene.Units.Count-1i>=0i--)
{
    if(
FightScene.Units[i].IsDead// проверка юнита на смерть
    
{
          
Destroy(FightScene.Units[i]);
          
FightScene.Units.RemoveAt(i);
    }

Т.к. в этом случае не используется foreach, который создает энумератор при переборе элементов списка, то не происходит исключения при изменении коллекции.
__________________
Blitz3d to Unity Wiki
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
Crystal (17.10.2020)
Старый 17.10.2020, 15:29   #19
Crystal
Терабайт исходников
 
Аватар для Crystal
 
Регистрация: 05.07.2007
Сообщений: 4,896
Написано 1,546 полезных сообщений
(для 4,958 пользователей)
Ответ: Очередные вопросы от меня по игровой логике и скриптингу

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
pax
Unity/C# кодер
 
Аватар для pax
 
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,550
Написано 2,991 полезных сообщений
(для 5,297 пользователей)
Ответ: Очередные вопросы от меня по игровой логике и скриптингу

Сообщение от Crystal Посмотреть сообщение
Это не работает, ночью я пробовал такой вариант.
Сейчас тоже попробовал, и тоже не работает.
А можешь показать пример как ты это используешь? По идее должно работать...

Сообщение от Crystal Посмотреть сообщение
Здесь "IsDead" это что и откуда? Я тут не понял где это должно быть вбито у объекта.
Не обратил внимания, что твой список это GameObject. Вот пример при котором я предполагаю, что у тебя на каждом юните висит одноименный класс Unit:
for(int i FightScene.Units.Count-1i>=0i--)
{
    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 
UnitMonoBehaviour
{
        public 
int health 100;

        public 
bool IsDead => health <= 0;


Пример класса Unit (свойство IsDead в виде обычного свойства только для чтения)
using UnityEngine;

public class 
UnitMonoBehaviour
{
        public 
int health 100;

        public 
bool IsDead
        
{
               
get
               
{
                      return 
health <= 0;
               }
        }


__________________
Blitz3d to Unity Wiki
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
Crystal (18.10.2020)
Старый 18.10.2020, 11:15   #21
Crystal
Терабайт исходников
 
Аватар для Crystal
 
Регистрация: 05.07.2007
Сообщений: 4,896
Написано 1,546 полезных сообщений
(для 4,958 пользователей)
Ответ: Очередные вопросы от меня по игровой логике и скриптингу

Сообщение от pax Посмотреть сообщение
А можешь показать пример как ты это используешь? По идее должно работать...



Не обратил внимания, что твой список это GameObject. Вот пример при котором я предполагаю, что у тебя на каждом юните висит одноименный класс Unit:
for(int i FightScene.Units.Count-1i>=0i--)
{
    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 
UnitMonoBehaviour
{
        public 
int health 100;

        public 
bool IsDead => health <= 0;


Пример класса Unit (свойство IsDead в виде обычного свойства только для чтения)
using UnityEngine;

public class 
UnitMonoBehaviour
{
        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
pax
Unity/C# кодер
 
Аватар для pax
 
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,550
Написано 2,991 полезных сообщений
(для 5,297 пользователей)
Ответ: Очередные вопросы от меня по игровой логике и скриптингу

Тогда просто меняй в моем пример Unit на MonsterInfo. Вот тебе еще пример)

for(int i FightScene.Units.Count-1i>=0i--)
{
    
// если в списке уже уничтоженный объект
    
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);
           }
    }

__________________
Blitz3d to Unity Wiki
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
Crystal (18.10.2020)
Старый 18.10.2020, 13:51   #23
Crystal
Терабайт исходников
 
Аватар для Crystal
 
Регистрация: 05.07.2007
Сообщений: 4,896
Написано 1,546 полезных сообщений
(для 4,958 пользователей)
Ответ: Очередные вопросы от меня по игровой логике и скриптингу

Спасибо, на следующей неделе попробую применить.
В данный момент не могу, у меня вчера ОРВИ дало осложнение на глаза
(покраснение, ощущение инородного тела, сморщивание коньюктивы при повороте глаза).
Вчера пришлось отказаться от программирования, закапать глаза, и лечь в постель...
Сегодня наверное тоже не смогу напрягать глаза.
(Offline)
 
Ответить с цитированием
Ответ


Опции темы

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


Часовой пояс GMT +4, время: 05:22.


vBulletin® Version 3.6.5.
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Перевод: zCarot
Style crйe par Allan - vBulletin-Ressources.com