Pojawiła się nowa wersja Unity, a wraz z nią nowe bajery i możliwości. Jedną z większych ciekawostek, szczególnie dla programistów będzie możliwość skorzystania z możliwości języka C# w wersji 6.0.

Dla bycia całkowicie poprawnym. C# 6.0 pojawił się już w wersji Unity 2017.1, ale był w modelu eksperymentalnym – czyli niby jest, może się sypnąć, nie powinno, ale pewnie tak się stanie. Obecnie wszystkie funkcje i bajery powinny być już stabilne. I jeszcze dla dziennikarskiej poprawności dodam, że nie chodzi stricte o język w wersji 6.0, ale o całą platformę programistyczną .NET (której składową jest język C#) w wersji 4.6.

Jak ustawić C# 6.0

Nowa wersja języka nie jest domyślnie ustawiona w Unity i trzeba to sobie zrobić ręcznie.

Najpierw znajdujemy sobie menu ukryte pod [Edit->Project Settings->Player->Other Settings->Configuration]. Tam znajdujemy opcję “Scripting Runtime Version” i ustawiamy na .NET 4.x.

Aktywujemy .NET 4.x

Zmienne tylko do odczytu

Z nową wersją dostajemy możliwość korzystania ze zmiennych tylko do odczytu, które da się ustawić jedynie w konstruktorze – nie mylić z funkcją Start!

public class Student
{
    public string Name { get;  }

    // Konstruktor
    public Student() {
        Name = "Joe Doe";
    }

    private void Start()
    {
        // Wygeneruje błąd: CS0200: Property or indexer cannot be assigned to -- it is read only
        // Name = "Joe Doe";
    }
}

Taka zmienna może być jedynie odczytana przez ten lub inne skrypty, ale nie może zostać w żaden sposób zmodyfikowana. Ustalamy jej wartość w trakcie tworzenia instancji obiektu wykorzystując konstruktor.

Możemy to wykorzystać do przetrzymywania różnych mnożników. Nie chcemy by te były modyfikowane przez inne skrypty, ale żeby ewentualnie miały do nich dostęp na potrzeby różnych obliczeń.

Uproszczone wypisywanie

Czasami zdarza się, że trzeba przygotować funkcję które tylko wypisują jakieś teksty. Budowanie do każdej z nich pełnego ciała, wydobywanie zmiennych etc. może być męczące jak takich tekstów mamy więcej. Dlatego możemy skorzystać z możliwości C# żeby sobie to ułatwić.

public override string ToString() => $"{LastName}, {FirstName}";
public string FullName => $"{FirstName} {LastName}";

Jeżeli założymy że podane linijki należą dla klasy jakiejś postaci, która ma zmienne FirstName i LastName (imię i nazwisko), to wykorzystując takie konstrukcję możemy wymusić ich wypisanie jeżeli na klasie wykonamy funkcję ToString() lub odwołamy się do zmiennej FullName. Jeżeli byłaby to klasa Student otrzymamy takie coś:

Student s = new Student();
s.ToString();
s.FullName;

Operator warunkowy NULL

Jak często zdarza się wam, wasz ulubiony NullReference Exception? Błąd mówiący o tym, że próbujecie się dobrać do danych obiektu który jest nullem? Pewnie nie raz. Najczęściej pojawia się on w kombinacji, kiedy szukamy komponentu w obiekcie, który najlepiej też wyszukujemy na scenie. Sypnąć się to może na tym, że obiektu nie ma na scenie, oraz na tym że obiekt nie ma szukanego komponentu.

Prosty przykład:

// Metoda prosząca się o błąd.
int x = GameObject.Find("MyObject").getComponent<MyScript>().variable_x;

Przy takiej konstrukcji, NullReference może pojawić się aż w 3 miejscach. Brak obiektu MyObject, brak komponentu MyScript w znalezionym obiekcie, oraz brak zmiennej variable_x w skrypcie. Moglibyśmy się bawić w zabezpieczanie tego ifami i będzie to słuszne, ale mało eleganckie. Z pomocą przychodzi nowy operator, który reprezentowany jest przez pytajnik. Wygląda to tak:

int x = GameObject.Find("MyObject")?.getComponent<MyScript>()?.variable_x;

Jaka jest różnica? Dzięki takiej budowie linijki i nowemu operatorowi, jeśli któryś z parametrów będzie miał wartość null, to kompilator zamiast rzucić wyjątkiem, przypisze do zmiennej x wartość null.

Możemy też wymusić jakąś wartość domyślną, np. tak:

int x = GameObject.Find("MyObject")?.getComponent<MyScript>()?.variable_x ?? 0;

W tym przypadku jeśli wartość miałaby być null, to zamiast tego przypisane zostanie zero. Co daje ten operator jest raczej oczywiste, bez niego nasza konstrukcja wyglądałaby tak:

int x = 0;
GameObject go = GameObject.Find("MyObject");
if( go != null) {
    MyScript ms = go.GetComponent<MyScript>();
    if( ms != null && ms.variable_x != null ) {
        x = ms.variable_x;
    }
}

Interpolacja Stringów

To już częściowo omawialiśmy, bo jest to nic innego jak opcja podania nazw zmiennych bezpośrednio w String. Tworzenie stringa zawierającego zmienne do tej pory wyglądało mało proadnie:

string fullName = string.Format("{0} {1}", FirstName, LastName);
string fullName = FirstName + " " + LastName;

Teraz można to zrobić bardziej elegancko, a zarazem lepiej:

string fullName = $"{FirstName} {LastName}";

Jest jeszcze parę rzeczy o których nie wspomniałem, ale możecie to nadrobić zapoznając się z dokumentacją .NET