Я ищу решение для поведения "Параметры правой кнопки мыши".
По сути, любой элемент в игре, если щелкнуть правой кнопкой мыши, может отображать набор параметров в зависимости от того, что это за объект.
Щелкните правой кнопкой мыши примеры для различных сценариев :
Инвентарь: Шлем показывает опции (Экипировка, Использование, Сброс, Описание)
Банк: Шлем показывает варианты (Take 1, Take X, Take All, Описание)
Этаж: шлем показывает варианты (возьми, иди сюда, описание)
Очевидно, что каждая опция как-то указывает на определенный метод, который делает то, что говорит. Это часть проблемы, которую я пытаюсь выяснить. С таким большим количеством возможностей для одного предмета, как бы мои классы были спроектированы таким образом, чтобы не быть слишком грязными?
- Я думал о наследовании, но это может быть очень долго, и цепь может быть огромной.
- Я думал об использовании интерфейсов, но это, вероятно, немного ограничило бы меня, так как я не смог бы загрузить данные элементов из файла XML и поместить их в общий класс «Item».
Я основываю свой желаемый конечный результат на игре под названием Runescape. Каждый объект можно щелкнуть правой кнопкой мыши в игре и в зависимости от того, что это такое и где он находится (инвентарь, пол, банк и т. Д.), Отображает различный набор параметров, доступных игроку для взаимодействия.
Как бы я пошел для достижения этого? Какой подход я должен использовать в первую очередь, чтобы решить, какие параметры ДОЛЖНЫ отображаться, и после щелчка выбрать способ вызова соответствующего метода.
Я использую C # и Unity3D, но любые приведенные примеры не обязательно должны быть связаны ни с одним из них, так как я использую шаблон, а не реальный код.
Любая помощь очень ценится, и если я не получил четкого ответа на свой вопрос или желаемых результатов, пожалуйста, оставьте комментарий, и я буду стремиться к нему как можно скорее.
Вот что я пробовал до сих пор:
- Мне действительно удалось реализовать универсальный класс «Предмет», который содержит все значения для различных типов предметов (дополнительная атака, дополнительная защита, стоимость и т. Д.). Эти переменные заполняются данными из файла XML.
- Я думал о размещении всех возможных методов взаимодействия внутри класса Item, но я думаю, что это невероятно грязная и плохая форма. Я, вероятно, выбрал неправильный подход для реализации системы такого типа, используя только один класс, а не подклассифицируя различные элементы, но это единственный способ, которым я могу загрузить данные из Xml и сохранить их в классе.
- Причина, по которой я решил загрузить все свои предметы из XML-файла, заключается в том, что в этой игре есть возможность более 40 000 предметов. Если моя математика верна, класс для каждого предмета - это много классов.
источник
Ответы:
Как и все в разработке программного обеспечения, идеального решения не существует. Только решение, которое идеально подходит для вас и вашего проекта. Вот некоторые из них, которые вы могли бы использовать.
Вариант 1: процедурная модель
Древнийустаревшиеметод старой школы.Все элементы являются глупыми обычными типами старых данных без каких-либо методов, но имеют множество открытых атрибутов, которые представляют все свойства, которые может иметь элемент, включая некоторые логические флаги, например
isEdible
,isEquipable
и т. Д., Которые определяют, какие записи контекстного меню доступны для него (возможно, вы могли бы также обойтись без этих флагов, когда вы можете получить его из значений других атрибутов). Есть несколько методов, какEat
,Equip
вашем классе игрока т. Д., Которые берут предмет и имеют всю логику для его обработки в соответствии со значениями атрибута.Вариант 2: объектно-ориентированная модель
Это скорее решение ООП, основанное на наследовании и полиморфизме.
Иметь базовый класс,
Item
от которого наследуются другие элементы, такие какEdibleItem
иEquipableItem
т. Д. Базовый класс должен иметь открытый методGetContextMenuEntriesForBank
иGetContextMenuEntriesForFloor
т. Д., Которые возвращают списокContextMenuEntry
. Каждый наследующий класс переопределяет эти методы, чтобы возвращать записи контекстного меню, которые подходят для этого типа элемента. Он также может вызвать тот же метод базового класса, чтобы получить некоторые записи по умолчанию, которые применимы для любого типа элемента. ЭтоContextMenuEntry
будет класс с методом,Perform
который затем вызывает соответствующий метод из элемента, который его создал (для этого можно использовать делегат ).Что касается ваших проблем с реализацией этого шаблона при чтении данных из файла XML: сначала проверьте узел XML для каждого элемента, чтобы определить тип элемента, а затем используйте специализированный код для каждого типа, чтобы создать экземпляр соответствующего подкласса.
Вариант 3: модель на основе компонентов
Этот шаблон использует композицию вместо наследования и ближе к тому, как работает остальная часть Unity. В зависимости от того, как вы структурируете свою игру, может быть возможно / полезно использовать систему компонентов Unity для этого ... или нет, ваш пробег может отличаться.
Каждый объект класса
Item
будет иметь список компонентов , какEquipable
,Edible
,Sellable
,Drinkable
и т.д. Элемент может иметь один или ни один из каждого компонента (например, шлет из шоколада было бы какEquipable
иEdible
, а когда это не сюжет критичного квестовый предмет тожеSellable
). В этом компоненте реализована логика программирования, характерная для данного компонента. Когда пользователь щелкает правой кнопкой мыши по элементу, компоненты элемента повторяются, и для каждого существующего компонента добавляются записи контекстного меню. Когда пользователь выбирает одну из этих записей, компонент, добавивший эту запись, обрабатывает эту опцию.Вы можете представить это в своем XML-файле, имея подузел для каждого компонента. Пример:
источник
Итак, Майк Хант, твой вопрос меня так заинтересовал, что я решил реализовать полное решение. После трех часов пробных попыток я получил пошаговое решение:
(Обратите внимание, что это НЕ очень хороший код, поэтому я буду принимать любые изменения)
Создание панели содержимого
(Эта панель будет контейнером для кнопок нашего контекстного меню)
UI Panel
anchor
внизу слеваwidth
на 300 (как вы хотите)Vertical Layout Group
и установитеChild Alignment
в верхний центр,Child Force Expand
в ширину (не высоту)Content Size Fitter
и установитеVertical Fit
минимальный размер(На этом этапе наша панель будет уменьшена до линии. Это нормально. Эта панель будет принимать кнопки как дочерние элементы, выравнивать их по вертикали и растягивать до итоговой высоты содержимого)
Создание образца кнопки
(Эта кнопка будет создана и настроена для отображения элементов контекстного меню)
anchor
в верхнем левом углуLayout Element
, установитьMin Height
30,Preferred Height
до 30Создание сценария ContextMenu.cs
(Этот скрипт имеет метод, который создает и показывает контекстное меню)
ContentPanel
префаб в соответствующий слот и перетащите сам Canvas в слотCanvas
.Создание скрипта ItemController.cs
Cube
), поместите его, чтобы он был виден камере, и прикрепите к нему этот скрипт. ПеретащитеsampleButton
префаб в соответствующий слот.Теперь попробуйте запустить его. Когда вы щелкаете правой кнопкой мыши по объекту, должно появиться контекстное меню, заполненное списком, который мы создали. Нажатие кнопок выведет в консоль некоторый текст, и контекстное меню будет уничтожено.
Возможные улучшения:
Пример проекта (Unity Personal 5.2.0, плагин VisualStudio): https://drive.google.com/file/d/0B7iGjyVbWvFwUnRQRVVaOGdDc2M/view?usp=sharing
источник