Unity - Czy pole z jednej klasy przypisane do drugiego, może zaktualizować się. Gdy wartość drugiego zostanie zmieniona?


#1

Cześć,

mam nadzieję, że ktoś poradzi jak to zrobić najprościej.

    private string testA = "pierwszy";
    private string testB = "drugi";
    private string testC = "trzeci";

    private void test()
    {
        Debug.Log("\ntestA = " + testA + "\ntestB = " + testB + "\ntestC = " + testC);
        testA = testB;
        Debug.Log("\ntestA = " + testA + "\ntestB = " + testB + "\ntestC = " + testC);

        testB = testC;
        Debug.Log("\ntestA = " + testA + "\ntestB = " + testB + "\ntestC = " + testC);

    }

image
Czy da się jakoś zrobić, żeby testA wskazywał, to co jest w testB. Po tym jak przypisze testB=testC;?

Pozdrawiam


#2

Musiałbyś mieć mutowalne obiekty i zmieniać ich zawartość, a nie referencję. W tym przypadku jak owrapujesz tego stringa inną klasą, przypiszesz obiekt tej klasy so każdego z tych testX to wtedy zmieniając jego zawartość, będziesz na raz zmieniał w każdym z nich.

No i przy okazji - mutowalność tego typu to zazwyczaj coś złego. Nie wiem do czego tego potrzebujesz, ale warto z tym uważać.


#3

Mam singletona (dont destroy on load) i przypisuje sobie z różnych scen do niego różne pola z różnych klas. Tyle że jak coś zmieni te obiekty - to w singletonie zostaje stara wersja.


#4

Nie wiem co tam jest w unity, ale może bardziej Cie interesuje jakaś forma obserwatora https://pl.wikipedia.org/wiki/Obserwator_(wzorzec_projektowy) albo komunikacja eventami? To co podesłałem też zadziała, ale unika się czegoś takiego właśnie po to by dane się nie zmieniały w niekontrolowany sposób. Zwłaszcza jeśli tam jeszcze wiele wątków działa, to taki program to wylęgarnia błędów.


#5
public class WrapperString
    {
        public string testX = "";
    }
    private string testA = "pierwszy";
    private string testB = "drugi";
    private string testC = "trzeci";

    private void test()
    {
        Debug.Log("\ntestA = " + testA + "\ntestB = " + testB + "\ntestC = " + testC);
        WrapperString tester = new WrapperString();
        testA = tester.testX;
        testB = tester.testX;
        testC = tester.testX;
        tester.testX = "NOwe";
        Debug.Log("\ntestA = " + testA + "\ntestB = " + testB + "\ntestC = " + testC);
    }

Proszę o pomoc.


#6
 public class WrapperString
    {
        public string testX = "";
    }
    private string testA = "pierwszy";
    private string testB = "drugi";
    private string testC = "trzeci";

    private void test()
    {
        Debug.Log("\ntestA = " + testA + "\ntestB = " + testB + "\ntestC = " + testC);
        WrapperString tester = new WrapperString();

        WrapperString testXA = new WrapperString();
        testXA.testX = testA;
        WrapperString testXB = new WrapperString();
        testXB.testX = testB;
        WrapperString testXC = new WrapperString();
        testXC.testX = testC;

        testXA = tester;
        testXB = tester;
        testXC = tester;

        tester.testX = "Nowe";

        Debug.Log("\ntestA = " + testXA.testX + "\ntestB = " + testXB.testX + "\ntestC = " +testXC.testX);
    }

Działa - Dziękuję.


#7

Z tego co zrozumialem chcesz w TestA miec zawsze to samo co w TestB. Jak w TestB zapiszemy „abcd” to w TestA ma byc ta sama wartosc.

Wiesz czemu Ci dziala test? Bo masz klase i zmieniasz tylko obiekt wewnatrz. To nie rozwiazuje w zaden sposob Twojego problemu a jezeli rozwiazuje to równie dobrze mogłbys wywalic TestA, TestB i TestC i dac Test. Ten sam poziom uzyskujesz.

Zrób tak:

public class …

string TestB;
string TestA
{
get { return TestB; }
set { TestB = value; }
}

W ten sposob mimo ze masz dwa pola to dzialaja one zaleznie. Wlasciwie to jedno to pole a drugie wlasciwosc.

Z kolei jezeli chcialbys by tylko ustawienie testB robilo wpisanie danych do TestA to:

protected string _TestB;

public string TestA;
public string TestB
{
get { return _TestB;}
set { _TestB = value; TestA = value; }
}

Tak szczerze to troszke to bezsensowne ale co tam potrzebujesz realizuje.


#8

Nie rób tak,
w sensie możesz opakować napisy w obiekty i mieć do nich referencje
ale ogólnie to to musi mieć jakąś logikę a nie losowe napisy popakowane i współdzielone
jak powiesz do czego ci to to masz szansę na lepszą poradę

string, int i inne typy proste tak jak pisano wyżej są nie mutowalne i nie ma do nich referencji
jak napiszesz
string x = “a”;
x += “b”;
to tam powstają 3 różne stringi - “a”, “b” i “ab”.
i x najpierw wskazuje na “a”, a potem na “ab”
to “ab” jest zupełnie nowe i stare “a” jest zapominane a nie się zmienia
jak napiszesz
var y = x;
to y “kopiuje” x w sposób niemutowalny,
czyli jest nowym wskaźnikiem na to na co wskazywał x w momencie wykonania kopii
ale ponieważ to na co wskazuje się nigdy nie zmieni nie będzie updateów po zmianie oryginału
nie da się wziąć adresu tego pierwszego “a” i go zmienić, ani wziąć adresu x i go jakoś obserwować żeby zobaczyć że teraz się zmienił, bo taki kod prowadzi do wielu dziwnych bugów i jest zabroniony (no trochę można do funkcji przez ref parametr ale to mocno ograniczone)

możesz to obejść tak jak to zrobiłeś, ale jak każdy zacznie w takim napisie grzebać to potem ciężko zdebugować kto tam co wstawił, dlatego zwykle się takie pola chowa za jakimś logicznym interfejsem żeby można było współdzielić stan, ale łatwiej było myśleć co to w ogóle robi i kto powinien a kto nie powinien tam grzebać


#9

Pomyśl o
var a = MyHackedString(“a”);
var b = a;
var c = b;
var d = a;
var e = d;
i teraz piszesz
c.SetHackedString(“b”);
zagadka - ile tych napisów się zmieni
A co jak będzie “var b = a.Clone();”