При изменении переменной у клона префаба она меняется у всех
go = Instantiate(prefab, ceateLoc.position, Quaternion.Euler(0f, 0f, 270f));
go.GetComponent<net>().Start();
go.GetComponent<net>().layerWeight12 = lw12;
go.GetComponent<net>().layerWeight23 = lw23;
go.GetComponent<net>().layerWeight34 = lw34;
go.GetComponent<net>().firstGeneration = false;
go.GetComponent<net>().active = false;
go.tag = "Agent";
go.name = "car";
go.GetComponent<net>().mutate = 5;
go.GetComponent<net>().Initializate();
go.GetComponent<net>().SetMutatedWeights();
Код выше из объекта despawnController повторяется 40 раз, и все 40 объектов имеют одинаковую переменную layerWeight12.
public void Initializate()
{
if (firstGeneration)
{
SetRandomWeights();
}
else
{
Rigidbody2D rb = gameObject.GetComponent<Rigidbody2D>();
rb.simulated = true;
}
}
public void SetMutatedWeights()
{
if (mutate != 0)
{
MutateArrRandom(layerWeight12, mutationRate);
MutateArrRandom(layerWeight23, mutationRate);
MutateArrRandom(layerWeight34, mutationRate);
}
active = true;
}
public double[,] MutateArrRandom(double[,] Arr, double mutationFactor)
{
double[,] arrc = Arr;
for (int i = 0; i < arrc.GetLength(0); i++)
{
for (int y = 0; y < arrc.GetLength(1); y++)
{
if (RandomInt(0, 2) == 1)
{
if (RandomInt(0, 2) == 1)
{
arrc[i, y] = Arr[i, y] + mutationFactor;
}
else
{
arrc[i, y] = Arr[i, y] - mutationFactor;
}
}
}
}
return arrc;
}
Это код из объекта car(agent).
P.s. это только обрывки кода, на скрине я выделил все созданные объекты car(agent)
Ответы (2 шт):
В методе
public void SetMutatedWeights()
{
if (mutate != 0)
{
MutateArrRandom(layerWeight12, mutationRate);
MutateArrRandom(layerWeight23, mutationRate);
MutateArrRandom(layerWeight34, mutationRate);
}
active = true;
}
Допущена ошибка, метод MutateArrRandom ничего не меняет, а возвращает массив,
который никуда не присваивается.
Скорее всего тут должно быть
layerWeight12 = MutateArrRandom(layerWeight12, mutationRate);
layerWeight23 = MutateArrRandom(layerWeight23, mutationRate);
layerWeight34 = MutateArrRandom(layerWeight34, mutationRate);
Операция
GetComponentдорогая и не должна повторяться.Startзапускается автоматически в следующем фрейме, и его не нужно запускать мануально. Метод исполняющий код при создании этоAwake.
Присвоения огромного количества публичных полей и вызовов методов ужасает, это должно выглядеть примерно так:
[DisallowMultipleComponent]
public class NetSpawner : MonoBehaviour {
[SerializeField] private Net _netTemplate;
[SerializeField] private int _netCount = 40;
[SerializeField] private int _mutate = 5;
public void Spawn (Vector3 position, Quaternion rotation) {
for (int i = 0; i < _netCount; i++) {
GameObject NewNet = Instantiate(_netTemplate.gameObject, position, rotation);
// если бесит клон в имени
NewNet.name = _netTemplate.gameObject.name;
// тег можно и в самом префабе указать
NewNet.GetComponent<Net>().Setup(lw12, lw23, lw34, _mutate);
}
}
}
[DisallowMultipleComponent]
// если обязательное, то указываем
[RequireComponent(typeof(Rigidbody))]
// Net ужасное имя, кто ты, что ты, не понятно
public class Net : MonoBehaviour {
public bool Active { get; private set; }
[SerializeField] private float _mutationOffset = 0.1f;
private Rigidbody _body;
private float[,] _layerWeight12;
private float[,] _layerWeight23;
private float[,] _layerWeight34;
private void Awake () {
_body = GetComponent<Rigidbody>();
}
public void Setup (float[,] lw12, float[,] lw23, float[,] lw34, int mutate, bool isFirstGeneration = false, bool active = false) {
_layerWeight12 = lw12;
_layerWeight23 = lw23;
_layerWeight34 = lw34;
Active = active;
Initializate(isFirstGeneration);
SetMutatedWeights(mutate, _mutationOffset);
}
private void Initializate (bool isFirstGeneration) {
if (isFirstGeneration)
SetRandomWeights();
else
_body.simulated = true;
}
public void SetMutatedWeights (int mutate, float offset) {
if (mutate != 0) {
MutateLayerWeith(_layerWeight12, offset);
MutateLayerWeith(_layerWeight23, offset);
MutateLayerWeith(_layerWeight34, offset);
}
Active = true;
}
private void MutateLayerWeith (float[,] weith, float mutationOffset) {
//...
}
}
Насколько я понял вы с вероятностью в 50% меняете элемент на некий +/- отступ.
Для чего схематоз с изменением массива который ссылается на исходный и его возвратом, который возвращается в никуда, не понятно.
Нужна ли точность double, я тоже сомневаюсь !?%
Просто меняем, то с чем работаем:
private void MutateLayerWeith (float[,] weith, float mutationOffset) {
for (int x = 0; x < weith.GetLength(0); x++)
for (int y = 0; y < weith.GetLength(1); y++)
if (Random.Range(0, 2) == 1) {
if (Random.Range(0, 2) == 1)
weith[x, y] += mutationOffset;
else
weith[x, y] -= mutationOffset;
}
}
