forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   2D/GUI (http://forum.boolean.name/forumdisplay.php?f=167)
-   -   Вызов гуя, есть проблемы. (http://forum.boolean.name/showthread.php?t=20843)

Crystal 18.09.2020 14:45

Вызов гуя, есть проблемы.
 
Короче есть у меня скрипт, который следит за тем чтобы гуй был вкл или выкл.

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

Всё работает до тех пор, пока я не собираюсь при вызванном гуе с монстра
щёлкнуть мышкой в другого монстра, и тут в 30% случаев сначала вызывается гуй, потом сразу скрывается из-за скрипта в предыдущем монстре
(скрипта, который после отображения скрывает гуй по щелчку).
Выглядит как баг, и не приятно. Посоветуйте как лучше организовать процесс, может у кого есть идеи?
Отображение и скрытие должны происходить на одну и ту же клавишу,
и то действие должно быть применимо к любому количеству пропикиваемых лучом монстров.

Я чё-то по ходу на работе заработался, что сейчас вечерами не могу решить такую простую элементарную задачу.

А теперь снова всё то же самое:
К щелчку по монстру привязано отображение гуя, когда гуй отображён,
при любом следующем щелчке срабатывает скрипт скрывающий гуй.
Проблема случается в тот момент, когда уже при отображённом гуе
вызванном на одном монстре, мне вдруг нужно щёлкнуть в другого монстра
и вызвать тот же гуй. В 30% случаев, сначала срабатывает вызов гуя на
новом монстре, и после на предыдущем монстре тот же самый клик мне всё руинит закрывая гуй.

Я знаю, что можно сделать, чтобы только по клику на монстра или на кнопку гуй закрывался,
и после типа мы только получали возможность тыкать в другого монстра, но мне это не подходит,
т.к. это медленный вариант раздражающий игрока, всё должно делаться быстро, и по клику на одну и ту же клавишу.

Вопрос в том, как дать понять скрипту, что раз мы уже на другом монстре гуй вызвали, то на прерыдущем его по щелчку
скрывать не надо. Вроде всё элементарно, тупо, просто. Но это юнити, и он мне что-то мозг сломал,
со своей разбивкой на миллион префабов, и скриптов обрабатываемых в рандомном порядке.
Если бы хотя бы какая-то структура обработки скриптов была на вызванных префабах,
а он рандомом хреначит без последовательности чёткой.

pax 18.09.2020 16:43

Ответ: Вызов гуя, есть проблемы.
 
Я бы не открывал гуй с скрипта на монстре, а открывал гуй тем скриптом, которым ты его скрываешь. Пусть этот скрипт палит где ты кликнул, если - монстр - открой гуй монстра, если другое место - скрыть гуй. Ну и соответственно клик на другом монстре обновит открытый гуй.

PS: еще есть конечно фича явного указания порядка обработки скриптов Script Execution Order, но это только в экстремальных случаях)

Crystal 18.09.2020 20:21

Ответ: Вызов гуя, есть проблемы.
 
Цитата:

Сообщение от pax (Сообщение 317558)
Я бы не открывал гуй с скрипта на монстре, а открывал гуй тем скриптом, которым ты его скрываешь. Пусть этот скрипт палит где ты кликнул, если - монстр - открой гуй монстра, если другое место - скрыть гуй. Ну и соответственно клик на другом монстре обновит открытый гуй.

PS: еще есть конечно фича явного указания порядка обработки скриптов Script Execution Order, но это только в экстремальных случаях)

Гуй отображает и скрывает отдельный скрипт, а скрипты на монстрах
отрабатывают пики лучём и щелчки клавишами, результат отработки
идёт в переменные глобального скрипта, а вот за ними следит скрипт
который скрыванием и отображением гуя занимается,
этот скрипт к префабу юнита не привязан, он привязан к независимому
объекту на сцене.

Представьте стратегию, где куча одинаковых юнитов-префабов,
вот они спавнятся, у них у всех один и тот же скрипт,
который следит за клацаниями мышки, и за лучом.

Проблема грубо говоря в том, что я мышкой юнитов выделяю,
одновременно может быть выделен только один, и вот когда
у меня уже есть выделенный юнит, и я хочу выделить другого
не сбросив выделения с первого, то по логике скрипта когда
я навёл на нового юнита луч и клацнул мышью, в него полетел луч,
что привело к выделению юнита в последствии, но к этой же самой
клавише мышки в скрипте привязано снятие выделения с юнита,
по тому, что мне так надо. Так вот значит у меня уже один выделенный,
я хочу вместо него выделить другого не сбрасывая предварительно
выделения у первого, оно должно само сброситься при выделении нового,
стреляю в нового лучом, он выделяется, появляется гуй, но перед этим
у старого юнита должно произойти снятие выделения, и гуй должен исчезнуть, чтобы у нового он появился,
и это работает в 70% случаев, но в 30% порядок меняется,
случайно, просто юнити решает, а давай ка я сначала займусь
обработкой скрипта вон того юнита, а не этого, и хопа у меня баг,
я на новом юните вместо отображения гуя получаю его скрытие,
по тому что старый юнит кинул переменную закрытия в следящий
за этим делом скрипт.

Блин, я надеюсь доходчиво процесс описываю, мне то понятно что я пишу,
но понятно ли вам неизвестно ))

Короче, я никогда не сталкивался с такими проблемами в блитце,
а ведь у меня есть на нём прототип RTS, но тут же с этими префабами,
и непонятно как обрабатываемыми скриптами я проблему победить
пока не могу.
Я просто не могу задать порядок выполнения процессов в одинаковых
скриптах одинаковых префабах в нужной последовательности
при определённых обстоятельствах.

Рано или поздно я это сделаю, правда даже не представляю что за монстра
мне придётся породить, это будет что-то наверное работающее
через задницу.

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

Добавлю: скрытие гуя реализовано так, что оно может произойти только
на втором прогоне скрипта после выделения юнита, и прописано оно раньше,
чем область кода отвечающая за отображение гуя. По идее, раз скрипт у всех
юнитов одинаковый, и они одинаково отслеживают нажатия клавиши,
то при одновременном срабатывании скрипта везде, сначала по порядку должно
произойти скрытие гуя на старом юните, а после открытие на новом.
Но как я теперь понимаю, юнити обрабатывает одинаковый скрипт на каждом префабе по очереди,
а не одновременно, и очерёдность обработки он выбирает сам по рандому, по воле аллаха.
Если бы мне удалось задать очерёдность обработки скриптов,
понижать и повышать статус важности выполнения,
тогда бы юнити делал то, что мне нужно.
Подчёркиваю, очерёдность обработки одного и того же скрипта на одинаковых префабах.
Можно поставить таймер на отображение гуя в пол секунды, но игрока будет раздражать, это не решение.

Crystal 18.09.2020 23:13

Ответ: Вызов гуя, есть проблемы.
 
Проблему решил за счёт нагрузки движка лишней прокруткой скрипта.
В общем сделал так, что при первом нажатии скрипт запоминает
это действие, прокручивается без вызова гуя, и после он 1 раз
уже сам себя прогоняет без кликания мышки и вызывает гуй.
При этом функция скрытия гуя выполняется сразу в первую
прокрутку скрипта. (а ведь скрытие у нас по условию [не каждый цикл скрипта])
Так-как юнити выбирает у префабов скрипты рандомно,
но с условием, что он не прокрутит скрипт ещё раз, пока
не прокрутит все остальные по разу, а вызов гуя у нас
происходит только на вторую самозапускаемую прокрутку,
то сто процентов скрипт сначала везде по убирает гуй,
потом самозапустится и гуй вызовет. Всё работает.

Сразу по ходу это породило баг, сделавший невозможным
скрытие гуя по клику на уже выделенного монстра, но я эту
проблему решил добавлением ещё одной переменной, и отслеживанием оной.

Crystal 18.09.2020 23:26

Ответ: Вызов гуя, есть проблемы.
 
Механика такова:

Код:

    private int ProgonScripta = 0;
    private int StatusVideleniya = 0;

 void Update()
 {
 |
 |
 |      if (ProgonScripta == 2)
 |      {
 |      |  ProgonScripta = ProgonScripta = 0;
 |      }
 |
 |      if (StatusVideleniya == 2)
 |      {
 |      |  StatusVideleniya = 0;
 |      |  ProgonScripta = 0;
 |      }
 |
 |      //Если нажата ЛКМ
 |      if (Input.GetMouseButtonDown(0) || ProgonScripta == 1)
 |      {
 |      |
 |      |    if (УсловиеСкрытия == 1 && StatusVideleniya == 1) //Функция скрытия
 |      |    {
 |      |    |  StatusVideleniya = 2;
 |      |    }
 |      |
 |      |    if (ProgonScripta == 1 && StatusVideleniya == 0)
 |      |    {
 |      |    |  ProgonScripta = 2;
 |      |    |
 |      |    |  //Здесь мы вызываем гуй
 |      |    |
 |      |    |  StatusVideleniya = 1;
 |      |    }
 |      |
 |      |    if (ProgonScripta == 0)
 |      |    {
 |      |    |  ProgonScripta = ProgonScripta = 1;
 |      |    }
 |      |
 |      }
 }


Crystal 18.09.2020 23:38

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

Crystal 18.09.2020 23:41

Ответ: Вызов гуя, есть проблемы.
 
Так не интересно, уже решил :(

Crystal 19.09.2020 00:05

Ответ: Вызов гуя, есть проблемы.
 
Билд этого всего тут: ТЫК

Мышкой бежим к монстру, выбираем режим "сражаться".
В сцене боя пока все юниты подконтрольны игроку,
можно наспавнить ещё сколько хочешь.
Ну и вот там по тыкайте по выделяйте, по сбрасывайте выделение,
всё должно работать.

pax 21.09.2020 10:07

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


PHP код:

using UnityEngine;

//Скрипт, контролирующий ввод. Например можно повесить на камеру
public class InputManagerMonoBehaviour
{
      
// ссылка на скрипт, контролирующий UI юнита
      
public UnitUIController unitUI;

      
// юнит, выделенный последний раз 
      
private Unit selectedUnit;


      
void Start()
      {
           
unitUI.gameObject.SetActive(false);
      }

      
void Update()
      {
             
// ловим клик левой кнопкой мыши
             
if(Input.GetMouseButtonDown(0))
             {
                   
// рейкаст из точки клика
                   
Ray ray Camera.main.ScreenPointToRay(Input.mousePosition);
                   
RaycastHit hit;

                   
Unit unit null;

                   if (
Physics.Raycast(rayout hitfloat.MaxValue))
                   {
                           
// если кликнули по юниту, то должен быть компонент Unit
                           // иначе функция поиска вернет null
                           
unit hit.collider.gameObject.GetComponentInParent<Unit>();
                   }
                   
// обработка клика (нашли или не нашли юнита)
                   
OnMouseClicked(unit);
             }

      }


      
void OnMouseClicked(Unit unit)
      {
           
// если кликнули в пустоту или по тому же юниту, скрываем UI
           
if(unit == null || unit == selectedUnit)
           {
                 
selectedUnit null;
                 
HideUI();
           }
           else
           {
                 
// кликнули по новому юниту
                 
selectedUnit unit;
                 
ShowOrUpdateUI(unit);
           }
      }

       
// Скрываем интерфейс
       
void HideUI()
       {
             
unitUI.gameObject.SetActive(false);
       }


       
// отображаем или обновляем интерфейс
       
void ShowOrUpdateUI(Unit unit)
       {
              
unitUI.gameObject.SetActive(true);
              
unitUI.UpdateUI(unit);
       }
       



PHP код:

using UnityEngine;
using UnityEngine.UI;

//Скрипт, обновляющий UI на экране, в зависимости от того, какой юнит выбран.
// повесить на корневой объект диалога, отображаемого по клику на юнита
public class UnitUIControllerMonoBehaviour
{
       public 
Text unitName;

       private 
void Uint unit;

       public 
void UpdateUI(Unit unit)
       {
              
// сохраняем ссылку на выделенного юнита, для которого показывается UI, чтобы потом выполнять его функции
              
this.unit unit
              
// отображаем имя выделенного юнита
              
unitName.text unit.displayName;
              
// и другие свойства юнита
       
}


PHP код:

using UnityEngine;

// скрипт юнита (должен висеть на каждом юните)
public class UnitMonoBehaviour
{
       public 
string displayName;


       
// другая логика и параметры юнита



Crystal 21.09.2020 16:55

Ответ: Вызов гуя, есть проблемы.
 
Привет Пакс, спасибо за труд, но это ты зря, я же за теорией только пришёл с конкретной проблемой )
(может в будущем мне понадобится подсмотреть твоё решение, если споткнусь об очередную граблю)

У меня сейчас всё работает как надо, а пример того, как оно работает
я выше описал. (без конкретных участков как мы луч пускаем, и тд). Оно всё так или иначе близко к тому, что ты накодил здесь,
я просто не стал сюда код выкладывать, т.к. он делает ещё много всего помимо включения интерфейса.
Там ещё всякие условия есть, не нашла ли мышь на интерфейс, не сделали ли мы там чё-то ещё.

Однако я считаю твоя работа может быть кому-то полезной,
и это хорошо, контент на форуме.
Стиль у нас конечно кодинга на разном уровне, у меня всё ещё
говнокодинг лютый, а у тебя по симпатичнее )

Если будет интересно, как это работает у меня, код скину,
правда комментариев мало, и есть не удалённый мусор.

----

Ты кстати свой код не испытывал ещё в реалиях? Может тот же баг со скрытием интерфейса вылезет )
Условие : один юнит уже выделен, нам надо выделить другого в 1 клик.
У меня в действительности до моего решения баг вылезал не сразу,
а где-то на шестом\седьмом юните. Так что это ещё наспавнить надо кучу, и прокликивать, чтобы выловить.

pax 21.09.2020 17:07

Ответ: Вызов гуя, есть проблемы.
 
Цитата:

Сообщение от Crystal (Сообщение 317570)
Ты кстати свой код не испытывал ещё в реалиях? Может тот же баг со скрытием интерфейса вылезет )
Условие : один юнит уже выделен, нам надо выделить другого в 1 клик.
У меня в действительности до моего решения баг вылезал не сразу,
а где-то на шестом\седьмом юните. Так что это ещё наспавнить надо кучу, и прокликивать, чтобы выловить.

Для этого в методе OnMouseClicked есть проверки по кому кликнули и сохранение выделенного юнита в поле selectedUnit. Если это новый юнит, то отображение и обновление UI. Если UI уже был отображен, то SetActive ничего не изменит, а обновление UI произойдет. Если клик в пустоту или по тому же юниту, то UI скрывается.

Тестировать не тестировал, прям в браузере писал. Но багов не должно быть, тут все однозначно.

Crystal 21.09.2020 17:39

Ответ: Вызов гуя, есть проблемы.
 
Щас покажу панковский метод:

Скрипт отвечающий и за выделение монстра, и за построение\удаление сетки
полигонов меша внутри ассета, с учётом массива проходимости ячеек:

[предупреждаю - есть мусор, оставленный от предыдущих версий, и тестов - на езду не влияет ))]

Код:

using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using UnityEngine;

public class SetkaHodaMonstra : MonoBehaviour
{

    public GameObject SetkaMobile;
    public Mesh SetkaDvij2;
    public GameObject Monster; //Монстр, которого будем двигать
    public GameObject TipaMonster; //Тело монстра в которого будем тыкать мышкой
    public Camera camera_n; //Камера конечно
    private Vector3 RaycastPickCoordinates; //Конечные координаты падения луча в рейкасте на коллайдер
    private string RaycastObjNow; // Текстовая переменная, содержит имя объекта коллайдер которого попал под луч
    private int TimeFlow; //Состояние времени
    private int SetkaDvijCreator = 0;
    private int SetkaDestroyer = 0;
    private int mxi;
    private int mzi;
    public int Stime; // Количество прокруток цикла высчитывающего X координату ячейки
    private int SetcaCreate = 0;

    private Vector3 Pickposition;
    private Vector3 PickpositionS;

    private int[,] MonHodMass;
    private int[] MonHodYachMass;
    private int SetkaMonHodX = 5;
    private int SetkaMonHodZ = 5;
    private int PloshMonHodXZ;
    private int Xcount = 0;
    private int UniversalCounter = 0; //Универсальный многоразовый счётчик для разных задачь
    private int UniversalCounter2 = 0; //Универсальный многоразовый счётчик для разных задачь
    private int UniversalCounter3 = 0; //Универсальный многоразовый счётчик для разных задачь
    private int Zcounter = 0;

    private float SetkaDvijScaleZ; //Размер сетки по оси "Z". - В флоатах
    private float SetkaDvijScaleX; //размер сетки по оси "X". - В флоатах

    private int SetkaDvijScaleZconstant; //Размер сетки по оси "Z". - Постоянная велечина
    private int SetkaDvijScaleXconstant; //размер сетки по оси "X". - Постоянная велечина

    private int SetkaDvijScaleZ2; //Размер сетки по оси "Z". - В интеджерах
    private int SetkaDvijScaleX2; //размер сетки по оси "X". - В интеджерах
    private int SetcaDvijPloshad2 = 0; //Площадь сетки.
 

    private int PloshCraft;
    private int[] PloshCraftMass;
    private int PloshCraftMassCounter = 0;
    private int PloshCraftFor = 0;
    private int PloX = 0;
    private int PloZ = 1;
    private int Perebor = 0;

    private int SetkaScaleControl = 0;


    private int ZDvij = 0;
    private int XDvij = 0;
    private int UDvij = 0;

    private int VSPX;
    private int VSPZ;


    private int TESTE = 0;


    private int SPK;
    private Vector3[] Vershini1;
    private int[] Bermudes1;
    private Vector2[] TextureCoordinates;
    private int VK = 0;
    private int BR = 0;
    private int SDVIG = 0;
    private int SDVIG2 = 1;

    private int SDVIGX = 0;
    private int SDVIGX2 = 0;
    private int SDVIGFUCK = 0;




    private int ZERO = 0; // Просто ноль, по тому, что мне нужен ноль.
    private int MonCorZ;
    private int MonCorX;
    private int SX;
    private int MHCleanerX = 0;
    private int MHCleanerZ = 0;


    public int MonsterNumber; //Порядковый номер монстра
    public int ThreatLevel; //Уровень угрозы монстра
    public int MonsterControl; //Уровень угрозы монстра
    public MonsterInfo MI; //Скрипт монстра MonsterInfo

    private int ProgonScripta = 0;
    private int StatusVideleniya = 0;

    private float BermudesTimer;

    void Start()
    {

        camera_n = Camera.main;
        TimeFlow = GLOBALSUPERSCRIPT.TimeFlow; //Получаем значение состояния времени
        SetkaMobile.transform.position = new Vector3(0f, 0f, 0f);


    }

    void Update()
    {


        SetcaDvijPloshad2 = SetkaDvijScaleZ2 * SetkaDvijScaleX2;
        PloshCraft = SetcaDvijPloshad2;
        MonHodMass = new int[(SetkaDvijScaleX2 * SetkaDvijScaleZ2) + 1, SetkaDvijScaleZ2 + 1 + SetkaMonHodZ];



        if (SetkaScaleControl == 0)
        {
            if (GLOBALSUPERSCRIPT.LevelScaleStatus == 1)
            {



                SetkaDvijScaleX = GLOBALSUPERSCRIPT.LevelScaleX;
                SetkaDvijScaleZ = GLOBALSUPERSCRIPT.LevelScaleZ;

                SetkaDvijScaleXconstant = Mathf.FloorToInt(SetkaDvijScaleX);
                SetkaDvijScaleZconstant = Mathf.FloorToInt(SetkaDvijScaleZ);


                SetkaDvijScaleX2 = SetkaDvijScaleXconstant;
                SetkaDvijScaleZ2 = SetkaDvijScaleZconstant;

                //Расчёт площади сетки.
                SetcaDvijPloshad2 = SetkaDvijScaleZ2 * SetkaDvijScaleX2;
                PloshCraft = SetcaDvijPloshad2;

                PloshCraftMass = new int[PloshCraft];
                MonHodYachMass = new int[PloshCraft];
                Vershini1 = new Vector3[(SetcaDvijPloshad2 * 6)];
                Bermudes1 = new int[(SetcaDvijPloshad2 * 6)];
                TextureCoordinates = new Vector2[(SetcaDvijPloshad2 * 6)];



                SetkaScaleControl = 1;
            }

        }


        if (TESTE == 0)
        {
            if (SetkaScaleControl == 1)
            {
                if (SetkaPassabilityControl.SetkaScaleControl == 3)
                {
                    TESTE = 1;
                    SetkaScaleControl = 2;
                    SPK = 3;
                }
            }
        }



        //------------------------------------------------------------------------------------------------------------------------------------



        if (ProgonScripta == 2)
        {
            ProgonScripta = ProgonScripta = 0;
        }
 
        if (StatusVideleniya == 2)
        {
            StatusVideleniya = 0;
            ProgonScripta = 0;
        }


        //Если нажата ЛКМ
        if (Input.GetMouseButtonDown(0) || ProgonScripta == 1)
        {
            Debug.Log("ProgonScripta:" + ProgonScripta);

            MonsterControl = MI.MonsterControl; // Статус выделения монстра, по умолчанию "0" не выделен.


                //Сам луч, начинается от позиции камеры и направлен в сторону мыши
                Ray ray = camera_n.ScreenPointToRay(Input.mousePosition);

                //Структура луча, нужна для получения информации из Raycast
                RaycastHit PickRay;

                //Пускаем луч
                Physics.Raycast(ray, out PickRay);

                Debug.DrawLine(ray.origin, PickRay.point, Color.red);

                SetkaDvijScaleX2 = SetkaDvijScaleXconstant;
                SetkaDvijScaleZ2 = SetkaDvijScaleZconstant;

            if (SetkaDestroyer == 1 && SetkaDvijCreator == 3)
            {
                SetkaDvijCreator = 0;
                SetkaDestroyer = 0;
            }

            if (SetkaDestroyer == 1 && StatusVideleniya == 1)
            {
                SetkaDvijCreator = 3;
                Destroy(GetComponent<MeshFilter>().mesh);
                Destroy(GetComponent<MeshCollider>());

                mxi = 0;
                mzi = 0;

                MonCorZ = 0; //Z координаты монстра
                MonCorX = 0; //X координаты монстра


                FightScene.SkillPanelSower = 3;
                StatusVideleniya = 2;


            }




                //Если запустили луч
                if (Physics.Raycast(ray, out PickRay) && FightScene.MonsterVidelStatus == 0)
                {

                    //Получаем координаты пика на коллайдере
                    RaycastPickCoordinates = new Vector3(PickRay.point.x, PickRay.point.y, PickRay.point.z);

                    //Пишем в RaycastObjNow и дебаггер конкретно во что воткнулся луч
                    RaycastObjNow = PickRay.collider.name;


                    if (PickRay.transform.gameObject == TipaMonster)
                    {
                        MI.MonsterControl = 1;

                    }

                    //Если луч попал в SetkaMobile монстра
                    if (PickRay.transform.gameObject == SetkaMobile && MI.MonsterControl == 1 && SetkaDestroyer == 1)

                    {

                        if (UnityEngine.EventSystems.EventSystem.current.IsPointerOverGameObject() == false)
                        {

                            // Высчитываем квадрат, куда движется монстр, чтобы сделать его непроходимым.
                            Stime = Mathf.FloorToInt(PickRay.point.x) - 1;

                            for (ZERO = 0; ZERO < Stime; Stime--)
                            {
                                SX = SX + SetkaDvijScaleZconstant;
                            }

                            if (Mathf.FloorToInt(PickRay.point.x) - 1 < 0)
                            {
                                SX = SX - SetkaDvijScaleZconstant;
                            }
                            SetkaPassabilityControl.Setka[SX + SetkaDvijScaleZconstant, Mathf.FloorToInt(PickRay.point.z) + 1] = 1; // Непроходимый квадрат
                            SX = 0;
                            Stime = 0;
                            //------------------------------------------------------------------------------

                            // Высчитываем квадрат, куда движется монстр, чтобы сделать его проходимым.
                            Pickposition = TipaMonster.transform.position;

                            Stime = Mathf.FloorToInt(Mathf.Floor(Pickposition.x)) - 1;

                            for (ZERO = 0; ZERO < Stime; Stime--)
                            {
                                SX = SX + SetkaDvijScaleZconstant;
                            }

                            if (Mathf.FloorToInt(Mathf.Floor(Pickposition.x)) - 1 < 0)
                            {
                                SX = SX - SetkaDvijScaleZconstant;
                            }
                            SetkaPassabilityControl.Setka[SX + SetkaDvijScaleZconstant, Mathf.FloorToInt(Pickposition.z) + 1] = 0; // Проходимый квадрат
                            SX = 0;
                            Stime = 0;

                            //------------------------------------------------------------------------------
                            if (MI.MonsterControl == 1)
                            {
                                Monster.transform.position = new Vector3(Mathf.Floor(PickRay.point.x) + 0.5f, 0, Mathf.Floor(PickRay.point.z) + 0.5f);
                                MI.MonsterControl = 0;
                            }

                            SetkaMobile.transform.position = new Vector3(0, 0, 0);
                            //Обнуляем RaycastObjNow
                            RaycastObjNow = "NiHuYa";
                            MI.MonsterControl = 0;


                        }



                    }


                }

            if (ProgonScripta == 1 && StatusVideleniya == 0)
            {
                ProgonScripta = 2;

                if (TESTE == 1)
                {

                    if (Physics.Raycast(ray, out PickRay))
                    {
                        if (PickRay.transform.gameObject == TipaMonster && FightScene.SkillActive == 0)

                        {



                            if (SetkaDvijCreator == 0 && MI.MonsterControl == 1)
                            {
                                if (UnityEngine.EventSystems.EventSystem.current.IsPointerOverGameObject() == false)
                                {
                                    SetkaDvijCreator = 1;
                                    SetkaDestroyer = 1;



                                    //Расчёт площади сетки.
                                    SetcaDvijPloshad2 = SetkaDvijScaleZ2 * SetkaDvijScaleX2;

                                    PloshCraft = SetcaDvijPloshad2;
                                    Perebor = SetcaDvijPloshad2 - 1;
                                    PloshCraftMassCounter = 0;
                                    PloX = 0;
                                    PloZ = 1;

                                    for (PloshCraftFor = 0; PloshCraftFor < PloshCraft; PloshCraft--)
                                    {

                                        PloshCraftMass[PloshCraftMassCounter] = SetkaPassabilityControl.Setka[PloX, PloZ];

                                        PloshCraftMassCounter = PloshCraftMassCounter + 1;


                                        PloZ = PloZ + 1;
                                        if (PloZ > SetkaDvijScaleZ2)
                                        {
                                            PloZ = 1;
                                            PloX = PloX + SetkaDvijScaleZ2;
                                        }

                                    }

                                    PloshCraft = SetcaDvijPloshad2;

                                   

                                    // Ищем координаты монстра, и занимаемся поиском координат клеток в радиусе шагания монстра -----
                                    Pickposition = TipaMonster.transform.position;
                                    mxi = Mathf.CeilToInt(Pickposition.x);
                                    mzi = Mathf.CeilToInt(Pickposition.z);

                                    MonCorZ = mzi; //Z координаты монстра
                                    MonCorX = mxi; //X координаты монстра

                                    MonCorZ = (MonCorZ - (SetkaMonHodZ / 2)); //Z координата точки отсчёта построения сетки ходьбы
                                    MonCorX = (MonCorX - (SetkaMonHodX / 2)); //X координата точки отсчёта построения сетки ходьбы


                                    MonCorX = MonCorX - 1; //X координаты монстра, еденицу отнимаем, чтобы воспользоваться формулой для расчёта X координаты номера ячейки

                                    PloshCraft = SetcaDvijPloshad2;
                                    PloshCraftMassCounter = 0;
                                    PloshMonHodXZ = SetkaMonHodX * SetkaMonHodZ;



                                    Xcount = MonCorX;

                                    if (Xcount > 0)
                                    {
                                        for (ZERO = 0; ZERO < Xcount; Xcount--)
                                        {
                                            SX = SX + SetkaDvijScaleZ2;

                                        }
                                    }

                                    if (Xcount <= 0)
                                    {
                                        for (ZERO = 0; ZERO > Xcount; Xcount++)
                                        {
                                            SX = SX - SetkaDvijScaleZ2;
                                        }

                                    }


                                    UniversalCounter2 = SetkaMonHodX;
                                    UniversalCounter3 = SetkaMonHodZ;
                                    UniversalCounter = 0;
                                    Zcounter = 0;

                                    for (ZERO = 0; ZERO < UniversalCounter3; UniversalCounter3--)
                                    {
                                        for (ZERO = 0; ZERO < UniversalCounter2; UniversalCounter2--)
                                        {
                                            if ((SX + Zcounter + MonCorZ) <= PloshCraft && (SX + Zcounter + MonCorZ) >= 0 - SX - Zcounter - SetkaDvijScaleZ2 && (MonCorZ + UniversalCounter) >= 0 && (MonCorZ + UniversalCounter) <= SetkaDvijScaleZ2)
                                            {

                                                MonHodMass[SX + Zcounter, MonCorZ + UniversalCounter] = 3;
                                            }
                                            UniversalCounter = UniversalCounter + 1;

                                            if (UniversalCounter > (SetkaMonHodX - 1))
                                            {
                                                UniversalCounter = 0;
                                            }
                                        }

                                        Zcounter = Zcounter + SetkaDvijScaleZ2;
                                        UniversalCounter2 = SetkaMonHodX;

                                    }

                                    Zcounter = 0;
                                    SX = 0;
                                    UniversalCounter = 0;
                                    UniversalCounter2 = 0;
                                    UniversalCounter3 = 0;








                                    PloX = 0;
                                    PloZ = 1;

                                    for (PloshCraftFor = 0; PloshCraftFor < PloshCraft; PloshCraft--)
                                    {
                                        MonHodYachMass[PloshCraftMassCounter] = MonHodMass[PloX, PloZ];

                                        PloshCraftMassCounter = PloshCraftMassCounter + 1;


                                        PloZ = PloZ + 1;
                                        if (PloZ > SetkaDvijScaleZ2)
                                        {
                                            PloZ = 1;
                                            PloX = PloX + SetkaDvijScaleZ2;
                                        }
                                    }


                                    //-----------------------------------------------------------------------------------------------
                               




                                    SDVIGX = SetkaDvijScaleX2;


                                    SetkaDvij2 = new Mesh();
                                    //Создаём меш.

                                    //Подключаем меш фильтр.
                                    MeshFilter SetkaDvijFilter2 = GetComponent<MeshFilter>();
                                    //Применяем мешфильтр к мешу.
                                    SetkaDvijFilter2.mesh = SetkaDvij2;



                                    TESTE = 2;


                                }
                            }
                        }
                    }



                }

            }
                if (SPK == 3 && TESTE == 2)
                {

                    BR = 0;
                    SDVIG = 0;
                    SDVIG2 = 1;
                    SDVIGX2 = 0;
                    SDVIGFUCK = 0;


                    //Получаем номера скиллов монстра
                    FightScene.SkillButton1 = MI.MonsterSkill1;
                    FightScene.SkillButton2 = MI.MonsterSkill2;
                    FightScene.SkillButton3 = MI.MonsterSkill3;
                    FightScene.SkillButton4 = MI.MonsterSkill4;
                    FightScene.SkillButton5 = MI.MonsterSkill5;
                    FightScene.SkillButton6 = MI.MonsterSkill6;

                    //Получаем радиус атаки скиллов монстра
                    FightScene.SkillRange1 = MI.MonsterSkill1Range;
                    FightScene.SkillRange2 = MI.MonsterSkill2Range;
                    FightScene.SkillRange3 = MI.MonsterSkill3Range;
                    FightScene.SkillRange4 = MI.MonsterSkill4Range;
                    FightScene.SkillRange5 = MI.MonsterSkill5Range;
                    FightScene.SkillRange6 = MI.MonsterSkill6Range;

                    FightScene.SkillLoad = 1; // Статус получения скиллов.
                                              //-----------------------------------------

                    FightScene.SkillPanelSower = 1;

                    FightScene.AttacCor = TipaMonster.transform.position;

                StatusVideleniya = 1;

                    //Циклы создания сетки исходя из её размера по оси "z" и оси "x" а так же её площади.



                for (ZDvij = 0; ZDvij < SetkaDvijScaleZ2; SetkaDvijScaleZ2--)
                    {


                        for (XDvij = 0; XDvij < SetkaDvijScaleX2; SetkaDvijScaleX2--)

                        {

                            for (UDvij = 0; UDvij < SetcaDvijPloshad2; SetcaDvijPloshad2--)
                            {



                                if (MonHodYachMass[Perebor] == 3 && PloshCraftMass[Perebor] == 0)
                                {
                                    // Пишем координаты вершин в массив
                                    Vershini1[VK] = new Vector3(SetkaDvijScaleX2 - SDVIG2, SetkaDvijScaleZ2 - SDVIGFUCK, 0);
                                    Vershini1[VK + 1] = new Vector3(SetkaDvijScaleX2 - SDVIG, SetkaDvijScaleZ2 - 1 - SDVIGFUCK, 0);
                                    Vershini1[VK + 2] = new Vector3(SetkaDvijScaleX2 - SDVIG2, SetkaDvijScaleZ2 - 1 - SDVIGFUCK, 0);

                                    Vershini1[VK + 3] = new Vector3(SetkaDvijScaleX2 - SDVIG, SetkaDvijScaleZ2 - SDVIGFUCK, 0);
                                    Vershini1[VK + 4] = new Vector3(SetkaDvijScaleX2 - SDVIG, SetkaDvijScaleZ2 - 1 - SDVIGFUCK, 0);
                                    Vershini1[VK + 5] = new Vector3(SetkaDvijScaleX2 - SDVIG2, SetkaDvijScaleZ2 - SDVIGFUCK, 0);

                                    // Пишем текстурные координаты в массив
                                    TextureCoordinates[VK] = new Vector2(SetkaDvijScaleX2 - SDVIG2, SetkaDvijScaleZ2 - SDVIGFUCK);
                                    TextureCoordinates[VK + 1] = new Vector2(SetkaDvijScaleX2 - SDVIG, SetkaDvijScaleZ2 - 1 - SDVIGFUCK);
                                    TextureCoordinates[VK + 2] = new Vector2(SetkaDvijScaleX2 - SDVIG2, SetkaDvijScaleZ2 - 1 - SDVIGFUCK);
                                    TextureCoordinates[VK + 3] = new Vector2(SetkaDvijScaleX2 - SDVIG, SetkaDvijScaleZ2 - SDVIGFUCK);
                                    TextureCoordinates[VK + 4] = new Vector2(SetkaDvijScaleX2 - SDVIG, SetkaDvijScaleZ2 - 1 - SDVIGFUCK);
                                    TextureCoordinates[VK + 5] = new Vector2(SetkaDvijScaleX2 - SDVIG2, SetkaDvijScaleZ2 - SDVIGFUCK);

                                    // Обнуляем номерные массивы проходимости ячеек

                                    MonHodYachMass[Perebor] = 0;
                                    PloshCraftMass[Perebor] = 0;
                                    SetcaCreate = 1;
                                }

                                Perebor = Perebor - 1;


                                VK = VK + 6;

                                SDVIG = SDVIG + 1;
                                SDVIG2 = SDVIG2 + 1;
                                SDVIGX2 = SDVIGX2 + 1;


                                if (SDVIGX2 == SDVIGX)
                                {
                                    SDVIGX2 = 0;
                                    SDVIGFUCK = SDVIGFUCK + 1;
                                }


                                if (SDVIG == SDVIGX)
                                {
                                    SDVIG = 0;
                                }

                                if (SDVIG2 == SDVIGX + 1)
                                {
                                    SDVIG2 = 1;
                                }



                                //Создаём массив с трианглами.

                                Bermudes1[BR] = 0 + BR;
                                Bermudes1[BR + 1] = 2 + BR;
                                Bermudes1[BR + 2] = 1 + BR;
                                Bermudes1[BR + 3] = 3 + BR;
                                Bermudes1[BR + 4] = 5 + BR;
                                Bermudes1[BR + 5] = 4 + BR;
                                BR = BR + 6;



                            }

                        }
                    }

                    if (TESTE == 2 && SetcaDvijPloshad2 == 0)
                    {


                        SetkaDvijScaleX2 = SetkaDvijScaleXconstant;
                        SetkaDvijScaleZ2 = SetkaDvijScaleZconstant;

                        //Задаём вершины мешу.
                        SetkaDvij2.vertices = Vershini1;
                        //Создаём трианглы меша.
                        SetkaDvij2.triangles = Bermudes1;
                        SetkaDvij2.uv = TextureCoordinates;

                        SetkaDvij2.RecalculateBounds();
                        SetkaDvij2.RecalculateNormals();
                        SetkaDvij2.RecalculateTangents();

                        if (SetcaCreate == 1)
                        {
                            MeshCollider MeshColl = SetkaMobile.AddComponent(typeof(MeshCollider)) as MeshCollider;
                            MeshColl.sharedMesh = SetkaDvij2;
                        }
                        SetcaCreate = 0;
                        TESTE = 1;
                        Pickposition = TipaMonster.transform.position;

                        VK = VK - 1;
                        for (ZERO = 0; ZERO < VK; VK--)
                        {
                            Vershini1[VK] = new Vector3(0, 0, 0);
                        }

                        BR = BR - 1;
                        for (ZERO = 0; ZERO < BR; BR--)
                        {
                            Bermudes1[BR] = 0;
                        }


                        SetcaDvijPloshad2 = SetkaDvijScaleZ2 * SetkaDvijScaleX2;
                        PloshCraft = SetcaDvijPloshad2 - 1;

                        for (ZERO = 0; ZERO < PloshCraft; PloshCraft--)
                        {
                            MonHodYachMass[PloshCraft] = 5;
                        }


                        SetcaDvijPloshad2 = SetkaDvijScaleZ2 * SetkaDvijScaleX2;
                        PloshCraft = SetcaDvijPloshad2 - 1;

                        for (ZERO = 0; ZERO < PloshCraft; PloshCraft--)
                        {
                            PloshCraftMass[PloshCraft] = 5;
                        }


                        MHCleanerX = (SetkaDvijScaleX2 * SetkaDvijScaleZ2) + 1 - 1;
                        MHCleanerZ = SetkaDvijScaleZ2 + 1 + SetkaMonHodZ - 1;

                        for (ZERO = 0; ZERO < MHCleanerX; MHCleanerX--)
                        {
                            for (ZERO = 0; ZERO < MHCleanerZ; MHCleanerZ--)
                            {
                                MonHodMass[MHCleanerX, MHCleanerZ] = 0;
                            }
                        }
                    }

                }



                if (ProgonScripta == 0)
            {
                ProgonScripta = ProgonScripta = 1;
            }


        }

   
    }
}

Скрипт отвечающий за отображение и скрывание нужного куска гуя (не весь):

Код:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SkillPanelSkrivator : MonoBehaviour
{
    public float Timer = 0f;
    public GameObject SkillPanel;
    // Start is called before the first frame update
    void Start()
    {
        SkillPanel.gameObject.SetActive(false); //Скрываем панель скиллов 
    }

    void Update()
    {



        if (FightScene.SkillPanelSower == 4)
        {
            Debug.Log("FightScene.SkillPanelSower" + FightScene.SkillPanelSower);
            FightScene.SkillPanelSower = 0;
            Debug.Log("FightScene.SkillPanelSower" + FightScene.SkillPanelSower);
            SkillPanel.gameObject.SetActive(false); //Скрываем панель скиллов 
        }

        if (FightScene.SkillPanelSower == 1)
        {
            Debug.Log("FightScene.SkillPanelSower" + FightScene.SkillPanelSower);
            FightScene.SkillPanelSower = 0;
            Debug.Log("FightScene.SkillPanelSower" + FightScene.SkillPanelSower);
            SkillPanel.gameObject.SetActive(true); //Отображаем панель скиллов 
        }

        if (FightScene.SkillPanelSower == 3)
        {
            Debug.Log("FightScene.SkillPanelSower" + FightScene.SkillPanelSower);
            FightScene.SkillPanelSower = 0;
            Debug.Log("FightScene.SkillPanelSower" + FightScene.SkillPanelSower);
            if (UnityEngine.EventSystems.EventSystem.current.IsPointerOverGameObject() == false)
            {
                SkillPanel.gameObject.SetActive(false); //Скрываем панель скиллов 
            }

        }


    }
}

Скрипт с глобальными переменными, в который мы часто обращаемся:

Код:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public static class FightScene
{


    public static int coins = 100;

    public static int SkillPanelSower = 0;

    public static int Summoning = 0; // Строим сетку призыва монстра, переменная отвечает за запуск скрипта создания оной
    public static int SummSost = 0; // Состояние алгоритма вызова скрипта построения сетки призыва монстра
    public static int SummDel = 0; // Состояние алгоритма вызова скрипта построения сетки призыва монстра, конкретно параметр удаления сетки
    public static int YachClick = 0; // Номер ячейки на панели шорткатов.

    public static int SkillButton1 = 0; // Кнопка скилла 1.
    public static int SkillButton2 = 0; // Кнопка скилла 2.
    public static int SkillButton3 = 0; // Кнопка скилла 3.
    public static int SkillButton4 = 0; // Кнопка скилла 4.
    public static int SkillButton5 = 0; // Кнопка скилла 5.
    public static int SkillButton6 = 0; // Кнопка скилла 5.

    public static int SkillRange1 = 0; // Кнопка скилла 1.
    public static int SkillRange2 = 0; // Кнопка скилла 2.
    public static int SkillRange3 = 0; // Кнопка скилла 3.
    public static int SkillRange4 = 0; // Кнопка скилла 4.
    public static int SkillRange5 = 0; // Кнопка скилла 5.
    public static int SkillRange6 = 0; // Кнопка скилла 5.

    public static int SkillLoad = 0; // Кнопка скилла 5.

    public static int SkillCreate = 0; // Строим сетку радиуса действия скила, переменная отвечает за запуск скрипта создания оной
    public static int SkillSost = 0; // Состояние алгоритма вызова скрипта построения сетки радиуса действия скила
    public static int SkillDel = 0; // Состояние алгоритма вызова скрипта построения сетки радиуса действия скила, конкретно параметр удаления сетки
    public static int SkillPanelClick = 0; // Номер ячейки на панели скилов
    public static Vector3 AttacCor; //Координаты атакующего
    public static Vector3 MishenCor; //Координаты мишени

    public static int SkillActive = 0; // Активный скилл, он выбран на панели скиллов.
    public static int SkillActiveRange = 0; // Радиус области атаки активным скиллом, нужен для измерения расстояния от атакующего монстра до атакуемого.
    public static int MonsterVidelStatus = 0; // Статус выделения монстра, проверяем выделен ли кто.
}

Наверное у опытного программиста от говнокодинга сейчас вытекут глаза,
однако этот код исправно функционирует, и довольно быстро )

pax 21.09.2020 17:54

Ответ: Вызов гуя, есть проблемы.
 
Много сложного кода :) . Но судя по последнему небольшому скрипту (SkillPanelSkrivator), он мониторит переменные и делает что-то на их основе.
Проблема может быть в том, что ты в блоках if не завершаешь логику (не делаешь return). Т.е. у тебя каждый Update всегда проверяются все три блока if.

Ну и в дополнение - избавляйся от магических чисел, используй энамы или константы.

pax 21.09.2020 18:00

Ответ: Вызов гуя, есть проблемы.
 
Цитата:

Сообщение от Crystal (Сообщение 317573)
Наверное у опытного программиста от говнокодинга сейчас вытекут глаза,
однако этот код исправно функционирует, и довольно быстро )

Ну да, что-то все сильно переусложнено. Вспомнился анегдот - работает не трожь!)

Crystal 21.09.2020 18:11

Ответ: Вызов гуя, есть проблемы.
 
Цитата:

Сообщение от pax (Сообщение 317574)
Много сложного кода :) . Но судя по последнему небольшому скрипту (SkillPanelSkrivator), он мониторит переменные и делает что-то на их основе.
Проблема может быть в том, что ты в блоках if не завершаешь логику (не делаешь return). Т.е. у тебя каждый Update всегда проверяются все три блока if.

Ну и в дополнение - избавляйся от магических чисел, используй энамы или константы.

Да я состояния чего-либо держу в отдельных переменных цифрами. (иногда буквами)
Когда апдейт докручивает до определённого if, он внутри скобок
проверяет условие, в каком состоянии находится интересующая нас переменная,
и при удовлетворительном результате запускает весь код в фигурных скобках.

Цитата:

Сообщение от pax (Сообщение 317575)
Ну да, что-то все сильно переусложнено. Вспомнился анегдот - работает не трожь!)

Это обычно про автомобильные механизмы ))
Фраза защищающая от рукожопых исследователей )

pax 22.09.2020 13:26

Ответ: Вызов гуя, есть проблемы.
 
В общем несколько советов (в порядке важности):

1. Не делать такие большие методы (как например Update класса SetkaHodaMonstra), а разделять на более мелкие методы. Это повысит читабельности коду и даст кускам кода имена (наименования методов). Для повышение читабельности так же можно использовать автоформат кода в Visual Studio (сочетание клавиш Ctrl+E, D или через меню Правка-Дополнительно-Форматировать документ).

2. Выносить специфические вещи в отдельные классы, не обязательно MonoBehaviour, а просто классы, выполняющие какую-то цель. Например генерацию меша сетки. Ну а если код отвечает за работу какого-то игрового объекта, то делать отдельный скрипт (MonoBehaviour) для этого объекта. Пусть свои функции он выполняет сам, а извне им только управлять (вызывать его методы, менять значения его открытых полей).

3. Избавляться от магических чисел. В коде много чисел, которые непонятно для чего служат. Лучше создавать константы с осмысленными именами для этих чисел и в коде применять эти константы. Если число определяет состояние, то использовать enum для задания состояний. Например FightScene.SkillPanelSower присваиваются какие-то значения и потом проверяются. Это просто числа, хз что они значат. Можно было бы сделать так:

PHP код:

public enum SkillPanelState
{
     
Hidden,
     
SkillsPanel,
     
ActionsPanel
}

public static 
SkillPanelState SkillPanelSower SkillPanelState.Hidden;

....
// где-то в коде
switch(FightScene.SkillPanelSower)
{
     case 
SkillPanelState.Hidden
          
//Скрыть панель, если не скрыта
          
break;
     case 
SkillPanelState.SkillsPanel
          
//Отобразить панель скилов, если скрыта или отображается что-то другое
          
break;
     case 
SkillPanelState.ActionsPanel
          
//Отобразить панель действий или еще чего-то, если скрыта или отображается что-то другое
          
break;


4. Использовать массивы или списки, вместо подобного кода:

PHP код:

public static int SkillButton1 0// Кнопка скилла 1.
    
public static int SkillButton2 0// Кнопка скилла 2.
    
public static int SkillButton3 0// Кнопка скилла 3.
    
public static int SkillButton4 0// Кнопка скилла 4.
    
public static int SkillButton5 0// Кнопка скилла 5.
    
public static int SkillButton6 0// Кнопка скилла 5.

    
public static int SkillRange1 0// Кнопка скилла 1.
    
public static int SkillRange2 0// Кнопка скилла 2.
    
public static int SkillRange3 0// Кнопка скилла 3.
    
public static int SkillRange4 0// Кнопка скилла 4.
    
public static int SkillRange5 0// Кнопка скилла 5.
    
public static int SkillRange6 0// Кнопка скилла 5. 


5. Не искал в коде дублирование данных, но если оно есть, то этого стоит избегать. Если в сцене есть какие-то скрипты на объектах, то их всегда можно найти и получить с них данные с помощью методов FindObjectOfType<T> или FindObjectsOfType<T>. Имея ссылку на объект в виде GameObject или другого компонента этого объекта можно всегда получить другие компоненты с этого объекта с помощью методов GetComponent<T> или GetComponentInChildren<T>. Если объект имеет несколько одинаковых компонентов, то есть аналогичные методы, возвращающие массивы компонентов GetComponents<T> или GetComponentsInChildren<T>.

6. Не создавать универсальные переменные. По типу таких:
PHP код:

private int UniversalCounter 0//Универсальный многоразовый счётчик для разных задачь
    
private int UniversalCounter2 0//Универсальный многоразовый счётчик для разных задачь
    
private int UniversalCounter3 0//Универсальный многоразовый счётчик для разных задачь 

Лучше создавать переменные в том месте, где они используются и давать им имена в этом контексте.

7. Первый раз вижу в коде использование ZERO как нуля) Но если даже так, то это константа, тогда она должна быть объявлена так:
PHP код:

private const int ZERO 0// Просто ноль, по тому, что мне нужен ноль. 

В таком случае не получится случайно этой переменной присвоить значение. Но тогда правда все твои циклы будут выдавать ошибку компиляции, потому что везде ты присваиваешь этой переменной значение 0. Хочу заметить, что цикл for может не иметь какую либо часть. Т.е. можно свободно заменить
PHP код:

for (ZERO 0ZERO StimeStime--)
{
      
SX SX SetkaDvijScaleZconstant;


на
PHP код:

for (; ZERO StimeStime--)
{
    
SX SX SetkaDvijScaleZconstant;


или на более понятный вариант - цикл while
PHP код:

while(ZERO Stime)
{
    
SX SX SetkaDvijScaleZconstant;
    
Stime--;



Все, завязываю с советами )

Crystal 22.09.2020 17:34

Ответ: Вызов гуя, есть проблемы.
 
1. Этот метод генерирует сетку из полигонов,
так-как генерация происходит одновременно с выделением
монстра, эти обе функции вдолблены в один скрипт.
Выглядит громоздко, по тому что идёт много расчётов,
так-как сгенерировать полигоны в нужных местах с
учётом непроходимых зон не так то просто.
Скрипт громоздкий ещё и по тому, что я перевожу в нём
координатную систему в номерную, то есть буквально
точки координат в номера ячеек на сетке.

Я придумал формулу, по которой точку в двумерном графике XY
можно перевести в номер ячейки. ((X * Yмакс) - Yмакс) + Y
Расчёт по точкам графика от нуля (X=0, Y=0) до любых положительных чисел.

Мне это нужно, так как при пике лучом я получаю координаты объекта,
которые округляю, а строю сетку в циклах по номерам ячеек.

Про скрипты на монстре, далеко не всё в одном файле, даже близко нет.
Например стрельба скиллом это другой скрипт,
генерация сетки радиуса удара другой, подворачивающий
монстра на камеру другой, скрипты интерфейса тоже отдельные.
Я чисто всё в один скрипт не луплю.

2. С классами я лично осваивая юнити так и не понял нафига
их плодить, если всё прекрасно в монобехавере живёт.
Этот момент поясни.

3. Ну это со стороны непонятно, а автор этого кода знает что они значат )
Для работы в команде программистов я думаю это важно,
но когда код для себя, так сказать не опен, то собственно нет.
Насчёт свитчей мне уже указывали ранее на булке, и я эту технологию
внедрил в том моменте, про который говорили, но тем не менее наблюдая
не увидел никаких преимуществ, ни в скорости работы, ни в принципе.
По этому в основном набирая быстро код мне проще накидать ifов, чем этот список строить.

4. Снова списки и массивы. Я конечно по всякому пробовал, но опять таки
ни прироста скорости обработки, ни какой-то другой пользы не нашёл.
Массивы использую там где огромное количество чисел надо хранить,
или ещё чего, но там где их до шести например, куда нагляднее
и удобнее впихнуть шесть переменных столбиком лично мне.

5. Универсальные переменные те подразумевают то,
что ни при каких условиях одна и та же переменная
не будет использоваться в разных местах одновременно.
Смысл был сократить количество переменных в коде,
если делать отдельные по месту то их получится в разы больше.
Это тупо счётчики.

6. Что изменится? Это постоянное число. Случайное присвоение исключено,
я же знаю что это ноль, который должен быть нолём )

7. На счёт "for" все три варианта почти одно и то же,
это уже вкусовщина. Но первый вариант исключение,
так-как тут мы можем использовать любую другую переменную,
и проверять её состояние (число), "а вдруг не ноль?" )

---
Твои советы интересны, продолжай )

pax 23.09.2020 07:59

Ответ: Вызов гуя, есть проблемы.
 
Цитата:

Сообщение от Crystal (Сообщение 317582)
2. С классами я лично осваивая юнити так и не понял нафига
их плодить, если всё прекрасно в монобехавере живёт.
Этот момент поясни.

Ну тут много говорить можно, но вот: SOLID, а конкретно - принцип единственной ответственности.

Цитата:

Сообщение от Crystal (Сообщение 317582)
5. Универсальные переменные те подразумевают то,
что ни при каких условиях одна и та же переменная
не будет использоваться в разных местах одновременно.
Смысл был сократить количество переменных в коде,
если делать отдельные по месту то их получится в разы больше.
Это тупо счётчики.

Экономия на количестве переменных - странная экономия, если она добавляет неразберихи в коде. Лучше создать переменную в месте ее использования, особенно счетчики. После выхода из области действия они уничтожаются и работают на стеке процессора, что очень быстро.

Цитата:

Сообщение от Crystal (Сообщение 317582)
6. Что изменится? Это постоянное число. Случайное присвоение исключено,
я же знаю что это ноль, который должен быть нолём )

Подход странный, я написал как это делают обычно)

Цитата:

Сообщение от Crystal (Сообщение 317582)
7. На счёт "for" все три варианта почти одно и то же,
это уже вкусовщина. Но первый вариант исключение,
так-как тут мы можем использовать любую другую переменную,
и проверять её состояние (число), "а вдруг не ноль?" )

В твоем случае одинарное равно - это присвоение переменной ZERO значения. Тут никакого сравнения с нулем нет. Сравнение - двойное равно "==".

Crystal 23.09.2020 14:10

Ответ: Вызов гуя, есть проблемы.
 
Цитата:

вдруг не ноль?" )
В твоем случае одинарное равно - это присвоение переменной ZERO значения. Тут никакого сравнения с нулем нет. Сравнение - двойное равно "==".
________________
Действительно, в этом моменте я лохонулся.
Вместо сравнения с нулём нулю присвоил ноль )

ABTOMAT 23.09.2020 22:43

Ответ: Вызов гуя, есть проблемы.
 
Цитата:

Сообщение от Crystal (Сообщение 317582)
3. Ну это со стороны непонятно, а автор этого кода знает что они значат )
Для работы в команде программистов я думаю это важно,
но когда код для себя, так сказать не опен, то собственно нет.
Насчёт свитчей мне уже указывали ранее на булке, и я эту технологию
внедрил в том моменте, про который говорили, но тем не менее наблюдая
не увидел никаких преимуществ, ни в скорости работы, ни в принципе.
По этому в основном набирая быстро код мне проще накидать ifов, чем этот список строить.

Это классический антипаттерн "Magic Numbers", поищи по этому запросу в Интернете, думаю, что ты найдёшь много хороших разъяснений, что это такое, и почему так делать не надо.

Если кратко, то вот что я бы лично для себя выделил:
  • Часто бывает нужно потом эти числа поменять, и удобнее, если они все будут находиться где-то в одном месте, а не искать, где они у тебя по коду раскиданы.
  • Часто бывает, что одну и ту же константу (или переменную) ты используешь потом ещё где-то, и тогда уже придётся следить, чтобы они в двух местах были одинаковы. При использовании "магических чисел" это ещё один фактор, по причине которого можно лохануться, а потом искать причину.
  • Свой код кроме тебя самого, даже если ты работаешь не в команде, будешь читать ещё и ты сам, но спустя месяц, например. Вот попробуй открой какой-нибудь старый проект, который ты как минимум уже месяц не открывал, и попытайся вспомнить, что же это число означает, и почему оно именно такое?

Конечно же, доводить до полного абсолюта эту идею тоже не надо.
Если где-то нет других вариантов, то пишем число.
Например, если надо что-то обнулить, то, понятное дело, нельзя обнулить что-то с числом 2.71. Обнуляют всегда с нулём. Поэтому и пишем просто 0, других вариантов нет, надобности заводить переменную "zero" тоже нет.

Циклы for бывают чаще всего с 0, но бывают и с 1, но там тоже обычно нет вариантов. Поэтому переменные "zero" и "one" тоже не нужны.

Бывает ещё чего-то нужно вдвое больше, например, если ты располагаешь какой-то объект по центру чего-то, и поэтому его надо сдвинуть ровно на половину его ширины. Поэтому мы умножаем её на 0.5 (ну или делим на 2, кому как больше нравится). Любое другое значение будет означать, что объект поставится криво. Поэтому пишем само число.

В качестве исключения ещё можно назвать какой-нибудь временный код, по типу for(int i=0; i<10; i++) createEnemy(); где ты, допустим, чисто для теста хочешь создать чего-нибудь 10 штук, потестить и удалить. Т.е. этот код не предполагается, что будет "жить" сколько-нибудь долго, и когда ты доделаешь функцию до конца, ты это удалишь.

В-общем, если обобщить, то идея такая: если есть (даже теоретическая) возможность подгонки числа, то хорошим тоном будет завести под него переменную или константу. Особенно если стороннему человеку не очень понятно с первого взгляда, а что это число означает. Тогда в названии переменной будет подсказка, что это число делает, что сэкономит читающему время. Помни, что читающим твой код и не понимающим, что он делает, будешь ты сам спустя долгое время.

И только если вариантов никаких других нет вообще, тогда можно написать само число (обычно это -1, 0, 1, 2, 0.5).


Всё, что-то я растёкся мыслию по древу и разумничался, за сим откланиваюсь.

Crystal 24.09.2020 11:35

Ответ: Вызов гуя, есть проблемы.
 
Цитата:

Сообщение от ABTOMAT (Сообщение 317592)
Это классический антипаттерн "Magic Numbers", поищи по этому запросу в Интернете, думаю, что ты найдёшь много хороших разъяснений, что это такое, и почему так делать не надо.

Если кратко, то вот что я бы лично для себя выделил:
  • Часто бывает нужно потом эти числа поменять, и удобнее, если они все будут находиться где-то в одном месте, а не искать, где они у тебя по коду раскиданы.
  • Часто бывает, что одну и ту же константу (или переменную) ты используешь потом ещё где-то, и тогда уже придётся следить, чтобы они в двух местах были одинаковы. При использовании "магических чисел" это ещё один фактор, по причине которого можно лохануться, а потом искать причину.
  • Свой код кроме тебя самого, даже если ты работаешь не в команде, будешь читать ещё и ты сам, но спустя месяц, например. Вот попробуй открой какой-нибудь старый проект, который ты как минимум уже месяц не открывал, и попытайся вспомнить, что же это число означает, и почему оно именно такое?

Конечно же, доводить до полного абсолюта эту идею тоже не надо.
Если где-то нет других вариантов, то пишем число.
Например, если надо что-то обнулить, то, понятное дело, нельзя обнулить что-то с числом 2.71. Обнуляют всегда с нулём. Поэтому и пишем просто 0, других вариантов нет, надобности заводить переменную "zero" тоже нет.

Циклы for бывают чаще всего с 0, но бывают и с 1, но там тоже обычно нет вариантов. Поэтому переменные "zero" и "one" тоже не нужны.

Бывает ещё чего-то нужно вдвое больше, например, если ты располагаешь какой-то объект по центру чего-то, и поэтому его надо сдвинуть ровно на половину его ширины. Поэтому мы умножаем её на 0.5 (ну или делим на 2, кому как больше нравится). Любое другое значение будет означать, что объект поставится криво. Поэтому пишем само число.

В качестве исключения ещё можно назвать какой-нибудь временный код, по типу for(int i=0; i<10; i++) createEnemy(); где ты, допустим, чисто для теста хочешь создать чего-нибудь 10 штук, потестить и удалить. Т.е. этот код не предполагается, что будет "жить" сколько-нибудь долго, и когда ты доделаешь функцию до конца, ты это удалишь.

В-общем, если обобщить, то идея такая: если есть (даже теоретическая) возможность подгонки числа, то хорошим тоном будет завести под него переменную или константу. Особенно если стороннему человеку не очень понятно с первого взгляда, а что это число означает. Тогда в названии переменной будет подсказка, что это число делает, что сэкономит читающему время. Помни, что читающим твой код и не понимающим, что он делает, будешь ты сам спустя долгое время.

И только если вариантов никаких других нет вообще, тогда можно написать само число (обычно это -1, 0, 1, 2, 0.5).


Всё, что-то я растёкся мыслию по древу и разумничался, за сим откланиваюсь.

Много буков.

Я открываю свои коды тринадцатилетней давности, и сразу понимаю что к чему в них.
По текущему проекту передышки по 2 месяца, возвращаюсь ничего не помня,
открываю и вижу как это работает, а важные переменные подписаны.
Для меня всё сразу очевидно, что куда как, т.к. создано мной,
и работает по моей логике, собственно мой код это то, как я мыслю.
На то как читают мой код другие мне абсолютно по барабану,
т.к. соло проект, и мне не нужно работать над тем,
чтобы кто-то понял внутряк. Проект не будет опен.

Собственно, работаю как мне удобно. Я придерживаюсь двух задач,
это быстрота работы кода, и скорость его реализации.
Красота, читаемость для других, какие-то там нормы морали
программерские меня не интересуют, правда.

Я знаю что есть некие каноны кодинга, и даже могу по канону,
но вот насрать вообще, до тех пор пока мне удобно, и пока я понимаю
что у меня там в строках происходит ))

Это ребята всё равно, что спорить о том, как правильно задницу вытирать,
сверху вниз, или снизу вверх, зевой плюс, или лопухом )

Давайте уже не будем флудить по теме, я задачу решил по своему,
на будущее висит решение пакса, к которому я в каком-либо моменте
возможно обращусь ещё.

Ну а про нормы морали программиста, и феншуй, предлагаю создать отдельную тему,
где каждый может заняться просветительством ))

Все советы были полезны, спасибо.

P.s. Я сейчас пишу анимацию хелсбара на "магических числах",
надо наверно будет прикола ради код выложить,
и посмотреть как в меня полетят ссаные тряпки )))

pax 24.09.2020 12:41

Ответ: Вызов гуя, есть проблемы.
 
Цитата:

Сообщение от Crystal (Сообщение 317593)
P.s. Я сейчас пишу анимацию хелсбара на "магических числах",
надо наверно будет прикола ради код выложить,
и посмотреть как в меня полетят ссаные тряпки )))

Зачем анимацию кодить? Есть же Animator/Animation.

Crystal 24.09.2020 13:03

Ответ: Вызов гуя, есть проблемы.
 
Цитата:

Сообщение от pax (Сообщение 317594)
Зачем анимацию кодить? Есть же Animator/Animation.

Первая ссаная тряпка ))
За тем, что в коде помимо перемещения квадов я управляю их прозрачностью и цветом )
Аниматор то используют чтобы в нужное время нужную анимацию запускать настраивая это чем то типа нодов.
А у меня нет никакой анимации, я просто квады двигаю куда мне надо )

pax 24.09.2020 13:26

Ответ: Вызов гуя, есть проблемы.
 
Цитата:

Сообщение от Crystal (Сообщение 317595)
Первая ссаная тряпка ))
За тем, что в коде помимо перемещения квадов я управляю их прозрачностью и цветом )
Аниматор то используют чтобы в нужное время нужную анимацию запускать настраивая это чем то типа нодов.
А у меня нет никакой анимации, я просто квады двигаю куда мне надо )

Ну так анимации могут тоже всем этим управлять, даже спрайты тебе поменять могут в нужный момент, если потребуется. Animator да, для машины состояний, но так есть и компонент Animation. Есть например метод Sample, он устанавливает анимацию в то время, которое выставляется в состоянии добавленного клипа.

Небольшой пример:
PHP код:

var animation GetComponent<Animation>();
AnimationState state animation["HealthBarAnim"]; // состояние клипа HealthBarAnim
state.enabled true// включаем состояние
state.weight 1// вес клипа при смешивании
state.normalizedTime health/(float)maxHealth// здоровье, переведенное в диапазон  0..1
animation.Sample();  // установка анимации в нужное место 

Также как показал гугл, можно просто анимацию семплировать на объекте с помощью метода AnimationClip.SampleAnimation, но пишут что он не очень быстрый.

Даже рискну пример написать)
PHP код:

public AnimationClip healthBarClip;


void Update()
{
    
healthBarClip.SampleAnimation(gameObject, (health/(float)maxHealth) * healthBarClip.length);



pax 24.09.2020 14:13

Ответ: Вызов гуя, есть проблемы.
 
Вложений: 1
Ну и в дополнение к предыдущему посту собрал хэлсбар на аниматоре с изменением цвета бара + миганием (два слоя анимации).
Сама работа хэлсбара на аниматоре с тремя анимациями в аттаче (видео). Управляется аниматор одним параметром - нормализованным здоровьем (heathNormalized).

Хэлсбар управляется вот этим скриптом.
PHP код:

using UnityEngine;

public class 
HelthBar MonoBehaviour
{
    public 
int health;
    public 
int maxHealth;

    private 
Animator animator;

    private 
void Start()
    {
        
animator GetComponent<Animator>();
    }

    
void Update()
    {
        if (
health 0health 0;
        if (
health maxHealthhealth maxHealth;

        
animator.SetFloat("heathNormalized"health/(float)maxHealth);
    }



Crystal 24.09.2020 19:08

Ответ: Вызов гуя, есть проблемы.
 
Не, мой хелсбар не похож ни на что, что ты видел.
Он у меня я бы сказал - дичь. Как говорят художники "я так вижу".
Когда закончу, увидите, времени мало щас, по чуть-чуть успеваю кодить.
Если есть спортивный интерес, и свободное время, потом можешь
повторить через анимации, с удовольствием погляжу этот вариант.

Видео посмотрел, нужно будет как-нибудь покурить эту тему, явно найду применение.
Видно что да, можно делать то же самое, что я пишу, скорее всего даже так проще (если уже работал с этим).

pax 25.09.2020 09:41

Ответ: Вызов гуя, есть проблемы.
 
Цитата:

Сообщение от Crystal (Сообщение 317607)
Видео посмотрел, нужно будет как-нибудь покурить эту тему, явно найду применение.
Видно что да, можно делать то же самое, что я пишу, скорее всего даже так проще (если уже работал с этим).

Я больше скажу, некоторые стейтмашину аниматора используют для программирования поведения боссов в игре)

Crystal 27.09.2020 19:33

Ответ: Вызов гуя, есть проблемы.
 
Итак PAX, готов для тебя челлендж по хелсбару.
Всё в видео:


pax 27.09.2020 23:47

Ответ: Вызов гуя, есть проблемы.
 
Вложений: 1
Цитата:

Сообщение от Crystal (Сообщение 317615)
Итак PAX, готов для тебя челлендж по хелсбару.

Челендж я принял, но это первый и последний черелндж) Видео с готовым хелсбаром в аттаче. Управляется тем же скриптом, что я приводил выше. Вероятнее всего кодом данная штука будет работать чуть быстрее, но не уверен, но настройка цвета кодом конечно удобнее. Можно заморочиться и написать скрипт, применяющий к спрайту цвет на основе двух параметров и анимировать эти два параметра вместо цвета и прозрачности, тогда можно будет задавать цвет снаружи. А сейчас цвет баров зашит в анимациях.

В результате получилось 4 анимации (анимация движения линии вверх-вниз, анимация прозрачности, анимация для перемещения квадратиков и собственно анимация состояния хэлсбара). Анимация прозрачности используется как на линиях, так и на квадратиках. Пришлось для каждой линии сделать копию контроллера анимации и настроить немного по разному скорости воспроизведения анимаций, чтобы получилось так же как у тебя. Тоже самое сделал для квадратиков. Анимация состояния хэлсбара управляет цветом линий и квадратиков (без прозрачности), а так же их масштабом. Плюс она двигает спрайты "скобок".

ABTOMAT 28.09.2020 05:36

Ответ: Вызов гуя, есть проблемы.
 
Но зачем и чтобы что, если кодом проще?

Crystal 28.09.2020 05:51

Ответ: Вызов гуя, есть проблемы.
 
Цитата:

Сообщение от pax (Сообщение 317617)
Челендж я принял, но это первый и последний черелндж) Видео с готовым хелсбаром в аттаче. Управляется тем же скриптом, что я приводил выше. Вероятнее всего кодом данная штука будет работать чуть быстрее, но не уверен, но настройка цвета кодом конечно удобнее. Можно заморочиться и написать скрипт, применяющий к спрайту цвет на основе двух параметров и анимировать эти два параметра вместо цвета и прозрачности, тогда можно будет задавать цвет снаружи. А сейчас цвет баров зашит в анимациях.

В результате получилось 4 анимации (анимация движения линии вверх-вниз, анимация прозрачности, анимация для перемещения квадратиков и собственно анимация состояния хэлсбара). Анимация прозрачности используется как на линиях, так и на квадратиках. Пришлось для каждой линии сделать копию контроллера анимации и настроить немного по разному скорости воспроизведения анимаций, чтобы получилось так же как у тебя. Тоже самое сделал для квадратиков. Анимация состояния хэлсбара управляет цветом линий и квадратиков (без прозрачности), а так же их масштабом. Плюс она двигает спрайты "скобок".

Моё почтение! Довольно близко к оригиналу, потратить на это ещё
столько же времени, и думаю будет один в один. Челлендж выполнен
быстрее, чем я расчитывал! Лично мне ты всё доказал с анимациями.
Только я думал анимаций меньше будет использоваться )
Немного шлифануть, чуть докодить, и это сэкономило бы
мне много строк кода.

А теперь внимание, барабанная дробь, и на экране
появляются магические числа без комментариев:


Код:

public class KrestAnimation : MonoBehaviour
{
    public Transform Krest;
    public Transform RKrest;
    public Transform LKrest;

    public Transform HPLine1;
    public Transform HPLine2;
    public Transform HPLine3;
    public Transform HPLine4;
    public Transform HPLine5;
    public Transform Begunok1;
    public Transform Begunok2;
    public Transform B2ML;
    public Transform B2MR;
    public Transform B1ML;
    public Transform B1MR;

    public Vector3 V100HPLine1 = new Vector3(2f, 0.03f, 1f);
    public Vector3 V100HPLine2 = new Vector3(2f, 0.01f, 1f);
    public Vector3 V100HPLine3 = new Vector3(2f, 0.05f, 1f);
    public Vector3 V100HPLine4 = new Vector3(2f, 0.005f, 1f);
    public Vector3 V100HPLine5 = new Vector3(2f, 0.02f, 1f);

    public Color Ucolor;

    public float Timer = 0.1f;

    private int L1Sost = 0;
    private float L1Stady = 0;
    private float L1Dist;

    private int L2Sost = 0;
    private float L2Stady = 0;
    private float L2Dist;

    private int L3Sost = 0;
    private float L3Stady = 0;
    private float L3Dist;

    private int L4Sost = 0;
    private float L4Stady = 0;
    private float L4Dist;

    private int L5Sost = 0;
    private float L5Stady = 0;
    private float L5Dist;

    public int B1Sost = 0;
    public float B1Stady = 0f;
    public int B2Sost = 0;
    public float B2Stady = 0f;


    public float MAXHP = 1000f;
    public float HP = 1000f;
    public float HPlast = 1000f;
    public float HPProcent = 0f;

    public int KrestAktivator = 0;

    // Start is called before the first frame update
    void Start()
    {
       
    }

    // Update is called once per frame
    void Update()
    {
        Timer = Timer - 0.1f * Time.time;

        if (Timer <= 0f)
        {
                // Управление размерами и цветом HPLine
                if (HP != HPlast)
            {

                if (HP < 1f && KrestAktivator == 0)
                {
                    RKrest.gameObject.SetActive(false);
                    LKrest.gameObject.SetActive(false);
                    Krest.gameObject.SetActive(true);

                    KrestAktivator = 1;
                }

                if (HP > 0f && KrestAktivator == 1)
                {
                    Krest.gameObject.SetActive(false);
                    RKrest.gameObject.SetActive(true);
                    LKrest.gameObject.SetActive(true);


                    KrestAktivator = 0;
                }


                if (HP < HPlast || HP > HPlast)
                {
                    HPProcent = HP * 100f / MAXHP;
                    HPProcent = HPProcent / 100f;
                    HPLine1.transform.localScale = new Vector3(2f * HPProcent, 0.03f, 1f);
                    HPLine2.transform.localScale = new Vector3(2f * HPProcent, 0.01f, 1f);
                    HPLine3.transform.localScale = new Vector3(2f * HPProcent, 0.05f, 1f);
                    HPLine4.transform.localScale = new Vector3(2f * HPProcent, 0.005f, 1f);
                    HPLine5.transform.localScale = new Vector3(2f * HPProcent, 0.02f, 1f);

                    RKrest.transform.localPosition = new Vector3(-1f * HPProcent, 0f, 0f);
                    LKrest.transform.localPosition = new Vector3(1f * HPProcent, 0f, 0f);


                    if (((HP * 100f) / MAXHP > 79f) && ((HP * 100f) / MAXHP) < 101f)
                    {
                        Ucolor = (HPLine4.GetComponent<Renderer>().material.color);
                        Ucolor.r = 1f;
                        Ucolor.g = 1f;
                        Ucolor.b = 1f;
                        (HPLine4.GetComponent<Renderer>().material.color) = Ucolor;

                        HPProcent = 20f - (100f - ((HP * 100f) / MAXHP));
                        Debug.Log("Процент Линии 4: " + HPProcent);
                        Ucolor = (HPLine4.GetComponent<Renderer>().material.color);
                        Ucolor.r = 1f;
                        Ucolor.g = (HPProcent * 0.05f);
                        Ucolor.b = (HPProcent * 0.05f);
                        (HPLine4.GetComponent<Renderer>().material.color) = Ucolor;
                    }
                    if (((HP * 100f) / MAXHP) < 80f)
                    {
                        Ucolor = (HPLine4.GetComponent<Renderer>().material.color);
                        Ucolor.r = 1f;
                        Ucolor.g = (0f);
                        Ucolor.b = (0f);
                        (HPLine4.GetComponent<Renderer>().material.color) = Ucolor;
                    }



                    if (((HP * 100f) / MAXHP > 59f) && ((HP * 100f) / MAXHP) < 80f)
                    {
                        Ucolor = (HPLine2.GetComponent<Renderer>().material.color);
                        Ucolor.r = 1f;
                        Ucolor.g = 1f;
                        Ucolor.b = 1f;
                        (HPLine2.GetComponent<Renderer>().material.color) = Ucolor;

                        HPProcent = 20f - (80f - ((HP * 100f) / MAXHP));

                        Debug.Log("Процент Линии 2: " + HPProcent);
                        Ucolor = HPLine2.GetComponent<Renderer>().material.color;
                        Ucolor.r = 1f;
                        Ucolor.g = (HPProcent * 0.05f);
                        Ucolor.b = (HPProcent * 0.05f);
                        HPLine2.GetComponent<Renderer>().material.color = Ucolor;
                    }

                    if (((HP * 100f) / MAXHP) < 60f)
                    {
                        Ucolor = (HPLine2.GetComponent<Renderer>().material.color);
                        Ucolor.r = 1f;
                        Ucolor.g = (0f);
                        Ucolor.b = (0f);
                        (HPLine2.GetComponent<Renderer>().material.color) = Ucolor;
                    }
                    if (((HP * 100f) / MAXHP) > 80f)
                    {
                        Ucolor = (HPLine2.GetComponent<Renderer>().material.color);
                        Ucolor.r = 1f;
                        Ucolor.g = 1f;
                        Ucolor.b = 1f;
                        (HPLine2.GetComponent<Renderer>().material.color) = Ucolor;
                    }





                    if (((HP * 100f) / MAXHP > 39f) && ((HP * 100f) / MAXHP) < 60f)
                    {
                        Ucolor = (HPLine5.GetComponent<Renderer>().material.color);
                        Ucolor.r = 1f;
                        Ucolor.g = 1f;
                        Ucolor.b = 1f;
                        (HPLine5.GetComponent<Renderer>().material.color) = Ucolor;

                        HPProcent = 20f - (60f - ((HP * 100f) / MAXHP));

                        Ucolor = (HPLine5.GetComponent<Renderer>().material.color);
                        Ucolor.r = 1f;
                        Ucolor.g = (HPProcent * 0.05f);
                        Ucolor.b = (HPProcent * 0.05f);
                        (HPLine5.GetComponent<Renderer>().material.color) = Ucolor;
                    }
                    if (((HP * 100f) / MAXHP) < 40f)
                    {
                        Ucolor = (HPLine5.GetComponent<Renderer>().material.color);
                        Ucolor.r = 1f;
                        Ucolor.g = (0f);
                        Ucolor.b = (0f);
                        (HPLine5.GetComponent<Renderer>().material.color) = Ucolor;
                    }
                    if (((HP * 100f) / MAXHP) > 60f)
                    {
                        Ucolor = (HPLine5.GetComponent<Renderer>().material.color);
                        Ucolor.r = 1f;
                        Ucolor.g = 1f;
                        Ucolor.b = 1f;
                        (HPLine5.GetComponent<Renderer>().material.color) = Ucolor;
                    }


                    if (((HP * 100f) / MAXHP > 19f) && ((HP * 100f) / MAXHP) < 40f)
                    {
                        Ucolor = (HPLine1.GetComponent<Renderer>().material.color);
                        Ucolor.r = 1f;
                        Ucolor.g = 1f;
                        Ucolor.b = 1f;
                        (HPLine1.GetComponent<Renderer>().material.color) = Ucolor;

                        HPProcent = 20f - (40f - ((HP * 100f) / MAXHP));

                        Ucolor = (HPLine1.GetComponent<Renderer>().material.color);
                        Ucolor.r = 1f;
                        Ucolor.g = (HPProcent * 0.05f);
                        Ucolor.b = (HPProcent * 0.05f);
                        (HPLine1.GetComponent<Renderer>().material.color) = Ucolor;
                    }
                    if (((HP * 100f) / MAXHP) < 20f)
                    {
                        Ucolor = (HPLine1.GetComponent<Renderer>().material.color);
                        Ucolor.r = 1f;
                        Ucolor.g = (0f);
                        Ucolor.b = (0f);
                        (HPLine1.GetComponent<Renderer>().material.color) = Ucolor;
                    }
                    if (((HP * 100f) / MAXHP) > 40f)
                    {
                        Ucolor = (HPLine1.GetComponent<Renderer>().material.color);
                        Ucolor.r = 1f;
                        Ucolor.g = 1f;
                        Ucolor.b = 1f;
                        (HPLine1.GetComponent<Renderer>().material.color) = Ucolor;
                    }





                    if (((HP * 100f) / MAXHP >= 0f) && ((HP * 100f) / MAXHP) < 20f)
                    {
                        Ucolor = (HPLine3.GetComponent<Renderer>().material.color);
                        Ucolor.r = 1f;
                        Ucolor.g = 1f;
                        Ucolor.b = 1f;
                        (HPLine3.GetComponent<Renderer>().material.color) = Ucolor;

                        HPProcent = 20f - (20f - ((HP * 100f) / MAXHP)); ;

                        Ucolor = (HPLine3.GetComponent<Renderer>().material.color);
                        Ucolor.r = 1f;
                        Ucolor.g = (HPProcent * 0.05f);
                        Ucolor.b = (HPProcent * 0.05f);
                        (HPLine3.GetComponent<Renderer>().material.color) = Ucolor;
                    }
                    if (((HP * 100f) / MAXHP) == 0f)
                    {
                        Ucolor = (HPLine3.GetComponent<Renderer>().material.color);
                        Ucolor.r = 1f;
                        Ucolor.g = (0f);
                        Ucolor.b = (0f);
                        (HPLine3.GetComponent<Renderer>().material.color) = Ucolor;
                    }
                    if (((HP * 100f) / MAXHP) > 20f)
                    {
                        Ucolor = (HPLine3.GetComponent<Renderer>().material.color);
                        Ucolor.r = 1f;
                        Ucolor.g = 1f;
                        Ucolor.b = 1f;
                        (HPLine3.GetComponent<Renderer>().material.color) = Ucolor;
                    }




                    HPProcent = 0f;
                    HPlast = HP;
                }


                if (HP >= MAXHP)
                {
                    HPLine1.transform.localScale = V100HPLine1;
                    HPLine2.transform.localScale = V100HPLine2;
                    HPLine3.transform.localScale = V100HPLine3;
                    HPLine4.transform.localScale = V100HPLine4;
                    HPLine5.transform.localScale = V100HPLine5;

                    RKrest.transform.localPosition = new Vector3(-1f, 0f, 0f);
                    LKrest.transform.localPosition = new Vector3(1f, 0f, 0f);

                    HP = MAXHP;
                    HPlast = MAXHP;
                }

                if (HP < 0)
                {
                    HPLine1.transform.localScale = new Vector3(0f * HPProcent, 0.03f, 1f);
                    HPLine2.transform.localScale = new Vector3(0f * HPProcent, 0.01f, 1f);
                    HPLine3.transform.localScale = new Vector3(0f * HPProcent, 0.05f, 1f);
                    HPLine4.transform.localScale = new Vector3(0f * HPProcent, 0.005f, 1f);
                    HPLine5.transform.localScale = new Vector3(0f * HPProcent, 0.02f, 1f);

                    RKrest.transform.localPosition = new Vector3(0f, 0f, 0f);
                    LKrest.transform.localPosition = new Vector3(0f, 0f, 0f);

                    HP = 0;
                    HPlast = 0;
                }



            }

            // Конец управления размерами и цветом HPLine.

            // Управление HPLine1


            Ucolor = (HPLine1.GetComponent<Renderer>().material.color);

            if (L1Sost == 1)
            {
                if (Ucolor.a > 0.99f)
                {
                    L1Sost = 0;
                    Ucolor.a = 1f;
                    (HPLine1.GetComponent<Renderer>().material.color) = Ucolor;
                }
            }

            if (L1Sost == 0)
            {
                if (Ucolor.a > 0f)
                {
                    Ucolor.a = Ucolor.a - 0.005f;
                    (HPLine1.GetComponent<Renderer>().material.color) = Ucolor;
                }
            }

            if (L1Sost == 1)
            {

                if (Ucolor.a < 10f)
                {
                    Ucolor.a = Ucolor.a + 0.005f;
                    (HPLine1.GetComponent<Renderer>().material.color) = Ucolor;

                }
            }

            if (Ucolor.a <= 0f && L1Sost == 0)
            {
                L1Sost = 1;
            }

            L1Dist = Vector3.Distance(HPLine1.transform.position, Krest.transform.position);

            if (L1Dist > 0f && L1Stady == 2)
            {
                HPLine1.transform.Translate(Vector3.down * 0.001f);

                L1Dist = Vector3.Distance(HPLine1.transform.position, Krest.transform.position);

                if (L1Dist >= 0.18f)
                {
                    L1Stady = 1;
                }
            }

            if (L1Dist > 0f && L1Stady == 1)
            {
                HPLine1.transform.Translate(Vector3.up * 0.001f);

                L1Dist = Vector3.Distance(HPLine1.transform.position, Krest.transform.position);

                if (L1Dist >= 0.18f)
                {
                    L1Stady = 2;
                }
            }


            if (L1Dist < 0.18f && L1Stady == 0)
            {
                HPLine1.transform.Translate(Vector3.down * 0.001f);

                L1Dist = Vector3.Distance(HPLine1.transform.position, Krest.transform.position);

                if (L1Dist >= 0.18f)
                {
                    L1Stady = 1;
                }
            }

            // Конец управления HPLine1.

            // Управление HPLine2

            Ucolor = (HPLine2.GetComponent<Renderer>().material.color);

            if (L2Sost == 1)
            {
                if (Ucolor.a > 0.99f)
                {
                    L2Sost = 0;
                    Ucolor.a = 1f;
                    (HPLine2.GetComponent<Renderer>().material.color) = Ucolor;
                }
            }

            if (L2Sost == 0)
            {
                if (Ucolor.a > 0f)
                {
                    Ucolor.a = Ucolor.a - 0.01f;
                    (HPLine2.GetComponent<Renderer>().material.color) = Ucolor;
                }
            }

            if (L2Sost == 1)
            {

                if (Ucolor.a < 10f)
                {
                    Ucolor.a = Ucolor.a + 0.01f;
                    (HPLine2.GetComponent<Renderer>().material.color) = Ucolor;

                }
            }

            if (Ucolor.a <= 0f && L2Sost == 0)
            {
                L2Sost = 1;
            }

            L2Dist = Vector3.Distance(HPLine2.transform.position, Krest.transform.position);

            if (L2Dist > 0f && L2Stady == 2)
            {
                HPLine2.transform.Translate(Vector3.down * 0.002f);

                L2Dist = Vector3.Distance(HPLine2.transform.position, Krest.transform.position);

                if (L2Dist >= 0.18f)
                {
                    L2Stady = 1;
                }
            }

            if (L2Dist > 0f && L2Stady == 1)
            {
                HPLine2.transform.Translate(Vector3.up * 0.002f);

                L2Dist = Vector3.Distance(HPLine2.transform.position, Krest.transform.position);

                if (L2Dist >= 0.18f)
                {
                    L2Stady = 2;
                }
            }


            if (L2Dist < 0.18f && L2Stady == 0)
            {
                HPLine2.transform.Translate(Vector3.down * 0.002f);

                L2Dist = Vector3.Distance(HPLine2.transform.position, Krest.transform.position);

                if (L2Dist >= 0.18f)
                {
                    L2Stady = 1;
                }
            }

            // Конец управления HPLine2.

            // Управление HPLine3

            Ucolor = (HPLine3.GetComponent<Renderer>().material.color);

            if (L3Sost == 1)
            {
                if (Ucolor.a > 0.99f)
                {
                    L3Sost = 0;
                    Ucolor.a = 1f;
                    (HPLine3.GetComponent<Renderer>().material.color) = Ucolor;
                }
            }

            if (L3Sost == 0)
            {
                if (Ucolor.a > 0f)
                {
                    Ucolor.a = Ucolor.a - 0.01f;
                    (HPLine3.GetComponent<Renderer>().material.color) = Ucolor;
                }
            }

            if (L3Sost == 1)
            {

                if (Ucolor.a < 10f)
                {
                    Ucolor.a = Ucolor.a + 0.01f;
                    (HPLine3.GetComponent<Renderer>().material.color) = Ucolor;

                }
            }

            if (Ucolor.a <= 0f && L3Sost == 0)
            {
                L3Sost = 1;
            }

            L3Dist = Vector3.Distance(HPLine3.transform.position, Krest.transform.position);

            if (L3Dist > 0f && L3Stady == 2)
            {
                HPLine3.transform.Translate(Vector3.down * 0.0005f);

                L3Dist = Vector3.Distance(HPLine3.transform.position, Krest.transform.position);

                if (L3Dist >= 0.17f)
                {
                    L3Stady = 1;
                }
            }

            if (L3Dist > 0f && L3Stady == 1)
            {
                HPLine3.transform.Translate(Vector3.up * 0.0005f);

                L3Dist = Vector3.Distance(HPLine3.transform.position, Krest.transform.position);

                if (L3Dist >= 0.17f)
                {
                    L3Stady = 2;
                }
            }


            if (L3Dist < 0.17f && L3Stady == 0)
            {
                HPLine3.transform.Translate(Vector3.down * 0.0005f);

                L3Dist = Vector3.Distance(HPLine3.transform.position, Krest.transform.position);

                if (L3Dist >= 0.17f)
                {
                    L3Stady = 1;
                }
            }

            // Конец управления HPLine3.

            // Управление HPLine4

            Ucolor = (HPLine4.GetComponent<Renderer>().material.color);

            if (L4Sost == 1)
            {
                if (Ucolor.a > 0.99f)
                {
                    L4Sost = 0;
                    Ucolor.a = 1f;
                    (HPLine4.GetComponent<Renderer>().material.color) = Ucolor;
                }
            }

            if (L4Sost == 0)
            {
                if (Ucolor.a > 0f)
                {
                    Ucolor.a = Ucolor.a - 0.025f;
                    (HPLine4.GetComponent<Renderer>().material.color) = Ucolor;
                }
            }

            if (L4Sost == 1)
            {

                if (Ucolor.a < 10f)
                {
                    Ucolor.a = Ucolor.a + 0.025f;
                    (HPLine4.GetComponent<Renderer>().material.color) = Ucolor;

                }
            }

            if (Ucolor.a <= 0f && L4Sost == 0)
            {
                L4Sost = 1;
            }

            L4Dist = Vector3.Distance(HPLine4.transform.position, Krest.transform.position);

            if (L4Dist > 0f && L4Stady == 2)
            {
                HPLine4.transform.Translate(Vector3.down * 0.003f);

                L4Dist = Vector3.Distance(HPLine4.transform.position, Krest.transform.position);

                if (L4Dist >= 0.18f)
                {
                    L4Stady = 1;
                }
            }

            if (L4Dist > 0f && L4Stady == 1)
            {
                HPLine4.transform.Translate(Vector3.up * 0.003f);

                L4Dist = Vector3.Distance(HPLine4.transform.position, Krest.transform.position);

                if (L4Dist >= 0.18f)
                {
                    L4Stady = 2;
                }
            }


            if (L4Dist < 0.18f && L4Stady == 0)
            {
                HPLine4.transform.Translate(Vector3.down * 0.003f);

                L4Dist = Vector3.Distance(HPLine4.transform.position, Krest.transform.position);

                if (L4Dist >= 0.18f)
                {
                    L4Stady = 1;
                }
            }

            // Конец управления HPLine4.

            // Управление HPLine5

            Ucolor = (HPLine5.GetComponent<Renderer>().material.color);

            if (L5Sost == 1)
            {
                if (Ucolor.a > 0.99f)
                {
                    L5Sost = 0;
                    Ucolor.a = 1f;
                    (HPLine5.GetComponent<Renderer>().material.color) = Ucolor;
                }
            }

            if (L5Sost == 0)
            {
                if (Ucolor.a > 0f)
                {
                    Ucolor.a = Ucolor.a - 0.002f;
                    (HPLine5.GetComponent<Renderer>().material.color) = Ucolor;
                }
            }

            if (L5Sost == 1)
            {

                if (Ucolor.a < 10f)
                {
                    Ucolor.a = Ucolor.a + 0.002f;
                    (HPLine5.GetComponent<Renderer>().material.color) = Ucolor;

                }
            }

            if (Ucolor.a <= 0f && L5Sost == 0)
            {
                L5Sost = 1;
            }

            L5Dist = Vector3.Distance(HPLine5.transform.position, Krest.transform.position);

            if (L5Dist > 0f && L5Stady == 2)
            {
                HPLine5.transform.Translate(Vector3.down * 0.003f);

                L5Dist = Vector3.Distance(HPLine5.transform.position, Krest.transform.position);

                if (L5Dist >= 0.18f)
                {
                    L5Stady = 1;
                }
            }

            if (L5Dist > 0f && L5Stady == 1)
            {
                HPLine5.transform.Translate(Vector3.up * 0.003f);

                L5Dist = Vector3.Distance(HPLine5.transform.position, Krest.transform.position);

                if (L5Dist >= 0.18f)
                {
                    L5Stady = 2;
                }
            }


            if (L5Dist < 0.18f && L5Stady == 0)
            {
                HPLine5.transform.Translate(Vector3.down * 0.003f);

                L5Dist = Vector3.Distance(HPLine5.transform.position, Krest.transform.position);

                if (L5Dist >= 0.18f)
                {
                    L5Stady = 1;
                }
            }

            // Конец управления HPLine5.

            // Управление Begunok1.

            if (B1Stady == 2)
            {
                if (Vector3.Distance(Begunok1.transform.position, B1ML.transform.position) > 0f && Vector3.Distance(Begunok1.transform.position, B1MR.transform.position) < ((((0.495f) * ((HP * 100f) / MAXHP)) / 100f) * 4f))
                {
                    Begunok1.transform.Translate(Vector3.right * (((0.005f) * ((HP * 100f) / MAXHP)) / 100f));

                }
                Ucolor = (Begunok1.GetComponent<Renderer>().material.color);

                if (Ucolor.a > 0f)
                {
                    Ucolor.a = Ucolor.a - 0.003f;
                    (Begunok1.GetComponent<Renderer>().material.color) = Ucolor;
                }

                if (Vector3.Distance(Begunok1.transform.position, B1ML.transform.position) <= 0.005f && B1Stady == 2)
                {
                   
                    B1Stady = 1;
                    Ucolor = (Begunok1.GetComponent<Renderer>().material.color);
                    Ucolor.a = 0f;
                    (Begunok1.GetComponent<Renderer>().material.color) = Ucolor;
                }
            }


            if (B1Stady == 1)
            {
               
                if (Vector3.Distance(Begunok1.transform.position, B1MR.transform.position) > 0f)
                {
                    Begunok1.transform.Translate(Vector3.left * (((0.005f) * ((HP * 100f) / MAXHP)) / 100f));

                }

                if (Vector3.Distance(Begunok1.transform.position, B1MR.transform.position) <= 0.005f && B1Stady == 1)
                {
                    B1Stady = 2;
                    Ucolor = (Begunok1.GetComponent<Renderer>().material.color);
                    Ucolor.a = 1f;
                    (Begunok1.GetComponent<Renderer>().material.color) = Ucolor;
                }
            }

            if (B1Stady == 0)
            {
                if (Vector3.Distance(Begunok1.transform.position, B1ML.transform.position) > 0f && Vector3.Distance(Begunok1.transform.position, B1MR.transform.position) < ((((0.495f) * ((HP * 100f) / MAXHP)) / 100f) * 4f))
                {
                 
                    Begunok1.transform.Translate(Vector3.right * (((0.005f) * ((HP * 100f) / MAXHP)) / 100f));

                }
                Ucolor = (Begunok1.GetComponent<Renderer>().material.color);

                if (Ucolor.a > 0f)
                {
                    Ucolor.a = Ucolor.a - 0.003f;
                    (Begunok1.GetComponent<Renderer>().material.color) = Ucolor;
                }

                if (Vector3.Distance(Begunok1.transform.position, B1ML.transform.position) <= 0.005f && B1Stady == 0)
                {
                    B1Stady = 1;
                    Ucolor = (Begunok1.GetComponent<Renderer>().material.color);
                    Ucolor.a = 0f;
                    (Begunok1.GetComponent<Renderer>().material.color) = Ucolor;
                }
            }

            // Конец управления Begunok1.

            // Управление Begunok2.

            if (B2Stady == 2)
            {
               
              if (Vector3.Distance(Begunok2.transform.position, B2MR.transform.position) > 0f && Vector3.Distance(Begunok2.transform.position, B2ML.transform.position) < ((((0.4900002f) * ((HP * 100f) / MAXHP)) / 100f) * 4f)) 
                {
                    Begunok2.transform.Translate(Vector3.left * (((0.005f) * ((HP * 100f) / MAXHP)) / 100f));

                }
                Ucolor = (Begunok2.GetComponent<Renderer>().material.color);

                if (Ucolor.a > 0f)
                {
                    Ucolor.a = Ucolor.a - 0.003f;
                    (Begunok2.GetComponent<Renderer>().material.color) = Ucolor;
                }

                if (Vector3.Distance(Begunok2.transform.position, B2MR.transform.position) <= 0.005f && B2Stady == 2)
                {
                    B2Stady = 1;
                    Ucolor = (Begunok2.GetComponent<Renderer>().material.color);
                    Ucolor.a = 0f;
                    (Begunok2.GetComponent<Renderer>().material.color) = Ucolor;
                }
            }


            if (B2Stady == 1)
            {
                if (Vector3.Distance(Begunok2.transform.position, B2ML.transform.position) > 0f)
                {
                    Begunok2.transform.Translate(Vector3.right * (((0.005f) * ((HP * 100f) / MAXHP)) / 100f));

                }

                if (Vector3.Distance(Begunok2.transform.position, B2ML.transform.position) <= 0.005f && B2Stady == 1)
                {
                    B2Stady = 2;
                    Ucolor = (Begunok2.GetComponent<Renderer>().material.color);
                    Ucolor.a = 1f;
                    (Begunok2.GetComponent<Renderer>().material.color) = Ucolor;
                }
            }

            if (B2Stady == 0)
            {
                if (Vector3.Distance(Begunok2.transform.position, B2MR.transform.position) > 0f && Vector3.Distance(Begunok2.transform.position, B2ML.transform.position) < ((((0.4900002f) * ((HP * 100f) / MAXHP)) / 100f) * 4f))
                {
                    Begunok2.transform.Translate(Vector3.left * (((0.005f) * ((HP * 100f) / MAXHP)) / 100f));

                }
                Ucolor = (Begunok2.GetComponent<Renderer>().material.color);

                if (Ucolor.a > 0f)
                {
                    Ucolor.a = Ucolor.a - 0.003f;
                    (Begunok2.GetComponent<Renderer>().material.color) = Ucolor;
                }

                if (Vector3.Distance(Begunok2.transform.position, B2MR.transform.position) <= 0.005f && B2Stady == 0)
                {
                    B2Stady = 1;
                    Ucolor = (Begunok2.GetComponent<Renderer>().material.color);
                    Ucolor.a = 0f;
                    (Begunok2.GetComponent<Renderer>().material.color) = Ucolor;
                }
            }

            // Конец управления Begunok2.

            Timer = 0.1f;
        }

    }
}



Много самокопипасты внутри кода, т.к. линиями управляет одинаковый
код, но с другими значениями. Оптимизировать размер можно,
не стал заморачиваться, смысла не имеет. На счёт скорости работы
кодом, не уверен, что она выше, т.к. я например постоянно мерю расстояния.
Первый вариант у меня был на таймерах, но я пришёл к выводу, что таймеры здесь неуместны.
Ну и вместо констант магические числа, для меня они те же константы )

Цитата:

Сообщение от ABTOMAT (Сообщение 317618)
Но зачем и чтобы что, если кодом проще?

Его вариант в реализации в разы быстрее, и кода в разы меньше.
Отличный вариант для дизайнера ) Ну, когда игры чисто на нодах пишут во всяких UE )
В общем данный способ имеет место быть, и нужно это как-то на ус мотать,
реально вижу экономит время.

Crystal 28.09.2020 06:35

Ответ: Вызов гуя, есть проблемы.
 
Добавил. Я сейчас подумал, и уже не уверен, что на анимациях разрабокта быстрее.
Я всё-таки больше возился с расчётом цвета, никто не написал в этих
ваших хэлпах, что цвет задаётся от 0 до 1, а не от 0 до 255 как
в интерфейсе юньки, и другие подводные камни, об которые я споткнулся.
Управление движением же было накодено моментально.

Тут надо как-то в общем скорость работы сравнивать,
чтобы понять, зачем и чтобы что )

pax 28.09.2020 07:40

Ответ: Вызов гуя, есть проблемы.
 
Цитата:

Сообщение от Crystal (Сообщение 317620)
Я всё-таки больше возился с расчётом цвета, никто не написал в этих
ваших хэлпах, что цвет задаётся от 0 до 1, а не от 0 до 255 как
в интерфейсе юньки

Есть два класса Color и Color32, компоненты второго как раз измеряются в диапазоне 0..255

Цитата:

Сообщение от Crystal (Сообщение 317620)
Тут надо как-то в общем скорость работы сравнивать,
чтобы понять, зачем и чтобы что )

Т.к. я с анимациями работаю редко, я потратил на реализацию где-то час. С учетом того, что пришлось подумать как сделать анимацию так, чтобы она не была похожа на зацикленную. Отсюда много контроллеров для линий. Можно было бы сделать одну анимацию для всех линий, но длинную. Мне лень было заморачиваться. Но одну вещь я еще сделаю - напишу данный хэлсбар скриптом, чтобы показать тебе плюсы массивов и ООП.

Crystal 28.09.2020 10:17

Ответ: Вызов гуя, есть проблемы.
 
Цитата:

Сообщение от pax (Сообщение 317621)
Есть два класса Color и Color32, компоненты второго как раз измеряются в диапазоне 0..255


Т.к. я с анимациями работаю редко, я потратил на реализацию где-то час. С учетом того, что пришлось подумать как сделать анимацию так, чтобы она не была похожа на зацикленную. Отсюда много контроллеров для линий. Можно было бы сделать одну анимацию для всех линий, но длинную. Мне лень было заморачиваться. Но одну вещь я еще сделаю - напишу данный хэлсбар скриптом, чтобы показать тебе плюсы массивов и ООП.

Не стоит пакс, я с массивами работаю где мне это удобно,
массив не является для меня чем-то новым и непонятным )
Просто я использую массивы только для хранения огромных объёмов информации.
В текущем проекте например в массивах хранятся карты проходимости по клеткам уровня,
хранятся координаты ячеек при конструировании мешей.
Когда дойду до загрузки-сохранения игрового процесса, тоже всё будет в массивах.

pax 28.09.2020 10:30

Ответ: Вызов гуя, есть проблемы.
 
Вложений: 2
Цитата:

Сообщение от Crystal (Сообщение 317622)
Не стоит пакс, я с массивами работаю где мне это удобно,
массив не является для меня чем-то новым и непонятным )

Тем не менее я уже сделал. В аттаче видео результата и проект (Unity 2019.4.10). Собственно код получился вот такой:

PHP код:

using UnityEngine;

public class 
HealthBarAnimated MonoBehaviour
{
    public 
int health;
    public 
int maxHealth;

    public 
Color32 normalColor;
    public 
Color32 dangerColor;

    [
System.Serializable]
    public class 
AnimatedElement
    
{
        public 
SpriteRenderer sprite// анимируемый спрайт
        
public Vector3 startPosition// начальная позиция анимации
        
public Vector3 endPosition;   // конечная позиция анимации
        
public float positionAnimationSpeed 1;  // скорость анимации позиции
        
public bool animatePositionAsHealthPercent false// анимировать позицию на основе процента жизней
        
private float positionAnimationTime// текущее время анимации позиции

        
public bool animateColor true// анимировать цвет
        
public AnimationCurve alphaAnimationCurve// кривая анимации альфы (можно конечно было использовать Mathf.SmoothStep, но решил показать еще один способ анимации)
        
public float alphaAnimationSpeed 1// скорость анимации альфы
        
private float alphaAnimationTime// время анимации альфы

        
public bool animateHealthPercentScale false// анимировать скейл на основе процента жизней
        
public AnimationCurve healthPercentScaleAnimationCurve// кривая интерполяции анимации масштаба
        
public Vector3 healthPercentStartScale// начальный масштаб
        
public Vector3 healthPercentEndScale// конечный масштаб

        
public float healthColorTransitionStart// начало зоны перехода из нормального цвета в цвет опасности
        
public float healthColorTransitionEnd// конец зоны перехода из нормального цвета в цвет опасности



        
public void Init()
        {
            
// рандомизация начальных позиций анимаций
            
positionAnimationTime Random.value;
            
alphaAnimationTime Random.value;
        }

        
// обновление состояния спрайта
        
public void Update(float healthPercentColor32 normalColorColor32 dangerColorfloat deltaTime)
        {
            if (
animatePositionAsHealthPercent)
            {
                
sprite.transform.localPosition Vector3.Lerp(startPositionendPositionhealthPercent);
            }
            else
            {
                
positionAnimationTime += deltaTime positionAnimationSpeed;
                
sprite.transform.localPosition Vector3.Lerp(startPositionendPositionMathf.PingPong(positionAnimationTime1));
            }

            if (
animateHealthPercentScale)
            {
                
sprite.transform.localScale Vector3.Lerp(healthPercentStartScalehealthPercentEndScalehealthPercent);
            }


            if (
animateColor)
            {
                var 
healthPercentClamped Mathf.Clamp(healthPercenthealthColorTransitionStarthealthColorTransitionEnd);
                var 
healthColorT = (healthPercentClamped healthColorTransitionStart) / (healthColorTransitionEnd healthColorTransitionStart);
                var 
color Color.Lerp(dangerColornormalColorhealthColorT);
                
alphaAnimationTime += deltaTime alphaAnimationSpeed;
                
color.alphaAnimationCurve.Evaluate(Mathf.PingPong(alphaAnimationTime1));
                
sprite.color color;
            }
        }
    }

    
// массив анимируемых объектов
    
public AnimatedElement[] animatedElements;

    
void Start()
    {
        
// инициализация элементов
        
for (int i 0animatedElements.Lengthi++)
        {
            
animatedElements[i].Init();
        }
    }

    
void Update()
    {
        if (
health 0health 0;
        if (
health maxHealthhealth maxHealth;

        var 
healthPercent health / (float)maxHealth;


        
// обновление анимации элементов
        
for (int i 0animatedElements.Lengthi++)
        {
            
animatedElements[i].Update(healthPercentnormalColordangerColorTime.deltaTime);
        }
    }


По времени заняло пол часа кода, пол часа настройки.

Crystal 28.09.2020 12:17

Ответ: Вызов гуя, есть проблемы.
 
Цитата:

Сообщение от pax (Сообщение 317623)
Тем не менее я уже сделал. В аттаче видео результата и проект (Unity 2019.4.10). Собственно код получился вот такой:

Твою бы активность да в собственный проект )
Это уже оффтоп, но я всегда допускаю оффтопство в своих темах.
Даже хелсбар оффтоп на самом деле ))

Что там после покойного стимкрафта?
Есть попытки ворваться в стим с новым проектом?

pax 28.09.2020 12:19

Ответ: Вызов гуя, есть проблемы.
 
Цитата:

Сообщение от Crystal (Сообщение 317624)
Твою бы активность да в собственный проект )
Это уже оффтоп, но я всегда допускаю оффтопство в своих темах.
Даже хелсбар оффтоп на самом деле ))

Что там после покойного стимкрафта?
Есть попытки ворваться в стим с новым проектом?

Собственных проектов сейчас нет. Не могу придумать ничего интересного.

Crystal 28.09.2020 12:28

Ответ: Вызов гуя, есть проблемы.
 
Цитата:

Сообщение от pax (Сообщение 317625)
Собственных проектов сейчас нет. Не могу придумать ничего интересного.

ММО идея тухлая, сам уже наверно понял. Нужен сингл, он не минусанёт счёт.
Если нужно придумывать, обращайся, геймдиз вартича к твоим услугам ))
У меня куча вообще нереализованных игр, или заброшенных вначале.
Даже уже могу предложить кое что, где не придётся моделить и анимировать человеков,
эта идея улетела в ящик уже 13 лет как.

pax 28.09.2020 12:43

Ответ: Вызов гуя, есть проблемы.
 
Цитата:

Сообщение от Crystal (Сообщение 317626)
ММО идея тухлая, сам уже наверно понял. Нужен сингл, он не минусанёт счёт.
Если нужно придумывать, обращайся, геймдиз вартича к твоим услугам ))
У меня куча вообще нереализованных игр, или заброшенных вначале.
Даже могу предложить кое что, где не придётся моделить и анимировать человеков.

Спасибо за предложение, но я пока не готов браться за что-то. Можно считать что я на отдыхе :)


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

vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot