Поменять переменную в другом классе

189
11 апреля 2017, 07:45

Я в шоке, не получается, весь день бьюсь(

using UnityEngine;
using System.Collections;
public class TestScript1 : MonoBehaviour {
    //public TestScript2 ts2;
    public GameObject go;
    public float number1 = 0f;
    // Use this for initialization
    void Start () {
    }
    // Update is called once per frame
    void Update () {
        number1++;
    }
}

второй скрипт на втором объекте

using UnityEngine;
using System.Collections;
public class TestScript2 : MonoBehaviour {
    //вариант 1
    //public TestScript1 ts1;
    //вариант2
    public GameObject go;
    public float number2 = 0f;
    // Use this for initialization
    void Start () {
    }
    // Update is called once per frame
    void Update () {
        //вариант1
        //number2 = ts1.number1;
        //вариант2
        number2 = go.GetComponent<TestScript1> ().number1;
        Debug.Log (number2);
    }
}

Еще пробовал делать геттеры и сеттеры, результат такой же. Короче, мне нужно, чтобы number2 из второго скрипта принимала значение number1 из первого. И все. Сейчас она всегда принимает значение 0 (при этом в первом скрипте я могу написать public float number1 = 9000f;, и все равно number2 будет 0. Еще во втором скрипте могу запихнуть ее в Start() и сделать number2 = 9000f или в самом начале public float number2 = 9000f, и во всех этих случаях она остается равной 0). Что вообще происходит и что я делаю неправильно? и как правильно?

В сами пребафы я запихнул те, которые нужны (в первый - второй, во второй - первый)

После экспериментов расширяю вопрос. В TestScript2 если сделать так, то number2 становится равной number1 (той number1, которая была при старте)

    void Start () {
        //number2 = go.GetComponent<TestScript1> ().number1;
        //number2 = ts1.number1;
    }

Работает любая из этих строк. Если их запихнуть в void Update (), то number2 НЕ изменяется так же, как number1, она остается той, которая была при старте.

Получается, GameObject1 пытается взять значение у префаба GameObject, который находится в папке Assets, а не у того, который находится на сцене. Я правильно понял? Если я делаю так, то он берет number1 у GameObject, который находится на сцене, и number2 меняет свое значение в соответствии с number1

void Update () {
        var myObject = GameObject.Find("GameObject0");
        number2 = myObject.GetComponent<TestScript1> ().number1;
        Debug.Log (number2);
    }

Но это ведь плохое решение? var myObject = GameObject.Find("GameObject0"); в void Start () не позволяет использовать myObject в void Update (). Плюс, если все же использовать это решение, то возникают очень большие проблемы - у меня будет много объектов со скриптом TestScript1 и столько же объектов с TestScript2 (последние динамически создаются) и мне нужно, чтобы они попарно брали значения друг у друга.

Обновление 2. Я уже ниего не понимаю(( На сцене создал объект со скриптом (CounterManager):

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class CounterManagerScript : MonoBehaviour {
public int maxObjects = 0;
public List<float> counterList; // тут хранятся счетчики
// позиция по Y и "граница" бокс коллайдера по Y
public List<float> objectPositionY;
public List<float> objectBoundsY;
public List<float> stickPositionY;
public List<float> stickBoundsY; // тут нет коллайдера, ее высчитываю по спрайту
public DeliveryStickMoveScript deliveryStick; // сюда засунул объект со скриптом из префаба (палка)
public DeliveryObjectScript deliveryOS; // аналогично, но тут объект ИКС
// тут я присваиваю объектам индексы, так скрипт узнает, куда отправить счетчик
public int counterofObject = -1;
public int counterOfStick = -1;
public void doCounter(){
    for (int i = counterOfStick; i < maxObjects; i++)
        counterList.Add (stickPositionY[i] - stickBoundsY[i]/2 - 
                         objectPositionY[i] + objectBoundsY[i]/2);
}

}

Теперь как я присваиваю значения:

public class DeliveryStickMoveScript : MonoBehaviour {
    public GameObject deliveryObject;
    public int indexOfObject = -1;
    public bool canMove = true;
    public float counter = 0f;
    public float objectBoundY = 0f;
    public bool canToGive = true;
    // суть этого всего - код добавляет значения в List, затем там увеличивает 1 параметр на единицу и присваивает его себе (как бы индекс)
    public void Start () {
        SpriteRenderer sr = GetComponent<SpriteRenderer> ();
        objectBoundY = sr.bounds.size.y;
        onScreen = true; 
        GameObject go = GameObject.Find ("CounterManager");
        go.GetComponent<CounterManagerScript> ().stickPositionY.Add (gameObject.transform.position.y);
        go.GetComponent<CounterManagerScript> ().stickBoundsY.Add (objectBoundY);
        go.GetComponent<CounterManagerScript> ().counterOfStick++;
        go.GetComponent<CounterManagerScript> ().maxObjects++;
        go.GetComponent<CounterManagerScript> ().doCounter ();
        indexOfObject = go.GetComponent<CounterManagerScript> ().counterOfStick;
        //if (indexOfObject == go.GetComponent<CounterManagerScript> ().counterOfStick)
            counter = go.GetComponent<CounterManagerScript> ().counterList [indexOfObject];
        //counter = go.GetComponent<CounterManagerScript> ().objectPositionY [indexOfObject];
    }
public void Update () {
        if (canMove) {
            counter -= 1 * Time.deltaTime;
            if (counter >=0)
            gameObject.transform.position = new Vector3 (gameObject.transform.position.x,
                                                     gameObject.transform.position.y - 1 * Time.deltaTime,
                                                     gameObject.transform.position.z);
            else 
                gameObject.transform.position = new Vector3 (gameObject.transform.position.x,
                                                             gameObject.transform.position.y + 1 * Time.deltaTime,
                                                             gameObject.transform.position.z);
        }
    }
}

И первый объект (выше был второй): public class DeliveryObjectScript : MonoBehaviour {

public int indexOfObject = -1;
public Transform deliveryStick;
private bool canCreateStick = true;
public bool startCounter = false; // запустить таймер
public float objectBoundY = 0f;
public float counter = 0f;
public bool onScreen = false; // если true, то CounterManager возьмет параметры
// суть этого всего - код добавляет значения в List, затем там увеличивает 1 параметр на единицу и присваивает его себе (как бы индекс)
public void giveParams(){
    GameObject go = GameObject.Find ("CounterManager");
    go.GetComponent<CounterManagerScript> ().objectPositionY.Add (gameObject.transform.position.y);
    go.GetComponent<CounterManagerScript> ().objectBoundsY.Add (objectBoundY);
    go.GetComponent<CounterManagerScript> ().counterofObject++;
    //go.GetComponent<CounterManagerScript> ().doCounter ();
    indexOfObject = go.GetComponent<CounterManagerScript> ().counterofObject;
    //if (indexOfObject == go.GetComponent<CounterManagerScript> ().counterofObject)
        counter = go.GetComponent<CounterManagerScript> ().counterList [indexOfObject];
    //counter = go.GetComponent<CounterManagerScript> ().stickPositionY [indexOfObject];
    onScreen = true;
}
// Use this for initialization
void Start () {
    SpriteRenderer sr = GetComponent<SpriteRenderer> ();
    objectBoundY = sr.bounds.size.y;
}

// Update is called once per frame
public void Update () {
    if (gameObject.GetComponent<ObjectChooserScript> ().canMove == true) {
        gameObject.GetComponent<Rigidbody>().useGravity = false;
        gameObject.GetComponent<BoxCollider>().enabled = false;
        if (canCreateStick) {
        Instantiate(deliveryStick, new Vector3(gameObject.transform.position.x
                                               ,20
                                               , gameObject.transform.position.z),
                    Quaternion.identity);
        canCreateStick = false;
            if (canCreateStick == false && onScreen == false)
                giveParams();
            startCounter = true;
        }
        if (startCounter)
            counter -= 1 * Time.deltaTime;
        if (counter <=0)
        gameObject.transform.position = new Vector3(
            gameObject.transform.position.x,
            gameObject.transform.position.y + 1 * Time.deltaTime,
            gameObject.transform.position.z);
    }
}

}

В общем, это дичайшая дичь. Тут он мне выдает ArgumentOutOfRangeException: Argument is out of range. в DeliveryObjectScript.giveParams () (at Assets/Scripts/DeliveryObjectScript.cs:25) DeliveryObjectScript.Update () (at Assets/Scripts/DeliveryObjectScript.cs:63). Но самое интересное, что в CounterManager юнити мне показывает, что все параметры принимаются. А, похоже, что DeliveryObjectScript "не видит" значения DeliveryStick, замена counter = go.GetComponent<CounterManagerScript> ().counterList [indexOfObject]; на counter = go.GetComponent<CounterManagerScript> ().stickPositionY [indexOfObject]; выдает тот же результат, а вот наоборот все норм (т.е палка все видит)

Answer 1

получается, GameObject1 пытается взять значение у префаба GameObject, который находится в папке Assets, а не у того, который находится на сцене. Я правильно понял?

Да. Так ты хранишь ссылку на префаб, а не на объект на сцене. Изначально нужно продумать логику нахождения нужного тебе объекта при инициализации. Из твоего скрипта:

    TestScript1 myObject;
    void Update () {
        if(myObject == null)
            myObject = GameObject.Find("GameObject0").GetComponent<TestScript1> ();
        number2 = myObject.number1;
        Debug.Log (number2);
    }

Или:

  void Start () {
               myObject = GameObject.Find("GameObject0").GetComponent<TestScript1> ();
    }

Но не безопасно искать по имени, так как объектов может быть много и у него скорей всего будет окончание (Clone). Нужно реализовать поиск иначе.

READ ALSO
Проблема с хранимой процедурой VK API

Проблема с хранимой процедурой VK API

ЗдравствуйтеСоздал хранимую процедуру для более быстрого получения списка друзей(для 25 пользователей одновременно) и записи их ID в массив

254
C# высоконагруженный клиент-сервер

C# высоконагруженный клиент-сервер

Есть сервер, у которого 20-30 активных подключенийИ одно подключение к другому серверу(машина куда надо отправлять обработанные данные)

284
Получить частоту звука и его громкость Unity C#

Получить частоту звука и его громкость Unity C#

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

346