Он не умеет сейчас нормально распознавать версию движка в проекте, поэтому прописал значение по умолчанию 4.26
В общем linux официально не поддерживается маркетплейсом. На просторах интернета было найдено несколько фанских проектов для скачивания контента и управления UEEngine, самый живой из них этот: https://github.com/nmrugg/UE4Launcher. Но он тоже полноценно не работает, надо докручивать. Попробую.

Структура наследования класса Character:

  • Object. Базовый минимальный класс, практически не имеет никакой функциональности. Не может быть размещен где-либо на игровом поле.
    • Actor Может быть размещен на игровом поле, но не может управляться игроком.
      • Pawn Может управляться игроком, но не имеет полноценной механики перемещения (точнее ходьбы как таковой). То есть его можно наделить функциями смещения в пространстве, но нет функционала Movement Component, в котором можно управлять скоростью ходьмы, степенью сцепления с поверхностями и т.п.
        • Character Полноценный класс со всеми необходимыми механиками, скелетом и оформлением.

На мой взгляд более последовательное видео с созданием персонажа с нуля на c++ https://youtu.be/nzxpNL5jswQ?t=333
Привет!

Ты явно перенес больше, чем следовало. Откуда у тебя здесь переменная cities? Ты же ее в пропсы не передавал.
Выливай что есть в отдельную ветку, буду посмотреть.
Николай, привет! Несмотря на то, что ты все описал подробно, я тыкаю кодом компонента в разные места и довольно бездумно.
Компонент:

const DropdownMenu: React.FC<DropdownMenuProps> = ({ name, href, title, children, ...other }) => { /** * Здесь вся логика с citiesOpened, toggleMenuCities и т.п. */ const [citiesOpened, citiesOpenedSetter] = useState(false) const toggleMenuCities = useCallback(() => { citiesOpenedSetter(!citiesOpened) }, [citiesOpened]) useEffect(() => { if (!citiesOpened) { return } const closeCitiesOpenedEvent = () => { citiesOpenedSetter(false) } window.document.addEventListener('click', closeCitiesOpenedEvent) return () => { window.document.removeEventListener('click', closeCitiesOpenedEvent) } }, [citiesOpened]) const citiesList = useMemo<JSX.Element | null>(() => { //const coordsUrl = '' const citiesList: JSX.Element[] = [] cities.forEach((city) => { if (!city) { return } const { id, name, lat, lng, alias: uri } = city if (!lat || !lng) { return } const link = `/${uri}@` + [lat, lng, 12].join(',') citiesList.push( <li key={id}> <Link href={link}> <a style={{ color: '#000', }} // onClick={closeMenu} > {name} </a> </Link> </li> ) }) return <DropdownMenuStyled {...other} > <a href={href} title={title} onClick={toggleMenuCities} > {name} <i className="fa fa-angle-down"></i> </a> <DropdownMenuBoxStyled opened={citiesOpened}> {children} </DropdownMenuBoxStyled> </DropdownMenuStyled> },[])

Засунул его перед компонентом MainMenu - ругается, что export MainMenu не катит - можно только элемент верхнего уровня экспортировать, внутрь компонента MainMenu перенес - ошибка та же. Вообще вынести в отдельный файл всё это хозяйство надо?

>> не могут же они сами по себе меняться

Они сами по себе и не меняются. Ты же вызываешь setState(...). И никакого сравнения здесь нет, здесь есть получение текущего значения и установка нового инвертированного.

В общем, ты не понимаешь как работают стейты в реакте. Иди уроки проходи начиная с этого.

Ты каким-то удивительным образом умеешь понимать и не понимать одновременно... :)

У тебя тоже есть классная супер способность, делать сложные вещи, еще сложней для понимания:) Вот только пока не понимаю ты - это специально делаешь или ты на таком небесном уровне, что для тебя - это кажется простым:)

Ладно сделаем вид, что я понял, как работает эта конструкция !(this.state?.done). так или иначе насколько я понимаю она в разных случаях меняет значение на true или false.

Но я не понимаю, как она его меняет она использует текущий state для замены, сравнивает в каком он сотоянии находится. Вот этот вопрос, на который ты не ответил:

В итоге получается, что если кликаем, когда state находится в состояние false он отправляет true, если state находится в состоянии false он отправляет true. Только я не понимаю, как вообще обработчик понимает в каком сейчас состоянии находится state, я думал так, что обработчик просто устонавливает и отправляет новое сотояние state, через setState, а получается он его еще и каким-то образом сравнивает его с текущим state.

Мне кажется здесь основной затык. Я не понимаю setState при замене объекта отслеживает текущее состояние state, чтобы выполнять эти операции !(this.state?.done) или done: !this.state.done, чтобы эти конструкции работали, если я правильно понимаю дожен быть какой-то тригер, не могут же они сами по себе меняться. Клик в даном случае запускает функцию setState, но сами значение что-то же должно менять, как они принимают или то или другое значение в объекте, которым мы меняем state?


Ты каким-то удивительным образом умеешь понимать и не понимать одновременно...
Если тебе не понятна конструкция !this.state?.done, то перепиши ее в !(this.state?.done). Может так тебе будет понятноей? Ты путаешься с моментом когда именно применяется восклицательный знак, так как он стоит перед this... Но правильно воспринимать не (!this)(.state)(.done), а именно !(this.state?.done), потому что восклицательный знак воздействует на значение конечного элемента, а не на первый элемент, то есть на done, а не на this.
Еще ты можешь сделать так, чтобы было понятней:
// Получаем текущее значение const done: boolean | undefined = this.state?.done; // Записываем в новую переменную измененное значение const newDone: boolean = !done // Записываем стейт this.setState({ done: newDone, });
И можешь в консоли поиграться с такими конструкициями:
!null true !undefined true !'' true
Приведение типов. Отрицание пустого дает истину.