Войти
UnityФорумПрограммирование

Неправильная рабора скрипта для редактора

#0
20:47, 25 ноя 2022

Есть список с объектами и вероятностью их спавна. Сума вероятностей спавна объектов должна равняться 1 (какой-то объект да заспавниться). Для облегчения подбора значений вероятности, есть метод ProbabilityReset который изменяет вероятность на указанное значение для указанного объекта из списка. При этом, изменяя значения и других объектов на соответствующий кэф. ProbabilityReset из кода работает без нареканий.
Есть желание сделать так, что-бы это работало и в редакторе Unity. То есть, при смене одного значения, остальные изменялись автоматически. Есть класс, реализующий эту потребность. Проблема в том, что изменяя значение первого элемента списка все работает, но при взаимодействии с любым другим элементом, первый не реагирует.

public RoadComponent[] objectPool;
public struct RoadComponent
    {
        public GameObject spawnObject;
        [Range(0f, 1f)] public float probability;
    }

public void ProbabilityReset(int objName, float newProbability)
    {
        objectPool[objName].probability = newProbability;

        float otherProbs = 0;
        for(int i = 2; i < objectPool.Length; i++)
        {
            if(i != objName)
            {
                otherProbs += objectPool[i].probability;
            }
        }

        float k = (1 - newProbability) / otherProbs;

        for (int i = 2; i < objectPool.Length; i++)
        {
            if (i != objName)
            {
                objectPool[i].probability *= k;
            }
        }
        //ProbabilityCheck();
    }



#if UNITY_EDITOR
using UnityEngine;

[ExecuteAlways]
public class RG_Editor : MonoBehaviour
{
    public RoadGenerator1 rg;

    void Update()
    {
        for(int i = 2; i < rg.objectPool.Length; i++)
        {
            rg.ProbabilityReset(i, rg.objectPool[i].probability);
        }
    }
}
#endif


Например.
В редакторе есть массив с 5 элементами типа RoadComponent. Первые 2 не принимают участия в расчетах.
probability[2]=0.6
probability[3]=0.2
probability[4]=0.2

Если изменить probability[2]=0,8, то 3 и 4 станут равными 0,1
Если изменить probability[3]=0,4, то 2 останется равным 0,6, а 4 будет равным 0
Если изменить probability[4]=0,4, то 2 останется равным 0,6, а 3 будет равным 0

Не могу понять, либо я упускаю лишнюю запятую, либо совершил логическую ошибку.

#1
16:53, 26 ноя 2022

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

#2
0:15, 28 ноя 2022

meekobold, спасибо за то, что направили на путь истинный. Переделал метод Update() и перенес его в основной скрипт как OnValidate(). Осознал, что в старом скрипте в Update вызывал ProbabilityReset для всех probability, а не только для новой. Кому интересно что я там наваял, вот код OnValidate().

#if UNITY_EDITOR

    void OnValidate()
    {
        int calcFrom = 0;
        bool loaded = false;
        
        if(!loaded)
        {
            for (int i = 2; i < objectPool.Length; i++)
            {
                oldProbs.Add(objectPool[i].probability);
            }
            loaded = true;
        }
        
        for (int i = 2; i < objectPool.Length; i++)
        {
            for(int j = 0; j < oldProbs.Count; j++)
            {
                if (i - 2 == j && oldProbs[j] != objectPool[i].probability)
                    calcFrom = i;
            }
        }

        if(calcFrom != 0)
        {
            ProbabilityReset(calcFrom, objectPool[calcFrom].probability);
            calcFrom = 0; 
            
            for (int i = 2; i < objectPool.Length; i++)
            {
                for (int j = 0; j < oldProbs.Count; j++)
                {
                    if (i - 2 == j)
                    {
                        oldProbs[i - 2] = objectPool[i].probability;
                    }
                }
            }
        }

    }
#endif
UnityФорумПрограммирование