Задать вопрос
  • Как работают переводы на другие языки в играх?

    K0TlK
    @K0TlK
    я притянул за уши

    Как и большинство своих аргументов :)

    и аналогичный ридер для переводчика, потому что вручную они могут поломать файл. Опять же, это было надо самому писать какие-то программы, а не браь готовое


    Дай дураку стеклянный член, он и член разобьет и руки порежет. А с другими форматами, ошибки быть не может? АААА, наверное подсветка синтаксиса есть, ой, так и у меня она тоже есть. Что-то не сходится. Зачем переводчику ридер, если он менять только строку будет? Для чего? Зачем?

    Не знаю. Для json знаю, для XML знаю, а для какого-то неизвестного проприетарного формата - не знаю.

    Как же ты хочешь меня на чем-то примитивном поддеть. Ну, если не знаешь последовательности, все, дорога в программисты тебе закрыта.

    Ну вы же не написали, что есть поддержка комментария. Отлично, что не забыли это предусмотреть! Но в каком-то стандартном формате и не пришлось бы гадать.

    Я так и не понял, понравилось или не понравилось? И в моем формате не пришлось бы гадать. Я бы написал пример, того, как полноценный файл должен выглядеть, если тебе это не очевидно, сожалею.

    Как переведёте? "tongue" или "language"?

    А ты мне полную строку дай, чего ты просто слово написал.
    Мало радости в блокноте ковырять файлы из тысяч и десятков тысяч строк. А если в игре богатый лор, то и сотни тысяч.


    Так а в чем минусы то? Чем блокнот от экселя отличается? Может у тебя блокнота хорошего не было?
    Написано
  • Как работают переводы на другие языки в играх?

    K0TlK
    @K0TlK
    maaGames, Хэш это просто число. В этом случае это просто рандомное, неповторяющееся число, чтобы по нему из ХЭШ таблицы получать строку. И хэш всегда был просто числом, ни больше ни меньше. В случае со словарем из c#, хэш - это ключ.
    Если я поменяю формат и надо будет сперва задать ключ, а не хэш, я ничего не буду менять, потому что хэш это и есть ключ. Но, если мне нужно будет поменять местами строку и хэш, я зайду в парсер и индексы местами поменяю. Но такого не произойдет, потому что формат локализации не поменяется. А, если, вдруг, звезды сойдутся так, что поменяется, я просто при парсинге, для новых строк, если они раньше не были, поставлю значение по умолчанию.
    А если опечатался и перепутал местами тэг и индекс? А если не поставил закрывающую кавычку, ты сделал проверку формата? А если две кавычки случайно нажал?

    А я не собираюсь заполнять файл локализации вручную, я напишу простой эдитор, который за меня это все заполнит, мне нужно будет только нажать кнопку "добавить" и написать строку.
    А если многострочный текст?

    Так а в чем здесь проблема? Не знаешь как эскейп последовательность для новой строки выглядит?
    И это ещё прееводчик должен помнить, какой из "столбцов" нужно редактировать

    Что? Столбца 2: ключ и строка, я не понимаю зачем ты придираешься к примеру, который показывает превосходство в читабельности своего формата над жсоном.
    А где в этом формате место для комментариев с пояснением контекста?

    Да, в принципе, где хочешь. Отлавливаешь последовательность '//' и игнорируешь до конца строки. Все. Кто, правда, этим пользоваться будет, непонятно, видел хоть когда-нибудь в файлах локализации комментарии?
    Про блокнот сказал, потому что он, как и любой другой тектовый редактор, умеет подсвечивать синтаксис json и ещё лучше умеет подсвечивать XML. И сразу на месте подсветит ошибки синтаксиса хоть какие-то.

    В том то и проблема, что для твоего жсона, нужна подсветка синтаксиса, а для моего - нет, потому что там буквально нечего подсвечивать. Но если очень хочется, можно назначить для файлов с расширением перевода подсветку синтаксиса ту же, что и у жсона и, ВНЕЗАПНО, строки тоже будут подсвечиваться.
    685176334a93a973845036.png
    Удивительно, правда?
    Просто формат ключ:строка удобен только в простейших случаях, когда ресурсов мало и их не редактируют. Либо есть редактор этих ресурсов, защищающий от ошибок. Даже в CSV формате будет намного удобнее и проще, чем изобретать свой "простой формат".

    А чем это будет удобнее и проще, ты можешь сказать?
    Написано
  • Как работают переводы на другие языки в играх?

    K0TlK
    @K0TlK
    maaGames, Следи за руками. Хэш : строка
    41245235 : "Строка"
    934872394 : "Строка 2"
    Или вот еще: хэш : тэг : индекс : строка
    6427839 : hello : 0 : "Hello"
    3412498 : hello : 1 : "World"
    Может твой жсон настолько же удобочитаемым быть?
    Причем тут вообще блокнот? Файл с текстом открыть в любом редакторе религия не позволяет? 99% это какая-то официальная статистика? Ее где-то посмотреть можно, или из пальца высосано? Перевод в бинарном виде, зачем? Вот хохма будет, когда переводчикам нужно будет качать отдельный софт и учиться с ним работать, вместо того, чтобы просто отрыть текстовый файл и заменить одну строчку другой. Подобный идиотизм могут только в майкрософт придумать, чтобы жизнь посильнее усложнить себе и всем пользователям.
    Ты по-моему перепутал. Диагностировать ошибку будет, как раз, проще в текстовом файле, который выглядит как ключ-строка, потому что там диагностировать нечего, весь файл выглядит вот так:
    ключ : "строка"
    ключ : "строка"
    ключ : "строка"
    Буквально 3 токена - ключ, разделитель, строка.
    Какую спецификацию ты собираешься изучать, чтобы пользоваться этим форматом? Спецификацию, в которой написано что первым идет ключ, а после знака : должна быть строка? Тебе нужны дополнения для нотпада, чтобы определить, что в начале идет ключ, а за ним строка? Может, если для формата перевода нужны какие-то дополнения для нотпада, чтобы текст стал читабельным, то формат изначально для этого не подходит? По-моему, это так должно работать, а не наоборот.
    Написано
  • Как работают переводы на другие языки в играх?

    K0TlK
    @K0TlK
    maaGames, А причем тут xml? Хэш-строка это элементарный формат файла, парсер для него самому написать - пару часов максимум. Зачем нужен жсон или хмл с их убогим синтаксисом, когда я могу сделать формат, который удобочитаем для переводчиков, который я могу изменить в любое время как угодно, для которого мне не нужны сторонние тулзы и который при этом парсится быстрее, чем жсон и хмл.
    Написано
  • Как работают переводы на другие языки в играх?

    K0TlK
    @K0TlK
    Так он и работает. Файл хранит список хэшей/индексов/guid строк с сами строки(не в json, только конченый мракобес будет хранить перевод в жсоне). При запуске, этот файл парсится, данные сохраняются в хэш таблицу: ключ - хэш, значение - строка. Доступ осуществляется по хэшу.
    Написано
  • Как отслеживать угол нормали для скольжению по склону?

    K0TlK
    @K0TlK
    a, Так интерпретируй эти стыки как ступеньки, в чем проблема? Свой код ты не приложил, поэтому вот простой пример того, как это реализовать:
    spoiler

    using UnityEngine;
    
    public class PlayerController : MonoBehaviour {
        public Camera  Camera;
        public float   Sensitivity  = 150f;
        public float   Speed        = 5f;
        public float   StepHeight   = 0.2f;
        public float   StepAngle    = 20f;
        public float   Radius       = 0.5f;
        public float   Height       = 1f;
        public float   Thickness    = 0.02f;
        public bool    Grounded     = false;
        public Vector3 Gravity      = new Vector3(0f, -9.8f, 0f);
    
        public float  X;
        public float  Y;
    
        private const uint MaxCollisionSteps = 8;
    
        private void Update() {
            var h       = Input.GetAxisRaw("Horizontal");
            var v       = Input.GetAxisRaw("Vertical");
            var x       = Input.GetAxisRaw("Mouse X");
            var y       = Input.GetAxisRaw("Mouse Y");
    
            X += x * Sensitivity * Time.deltaTime;
            Y += y * Sensitivity * Time.deltaTime;
    
            Y = Mathf.Clamp(Y, -89f, 89f);
    
            Camera.transform.rotation = Quaternion.Euler(new Vector3(-Y, X, 0));
    
            var pos      = transform.position;
            var forward  = Camera.transform.forward;
            var right    = Camera.transform.right;
            var dir      = forward * v + right * h;
            dir.y        = 0f;
            dir.Normalize();
            var velocity = dir * Speed * Time.deltaTime;
    
            pos = Movement(pos, velocity);
            pos = ApplyGravity(pos);
    
            transform.position = pos;
        }
    
        private Vector3 ApplyGravity(Vector3 pos) {
            var gravity = Gravity * Time.deltaTime;
            var collide = Physics.CapsuleCast(pos,
                                              pos + new Vector3(0, Height, 0),
                                              Radius,
                                              gravity,
                                              out var hit,
                                              gravity.magnitude);
    
            if(collide) {
                Debug.DrawRay(hit.point, hit.normal * 2f, Color.green);
                var d = hit.point - pos;
                var l = d.magnitude - Radius - Thickness;
    
                pos += gravity.normalized * l;
                Grounded = true;
            } else {
                pos += gravity;
                Grounded = false;
            }
    
            return pos;
        }
    
        private Vector3 Movement(Vector3 pos, Vector3 velocity) {
            var dir          = velocity.normalized;
            var distanceLeft = velocity.magnitude;
    
            for(var i = 0; i < MaxCollisionSteps; ++i) {
                var collide = Physics.CapsuleCast(pos,
                                                  pos + new Vector3(0, Height, 0),
                                                  Radius,
                                                  velocity,
                                                  out var hit,
                                                  distanceLeft);
    
                if(collide) {
                    Debug.DrawRay(hit.point, hit.normal * 2f, Color.red);
                    var d = hit.point - pos;
                    var l = d.magnitude - Radius - Thickness;
                    distanceLeft -= l;
    
                    var angle = Vector3.Angle(Vector3.up, hit.normal);
    
                    if(angle >= StepAngle) {
                        var stepUp = pos + new Vector3(0, StepHeight, 0);
                        var stepCollide = Physics.CapsuleCast(stepUp,
                                                      stepUp + new Vector3(0, Height, 0),
                                                      Radius,
                                                      dir,
                                                      out hit,
                                                      distanceLeft);
    
                        Debug.DrawRay(stepUp, dir * 2f, Color.yellow);
    
                        if(!stepCollide) {
                            pos = stepUp + dir * distanceLeft;
                            distanceLeft = 0;
                            break;
                        }
                    }
    
                    dir  = Vector3.ProjectOnPlane(dir, hit.normal).normalized;
                    pos += dir * l;
    
                    if(distanceLeft <= Thickness) {
                        break;
                    }
                } else {
                    pos += dir * distanceLeft;
                    break;
                }
            }
    
            return pos;
        }
    }

    Написано
  • Как отслеживать угол нормали для скольжению по склону?

    K0TlK
    @K0TlK
    Если с капсулькаст все идеально, то просто адаптируй его для перемещения по ступенькам. Если есть коллизия и угол не подходит для перемещения, делай каст выше на максимальную высоту ступеньки.
    Написано
  • Как закрепить к варианту enum переменную?

    K0TlK
    @K0TlK
    Лучше отредактируй вопрос и напиши о том, что именно ты хочешь сделать. Без всяких "обусловимся", "допустим" и т.п. На твой текущий вопрос может быть 10 разных ответов и ни один из них тебе не подойдет, потому что не понятно, что тебе вообще нужно. Например, ты можешь написать для своего класса, в котором есть поле с этим енамом, кастомный инспектор и, в зависимости от того, какое значение выбрано, рисовать поля.
    Написано
  • Как реализовать массив хранящий различные типы данных?

    K0TlK
    @K0TlK
    public enum FirstEnum {
        One
    }
    
    public enum SecondEnum {
        Two
    }
    
    public struct Element {
        public string     Text;
        public FirstEnum  First;
        public SecondEnum Second;
    }
    
    public class SomeClass {
        public Element[] Elements;
    }


    Это самая базовая база программирования.
    Написано
  • Как сделать, чтобы CombineMeshes() объединял несколько материалов, а не только меши?

    K0TlK
    @K0TlK
    Никак. Материалы к мешу никак не относятся. У компонента MeshRenderer есть поле materials. У меша есть сабмеши. Ты можешь меши с разными материалами скомбинировать в один меш, но с несколькими сабмешами. Для каждого отдельного материала - отдельный сабмеш. А в меш рендерере установить эти материалы. Индекс материала в меш рендерере соответствует индексу сабмеша.
    Написано
  • Как правильно ограничить выбор enum значений в инспекторе для разных типов предметов?

    K0TlK
    @K0TlK
    freeExec,

    public enum ItemType : byte {
        Clothes,
        Weapon
    }
    
    [CreateAssetMenu(fileName = "Item Config", menuName = "Configs/Item")]
    public class ItemConfig : ScriptableObject {
        public ItemType Type;
        public float    Damage;
        public float    SwingSpeed;
        public int      Armor;
        public float    Weight;
    }
    
    [CustomEditor(typeof(ItemConfig))]
    public class ItemConfigEditor : Editor {
    
        public override void OnInspectorGUI() {
            var typeProperty = serializedObject.FindProperty("Type");
    
            EditorGUILayout.PropertyField(typeProperty);
    
            var type = (ItemType)typeProperty.enumValueIndex;
    
            switch(type) {
                case ItemType.Clothes : {
                    DrawProperty("Armor");
                    DrawProperty("Weight");
                } break;
    
                case ItemType.Weapon : {
                    DrawProperty("Damage");
                    DrawProperty("SwingSpeed");
                } break;
            }
    
            serializedObject.ApplyModifiedProperties();
        }
    
        private void DrawProperty(string name) {
            EditorGUILayout.PropertyField(serializedObject.FindProperty(name));
        }
    }


    5 минут. Крайне хлопотно.
    Написано
  • Как правильно ограничить выбор enum значений в инспекторе для разных типов предметов?

    K0TlK
    @K0TlK
    У тебя в комментах к ItemType написано то, что должно быть в ItemType.
    ItemType {
        Clothes,
        Weapon
    }


    Можешь избавиться от наследников ItemConfig, все их поля перекинуть в айтем конфиг, а для айтем конфиг написать кастомный инспектор, который будет отображать нужные поля, в зависимости от типа предмета.
    Написано
  • Как в 3D-моделях можно сделать кости для анимации?

    K0TlK
    @K0TlK
    67ea092ea2bcd328182867.jpeg
    Ты нейросеть или просто прикидываешься ей?
    Написано
  • Unity как отследить координаты мыши после клика по ui кнопке или проведя по ней с зажатой клавишей мыши?

    K0TlK
    @K0TlK
    Создать кастомный класс кнопки, реализовать этот и этот интерфейсы. OnDown вызывается при нажатии клавиши, OnUp при отпускании.
    Написано
  • Архитектура MV* используется для разделения логики персонажей?

    K0TlK
    @K0TlK
    Николай Егоров, можешь декомпилировать(открыть в райдере/вижуал студио Assembly-CSharp.dll, которая находится в папке Game_Data/Managed) игры от Owlcat Games (pathfinder, wh rogue trader), там какой-то из мвх паттернов используется для юи.

    А сущности у нас обычно состоят из многих компонентов... тот же самый игрок, или NPC

    С мвх компонентный подход, когда на одном геймобжекте висит 20 компонентов несовместим в принципе. Будет еще больше ненужного кода, который ничего не делает, а существует просто для связи одного с другим. Делай один компонент для игрока и в него пхай все, что относится к игроку. Если хочешь вынести что-то в отдельный компонент, просто выноси это в отдельный класс и пхай его в сущность, соответственно, этому классу не нужно плодить контроллеры, вью и т.п. И будет тогда, условно, Player, PlayerView, PlayerController, гораздо меньше бесполезного говнокода.
    Написано
  • Архитектура MV* используется для разделения логики персонажей?

    K0TlK
    @K0TlK
    Иногда встречаю высказывания, что всю логику хорошо бы делить еще и по MVC/MVP

    И почти всегда такие высказывания делают люди, которые этот мвх только на юи примерах видели.
    Не нужно использовать мвх для логики игры, ничего, кроме разделения одной/двух сущностей на 3 оно не делает. Использование его приводит только к запутанности кода, когда логика одной сущности раскидана по нескольким классам и один из этих классов существует только, чтобы связать между собой другие.
    Мвх может быть полезен для юи и то в очень редких случаях, в остальном это написание кода ради написания кода.

    Если ты хочешь свой проект на юнитевских компонентах переделать в мвх, то проще будет создать новый проект и изначально писать его на мвх. Можешь попробовать, чтобы понять насколько это абсурдный паттерн.
    Написано
  • Как правильно начать изучать Unity?

    K0TlK
    @K0TlK
    никогда не ясно насколько качественный код предоставляется в качестве решения моей проблемы
    Забей на "качественный код". Писать говнокод ты будешь в любом случае, этого не избежать. Избежать "некачественного кода" при обучении невозможно.

    Посоветуйте с чего начать и к чему продвигаться

    Начать с изучения c#, продвигаться к изучению юнити.
    Написано
  • Vector3.forward: как он работает?

    K0TlK
    @K0TlK
    Moskaa, Я же русским по белому написал:
    Vector3.forward это просто Vector3(0, 0, 1). Transform.forward - это направление оси Z объекта в мировых координатах.

    Vector3.forward и transform.forward это не одно и то же.
    Написано
  • Vector3.forward: как он работает?

    K0TlK
    @K0TlK
    Правильно все в документации написано. Vector3.forward это просто Vector3(0, 0, 1). Transform.forward - это направление оси Z объекта в мировых координатах. transform.forward - это просто transform.rotation умноженный на Vector3.forward.
    Написано