Четверг, 19 Декабря 2024, 06:36

Приветствую Вас Гость

[ Новые сообщения · Игроделы · Правила · Поиск ]
  • Страница 1 из 1
  • 1
Пытаюсь разобраться с Inheritance в Unity
alexsilentДата: Вторник, 30 Июня 2020, 18:24 | Сообщение # 1
почти ветеран
Сейчас нет на сайте
Всё ещё изучаю C# в юнити.

Не очень понимаю как работает Inheritance вообще в Unity, но например в Game Maker я легко разобрался,
потому-что там не было лишней писанины и просто нужно галочку поставить в определённом месте.

В Unity в уроках нашёл такой пример: https://learn.unity.com/tutorial/inheritance

Вроде всё круто и работает в логах, НО это не объекты юнити, а как бы сами по себе объекты С#,
у которых даже простого transform нет.
Есть ли где (для новичков) примеры с GameObject и inheritance? Чтобы понять как работать с этим.

Я попробовал загуглить и нашёл разные примеры, или это для профессионалов, или это так и нужно,
где даже есть незнакомые понятия virtual и override, стоит ли вообще с этим связываться для новичка,
или лучше другие примеры поискать?
https://forum.unity.com/threads.....525281

Код

class BaseClass : Monobehaviour
{
    public virtual Start()
    {
        Debug.Log("BaseClass.Start()");
    }
}

class ChildClass : BaseClass
{
    public override Start()
    {
        base.Start();
        Debug.Log("ChildClass.Start()");
    }
}


Если честно, я долго делал игры без всяких базовых классов и мне этого хватало, потому не особо хочется сильно глубоко в дебри программирования лезть (и узнавать что такое "virtual", если только это не важное понятие в создании Базовых Классов), просто теперь мне нужна функция, чтобы во всех игровых объектах на уровне был базовый класс с Dictionary, где будут храниться переменные. Что-то типа свои встроенные переменные к которым легко обратиться через String и чтобы это было во всех объектах уровня.


Сообщение отредактировал alexsilent - Вторник, 30 Июня 2020, 18:48
VostruginДата: Вторник, 30 Июня 2020, 19:00 | Сообщение # 2
постоянный участник
Сейчас нет на сайте
Начни использовать потихоньку, а в процессе разберёшься :)

- Ключевым словом virtual ты помечаешь методы, свойства, которые могут быть переопределены в дочерних классах. Методы virtual могут содержать реализацию.
- Ключевое слово abstract похоже на virtual, но абстракный метод, свойство не может содержать реализации.
- Чтобы переопределить метод, свойство в дочернем классе, ты должен использовать ключевое слово override.

В твоём же случае с Dictionary можно не париться. Поехали:

Код
class BaseClass : MonoBehaviour {
    protected readonly Dictrionary<string, string> myAwesomeDictionary = new Dictionary<string, string>();
}

class ChildClass : BaseClass {
    private void Start() {
      myAwesomeDictionary.Add("something", "new")
    }
}




pixeyeДата: Вторник, 30 Июня 2020, 19:08 | Сообщение # 3
Red Winter Software
Сейчас нет на сайте
Да ты уже тот еще новичок ; )

Давай по-чесноку. Нельзя нормально что-то использовать начиная с отрицания типа "мне вроде надо, но понимать не хочу".
Наследование само по себене имеет ничего общего с юнити. Наследование это про C# и ооп. А то что ты видишь в юнити уже реализация этого самого ооп на C#.

В отличии от гейммейкера со встроенным GML языком юнити использует полноценный язык C# в качестве скриптового языка. Но это C# без всяких компромиссов во всей красе.
( любые нюансы C# на юнити связаны лишь с компиляцией и ограничением версии языка поддерживаемой юнити )

Отсюда следует что если ты потратишь немного времени на понимание как работает наследование в ооп то твой вопрос автоматически отпадет.

Виртуальные методы это методы для переопределения. Это значит что ты можешь *перезаписать* метод базового классе в наследуемом классе.

Код

public class Animal{
public virtual void Vocal(){
Debug.Log("Basic Animal Sound");
}
}

public class Dog: Animal{
public override void Vocal(){
Debug.Log("Woof");
}
}


В примере выше если ты создашь Dog и вызовешь Vocal то собака будет лаять. Ты спросишь а нафига тут базовый класс? Ну фишка в том что создав собаку наследуемую от животного ты
можешь сделать массив животных ( не указывая что это собаки, кошки и прочая ). На уровне языка будет известно что твой Animal это собака так что когда ты из массива animals[0] дергнешь Vocal то он все равно залает ( ибо ты в animals[0] передал собаку например )

Что касается Юнитивских классов то базовый класс для игровых объектов у них условно Monobehavior, говорю условно потому что не все так просто но это как раз тебе уже пока не должно быть интересно. Так вот Monobehavior прекрасно знает о трансформе и gameobject которому принадлежит. Ровно как ты можешь и из go получить transform и наоборот из transform получить go

Следовательно любой твой класс отнаследованный от Monobehavior будет знать о трансформе тоже.


ACTORS - мой фреймворк на Unity
Until We Die - игра над которой работаю



Сообщение отредактировал pixeye - Вторник, 30 Июня 2020, 19:10
alexsilentДата: Вторник, 30 Июня 2020, 19:17 | Сообщение # 4
почти ветеран
Сейчас нет на сайте
Цитата Vostrugin ()
В твоём же случае с Dictionary можно не париться. Поехали:

Vostrugin, ого спасибо!!
Как просто выглядит код, кроме одного момента protected readonly пошёл гуглить, ибо первый раз встречаю :)
звучит так как будто переменная только для чтения и нельзя изменять словарь, но в то же время мы его можем менять, странно) пошёл искать инфу.
VostruginДата: Вторник, 30 Июня 2020, 19:21 | Сообщение # 5
постоянный участник
Сейчас нет на сайте
protected - это модификатор доступа, словарь будет доступен только внутри этого класса и его наследников (так же не будет виден в инспекторе, для этого можно использовать аттрибут [SerializedField])
readonly - как следует из названия, не даст тебе создать по ошибке другой экземпляр словаря, но при этом ты волен добавлять/удалять новые элементы в словарь.




alexsilentДата: Вторник, 30 Июня 2020, 19:33 | Сообщение # 6
почти ветеран
Сейчас нет на сайте
pixeye, Спасибо Большое за пример!

Цитата pixeye ()
"мне вроде надо, но понимать не хочу"

Я конечно ленивый, но если это всё-таки очень важный момент, то стоит изучить. :)

Добавлено (30 Июня 2020, 19:51)
---------------------------------------------
pixeye, попытался создать класс на твоём примере, и получил ошибку, видимо потому-что
Dog переписала Animal или другие причины, а как сделать так чтобы переменная trans была установлена в базовом скрипте при пробуждении, чтобы лишний раз её не дёргать из Child скриптов?
То есть чтобы 2 Awake сработали, вначале у базы, потом у чайлда.

Код

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Animal : MonoBehaviour {
    public Transform trans;
    public virtual void Awake() {
       print("Awake Base!");
       trans = transform;
    }
    public virtual void Vocal(){
       Debug.Log("Basic Animal Sound");
    }
}


Код

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Dog: Animal{
    public override void Awake() {
      print("Awake Child!");
      trans.position = new Vector3(0,0,0);
    }
    public override void Vocal(){
       Debug.Log("Woof");
    }
}


Добавлено (30 Июня 2020, 20:00)
---------------------------------------------
хотя убрав override из Awake Dog, все равно получил ошибку, похоже trans переменная не доступна для Dog или хз:



Добавлено (30 Июня 2020, 20:14)
---------------------------------------------
Ещё попробовал такой вариант с базой, вместо Awake поставить Animal, как было в примере урока юнити
с фруктами, но в таком случае с transform вообще нельзя работать, юнити выдаёт ошибку, что Transform тут не место:

Код

public class Animal : MonoBehaviour {
    public Transform trans;
    public Animal() {
     print("Awake Base!");
     trans = transform;
    }
    public virtual void Vocal(){
     Debug.Log("Basic Animal Sound");
    }
}


Сообщение отредактировал alexsilent - Вторник, 30 Июня 2020, 20:26
pixeyeДата: Вторник, 30 Июня 2020, 20:15 | Сообщение # 7
Red Winter Software
Сейчас нет на сайте
Ты используешь конструкторы класса - с монобехейверами этого делать не надо. Более того я уверен что тебя юнити предупреждает о том что ты делаешь в консоле закидывая Warning что конструкторы в монобехейвере запрещены.

у тебя есть для этого методы Awake и Start


ACTORS - мой фреймворк на Unity
Until We Die - игра над которой работаю

pixeyeДата: Вторник, 30 Июня 2020, 20:19 | Сообщение # 8
Red Winter Software
Сейчас нет на сайте
Код

public class ActorAnimal : MonoBehaviour
  {
    public Transform selfTransform;

    public virtual void Awake()
    {
      selfTransform = transform;
    }
  }

public class ActorDog : ActorAnimal
  {
    public override void Awake()
    {
      // вызываешь авейк родителя и назначаешь там трансформ
      base.Awake();
      
      Debug.Log(selfTransform);
      // твои штуки
    }
  }


ACTORS - мой фреймворк на Unity
Until We Die - игра над которой работаю

alexsilentДата: Вторник, 30 Июня 2020, 20:20 | Сообщение # 9
почти ветеран
Сейчас нет на сайте
лол, у меня в первом сообщении есть ответ, просто я вначале не понимал как оно работает, а сейчас перечитал и нашёл
Код
base.Awake();
хотя ещё не тестировал)

Добавлено (30 Июня 2020, 20:22)
---------------------------------------------
pixeye, спасибо ещё раз!Мне C# теперь нравится больше JS (Unity Script), хотя бы потому-что даже если там тоже это было, то я раньше не знал, а теперь понимаю как упростить код в юнити. :3


Сообщение отредактировал alexsilent - Вторник, 30 Июня 2020, 20:23
pixeyeДата: Вторник, 30 Июня 2020, 20:23 | Сообщение # 10
Red Winter Software
Сейчас нет на сайте
Если потратишь свое время и усердно поучишь C# то он тебе еще больше понравится : )

ACTORS - мой фреймворк на Unity
Until We Die - игра над которой работаю

alexsilentДата: Вторник, 30 Июня 2020, 20:40 | Сообщение # 11
почти ветеран
Сейчас нет на сайте
Vostrugin, Спасибо Большое! Прикрутил словарь) всё работает, кроме [SerializedField],
компилятор ругается из-за того что рядом стоит словарь, видимо его нельзя показать, ну неважно,
можно и обычным кодом переменные словарю добавлять, как я вначале и планировал. lovegcup
VostruginДата: Среда, 01 Июля 2020, 00:15 | Сообщение # 12
постоянный участник
Сейчас нет на сайте
Цитата alexsilent ()
можно и обычным кодом переменные словарю добавлять, как я вначале и планировал.


Упс, да, погорячился, по дефолту юнити не отрисует словарь. Есть пара способов, но думаю не стоит пока тебя пугать :) Если вдруг нужно будет реализовать управление через инспектор, то проще будет свою реализацию коллекции ключ-значение сделать :)




drcrackДата: Среда, 01 Июля 2020, 01:34 | Сообщение # 13
старожил
Сейчас нет на сайте
Прямо удивительно как можно изучать C# более года и до сих пор не знать про наследование и бояться virtual и override
alexsilent, дело конечно твое, но что-то мне подсказывает, что если ты работаешь один с таким уровнем знанием, то все что ты делаешь, ты делаешь крайне неэффективно и криво
Отложить проект в сторону на месяц и заняться изучением основ могло бы сэкономить тебе кучу времени в будущем
alexsilentДата: Среда, 01 Июля 2020, 08:33 | Сообщение # 14
почти ветеран
Сейчас нет на сайте
drcrack, ну я согласен с тем что я делаю не эффективно и криво) я больше художник, чем программист , и очень долго простые вещи программирую, сейчас буду в третий раз переписывать ядро на юнити, на основе новых знаний.)



Добавлено (01 Июля 2020, 10:50)
---------------------------------------------
Вот кстати, если в уроке доходчиво на примерах объясняют зачем нужен этот функционал, то такие уроки я могу ещё осилить,
а если ещё и пример очень интересный и очень короткий (чтобы с ходу понять), то вообще круто, но такие учителя/уроки редкость, чаще урок просто выглядит так: "Вот вам базовое знание потому-что это надо знать."
Ну как-то так, совсем не понятно, где я буду это применять и буду ли вообще, не очень мотивирует.


Сообщение отредактировал alexsilent - Среда, 01 Июля 2020, 10:53
  • Страница 1 из 1
  • 1
Поиск:

Все права сохранены. GcUp.ru © 2008-2024 Рейтинг