Ответы пользователя по тегу Unity
  • Unity editor долго запускается! В чём проблема?

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    Тут есть несколько моментов.
    1) Так как вы создаёте, а не открываете, у вас идёт генерация файлов - это всегда процесс не быстрый, но зато последующие запуски будут шустрее.
    2) Во время создания проекта генерируется большое количество файлов (для 2д вашей версии примерно ~13 тыс), что неплохо грузит жёсткий диск. Долгий процесс также может свидительствовать о возможных проблемах с ним.
    3) Unity 2021 и моложе сами по себе немного глючные, в сравнении, например, с теми же 2019/2020.
    Ответ написан
    Комментировать
  • Как сделать механику удара об что то?

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    Факт удара можно отследить через CollisionEnter. Скорость - магнитуда вектора движения. А дальше дело за фантазией. В общих чертах как-то так:

    using UnityEngine;
    
    public class RigidbodyDamager : MonoBehaviour
    {
        public float damageMultiplier = 1.0f; // Множитель урона (для коррекции значения урона)
    
        private void OnCollisionEnter(Collision collision)
        {
            // Получаем силу удара мяча
            float impactForce = collision.impulse.magnitude;
    
            // Вычисляем урон в зависимости от силы удара (здесь можно использовать свою формулу)
            float damage = impactForce * damageMultiplier;
    
            // Применяем урон к объекту, с которым столкнулись (если это противник и имеет компонент здоровья)
            Health health = collision.gameObject.GetComponent<Health>();
            if (health != null)
            {
                health.Damage(damage);
            }
        }
    }


    Можно сделать как на примере - умножить скорость на некое число. А можно, например, добавить график AnimationCurve и там выставить все нужные значения.
    Ответ написан
    2 комментария
  • Как можно исправить поворот объектов?

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    Рекомендую вместо Translate использовать Vetor3.MoveTowards. Таким образом перемещение станет более контроллируемым и вы сможете использовать поворот LookAt.
    Ответ написан
    Комментировать
  • Хочу забилдить свою андроид игру, но выдает ошибку, что делать?

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    Всегда начинайте просмотр с самой первой красной ошибки - там как раз и говорится, что пошло не так. Если нужна с ней помощь - приложите скриншот в комментарий к ответу.
    Ответ написан
  • Код не видит Camera.main. Как это исправить?

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    "Camera.main" находит первую камеру на сцене, подписанную стандартным тегом "MainCamera". Убедитесь в том, что на нужной камере он есть.
    Ответ написан
    Комментировать
  • С чего начать изучение Unity?

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    В Unity вы можете начать работать вообще без знания кода в принципе. Вам в любом случае придётся потратить время, чтобы понять что в Unity что делает. Поэтому советую изучать Unity и C# параллельно. Знания второго раздела достаточно для старта в юнити по скриптам. Остальное вы можете осваивать уже по ходу разработки первых простых игр вроде 2д платформеров и раннеров.
    Ответ написан
    Комментировать
  • Можно ли применять occlusion culling в онлайн игре на Unity?

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    Не просто можно, а даже нужно.

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

    И пока вы не синхронизируете эффекты оптимизации графики по сети, они будут оставаться на локальном устройстве. Например, вы можете у себя поставить ту же дальность прорисовки на 20 метров, а другой игрок у себя поставит 40 и эти значения никак друг на друга не должны влиять, так как это чисто локальная тема.
    Ответ написан
    Комментировать
  • Как сделать чтобы в Unity 3D "Character Controller" поворачивался вместе с камерой (FPS_Player)?

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    Поворачивайте вокруг оси Y сам объект с CharacterController. Это можно сделать через Transform объекта.
    Ответ написан
    Комментировать
  • Подойдёт ли Unity для создания игры, по типу Зайчика?

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    Такую игру можно сделать вообще на чём угодно. Плюсы выбора конкретно юнити скорее в относительной простоте, бесплатности и лёгкости сбора сразу на несколько разных платформ.
    Ответ написан
    Комментировать
  • Как найти наследуемые Объекты?

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    Простой способ:
    1) Создаёте класс Enemy и в нём реализовываете возможность получить урон;
    2) Создаёте производные классы и накладываете их на соответствующие объекты;
    3) В скрипте попадания используете TryGetComponent.
    4) Profit

    Пример:
    using UnityEngine;
    
    public class Projectile : MonoBehaviour {
    
    	private void OnCollisionEnter(Collision c) {
    		if (c.gameObject.TryGetComponent(out Enemy e)) {
    			// damage enemy
    		}
    		// destroy bullet or return to object pool
    	}
    }
    Ответ написан
    Комментировать
  • Как правильно создавать верхнее меню (жизни монеты) игрока?

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    Если простым языком, опция Render Mode используется следующим образом:
    1) Overlay - стандартный вариант, когда у вас одна камера на все задачи;
    2) Camera - показать специфический интерфейс для определённой камеры;
    3) World - вообще отвязать от камер, сделав объектом сцены.

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

    Далее размер зоны Canvas-а на сцене. В режиме Overlay он огромен неспроста - он имеет размер экрана. Например, если эран 2960:1440, то и канвас будет иметь такой размер, почти 3к в ширину и 1.5к в высоту. Но на камеру он будет накладываться так, чтобы вложиться в её границы. Единственное неудобство в том, что чисто визуально сложно представить, как это дело будет выглядеть в игре. Чтобы каждый раз не прыгать в плеймод, можно просто вкладку Game расположить где-нибудь рядом. Ну или делать как мои знакомые. Заметил среди знакомых тренд, что они в простых гиперказуалках просто ставят режим Render Mode - Camera и сразу так работают. Сценический размер и положение канваса подстраиваются под камеру и им удобно.

    Касательно масштабирования, обычно разработчики выбирают эталонное разрешение экрана, которое указывают в Canvas Scaler (рядом с Canvas на одном объекте). Там опция - UI Scale Mode, режим Scale With Screen Size. А ползунком ниже указывают как именно интерфейс будет зависеть от ширины и высоты. Затем нужно перейти во вкладку Game и там слева вверху есть выпадающий список с размерами экрана. Нужно выбрать или создать и выбрать то же самое разрешение.

    Если вы хотите, чтобы определённый объект был привязан, например, к левому верхнему краю экрана, этот объект обязательно должен иметь RectTransform. В компоненте вы можете заметить вот такую фичу:
    64742aa24ddcc140401392.png
    Открываем, согласно подсказке жмём Shift+Alt и нажимаем на левый верхний квадрат:
    64742acbe889e101758998.png
    Осталось только в самой компоненте задать такие Pos X / Pos Y, чтобы вам нравились отступы от левого и верхнего краёв экрана.

    Делать основной канвас дочерним игроку - плохая практика. Максимум на уровне префаба и сразу вытащить из игрока при спавне, но и это хз зачем, если её можно сразу поставить на сцену и не мучаться. Если у вас много сцен с таким канвасом, то просто сделайте сам канвас префабом и меняйте его содержимое не для конкретной сцены, а на уровне префаба. Собственно, так обычно и делают, разве что у вас всего 1 сцена игры, на которой вы спавните префаб нужного уровня.

    Осталось лишь придумать как привязать этот интерфейс к игроку на уровне скрипта. Много кто использует для этого синглтон, кто-то при спавне игрока просто ищет специфический скрипт на сцене и сохраняет на него ссылку. Это реально неплохие варианты.
    Ответ написан
    Комментировать
  • Как формируется порядок элементов массива gameObject-ов?

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    Есть (как минимум) три фактора, которые внесут элемент хаоса в попытки создать правильный порядок:
    1) Способ сохранения. Данные сцены сохраняются в yaml структуру процессом, вообще не гарантирующим, что порядок сохранения элементов будет как-то соответствовать их порядку в иерархии сцены. И даже более того, сам этот процесс немного меняется от версии к версии, поэтому более детальный ответ будет сильно специфическим.
    2) Способ загрузки. Перед передачей данных сценическому графу их нужно считать анализатором, и хоть он и правда читает построчно, но в итоге преобразования в доступные структуры порядок данных также меняется. Могу лишь сказать, что на это как-то влияет fileID объектов, но детальнее я не разбирал эту тему.
    3) Вы сами вносите ещё больше беспорядка в процесс, руками меняя порядок элементов в иерархии. Просто потому что это никак не влияет на структуру файла сцены.

    Тем не менее порядок гарантировать всё же можно. Например... отсортировав, как и предлагал отвечающий выше.
    // using System.Linq;
    atoms = GameObject.FindGameObjectsWithTag("atom");
    Array.Sort(atoms, (a, b) => string.Compare(a.name, b.name));
    Ответ написан
    Комментировать
  • Как исправить скрипт камеры?

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    Я так понимаю, камеру дочерней сделали вы, чтобы всё спавнить вместе? Если я угадал, тогда вы прямо в префабе можете руками сделать ссылку на игрока, а затем на старте этого скрипта просто вызвать
    transform.parent = null;
    Чтобы отправить камеру в свободное плавание, что и предполагается скриптом слежки.
    Ответ написан
    1 комментарий
  • Правильно физическое движение в Unity?

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    Используйте Rigidbody.AddForce с ForceMode.Impulse. Чтобы мяч не терял импульса, выставите правильные настройки физического материала.
    Ответ написан
    Комментировать
  • Влияет ли размер тайлов на игру (быстродействие, отображение)?

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    Так как ваша сетка не движется, то единственное, чем она ваш комп грузит - это добавляет свои данные в Draw call Batching. А учитывая специфику этого процесса, выгоднее сделать меньше больших, чем больше маленьких. Но речь идёт о каких-то безумных числах, вроде 10 тыс клеток при условии, что они будут ВСЕ у вас на экране в границах активной камеры. Но даже так, пока изменение тайлмапа (большими порциями за раз) не происходит в рантайме вы не словите каких-то ощутимых лагов.
    Если же говорить про оптимизацию процесса, то выгоднее сделать более мелкую сетку по одной простой причине - вы можете рисовать как одной клеткой за раз, так и их энным количеством (как буд-то вы рисуете более большой сеткой), а вот уменьшить исходно большую если и возможно, то я хз как.
    Ответ написан
    1 комментарий
  • Что использовать вместо Transform unity?

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    Пока вы только начинаете свой путь, не забивайте себе голову такими вещами как "актуально" или не "актуально". Основы и принципы, которые вы познаете во время освоения чего-либо в разработке пригодится вам дальше вне зависимости от того, что вы изучали.

    Вероятно, вы говорите о видео с канала Сакутина. Это не самый лучший способ начать изучение, так как автор всё же делает контент больше для тех, кто понимает основные принципы программирования и процесс разработки проекта на юнити.
    Начать можно с чего-то менее хардкорного, например https://www.youtube.com/@graphicaldesign2776/ и/или https://www.youtube.com/c/emeraldpowder.
    Ответ написан
    Комментировать
  • Из-за чего ломается скрипт?

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    Ошибка в использовании пустой ссылки:
    // вместо
    public static List<Vector2> colliderPositions;
    
    // напишите
    public static List<Vector2> colliderPositions = new List<Vector2>();


    Это не связано с вашим вопросом, но есть ещё одна ошибка. Перед тем как проверять "с чем луч столкнулся", стоит проверить, а столкнулся ли он вообще хоть с чем-то.
    if (hitInfo.collider == null) {
    	// то же как в блоке else
    } else if (hitInfo.collider.CompareTag("Mirror")) {
    // ... ну и так далее
    Ответ написан
    Комментировать
  • Почему медленно загружается xml файл?

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    Есть несколько рекомендаций:
    1. Используйте асинхронный код. Что-то типа такого:
    public static async void SetXMLValue(string pathToXMLFile, string nodeName1, string nodeName2, string nodeName2Value) {  
        TextAsset textAsset = Resources.Load<TextAsset>(pathToXMLFile);
        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.LoadXml(textAsset.text);
        XmlNode node = xmlDoc.SelectSingleNode("/" + nodeName1 + "/" + nodeName2);
        node.InnerText = nodeName2Value;
        await File.WriteAllTextAsync(Application.dataPath + "/Resources/" + pathToXMLFile + ".xml", xmlDoc.OuterXml);
    }

    2. Используйте более быстрые методы чтения и записи XML. Вместо стандартных методов XmlDocument.LoadXml() и XmlDocument.OuterXml вы можете использовать XmlReader и XmlWriter. XmlReader позволяет читать XML файлы по мере их поступления и не хранить их в памяти целиком, что позволяет сократить время чтения. XmlWriter позволяет записывать XML файлы по мере их создания, что позволяет сократить время записи.
    3. Используйте кэширование данных в памяти. Вместо того, чтобы каждый раз читать настройки из XML файла, вы можете загрузить их в память при запуске программы и хранить в памяти. При изменении настроек вы можете обновить их как в памяти, так и в XML файле. Это позволит избежать чтения XML файла каждый раз при обращении к настройкам.
    4. Используйте более быстрый способ доступа к файлам. Вместо использования метода File.WriteAllText() вы можете использовать методы доступа к файлам, которые более быстры и оптимальны для Unity, например, System.IO.MemoryMappedFiles.
    5. Если вам и правда так припекло использовать XML, вы можете немного ускорить процесс, оптимизировав его структуру. Например, выделить для каждой локали по отдельному файлу. Но лично я вам советую познакомиться с форматом JSON, тем более в юнити есть хороший нативный инструмент JsonUtility, а в шарпе newtonsoft.json.

    Но если ваша цель не решить интересную задачу, а просто иметь под рукой хороший инструмент, советую вам не мучать себя, а просто воспользоваться пакетом Unity.Localization. Ну или если у вас есть лишних $45, то пакетом i2 в ассет сторе.
    Ответ написан
    1 комментарий
  • Скажите пожалуйста правильно я пользуюсь PlayerPrefs в Unity?

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    Есть несколько рекомендаций:
    1) Загрузка. В строке
    PlayerPrefs.GetInt("money");
    Вы загружаете данные из базы, но никуда не сохраняете. Нужно написать так:
    Money = PlayerPrefs.GetInt("money");

    2) Обновление. Обновлять данные, используя
    void Update() {
    	PlayerPrefs.SetInt("money", Money);
    }

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

    Лучше данные сохранять тогда, когда они меняются. Например, добавим метод:
    public void SetMoney(int money) {
    	// Поменяли
    	Money = money;
    	// Сохранили
    	PlayerPrefs.SetInt("money", Money);
    }

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

    3. Раз мы создали метод изменения денег, но у нас всё равно осталось публичное поле, то его стоит спрятать, чтобы случайно не вызвать логику изменения без сохранения в базу (вы же не хотите чтобы ваши игроки читерили, узнав о таком способе?). Потому делаем поле приватным и добавляем геттер:
    private int Money;
    
    // ...
    
    public int GetMoney() {
    	return Money;
    }


    4. Ваше поле Money имеет значение по умолчанию 1, но из базы загружается значение по умолчанию 0. Поэтому метод загрузки мы исправим вот так:
    Money = PlayerPrefs.GetInt("money", 1);

    В итоге получается такой код:
    using UnityEngine;
    
    public class MoneyScriptDemo : MonoBehaviour {
    
    	private int Money = 1;
    
    	private void Start() {
    		Money = PlayerPrefs.GetInt("money", 1);
    	}
    
    	public void SetMoney(int money) {
    		Money = money;
    		PlayerPrefs.SetInt("money", Money);
    	}
    
    	public int GetMoney() {
    		return Money;
    	}
    
    	public void SaveGame() {
    		PlayerPrefs.Save();
    	}
    }


    PS. Ну и так как мы не в Java, а в C#, то вместо геттера и сеттера можем написать аксессор:
    using UnityEngine;
    
    public class MoneyScriptDemo : MonoBehaviour {
    
    	private int Money = 1;
    
    	public int money {
    		get => Money;
    		set {
    			Money = value;
    			PlayerPrefs.SetInt("money", value);
    		}
    	}
    
    	private void Start() {
    		Money = PlayerPrefs.GetInt("money", 1);
    	}
    
    	public void SaveGame() {
    		PlayerPrefs.Save();
    	}
    }
    Ответ написан
    Комментировать
  • Почему Instantiate иногда создаёт объект не в том месте?

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    Уверен, что проблема в том, что коллайдер пистолета выталкивает коллайдер пули. Это можно проверить в редакторе создав пулю в месте её спавна, а затем, выбрав одновременно пистолет и пулю, посмотреть, не сталкиваются ли их коллайдеры. Проблему можно решить двумя путями:
    1) Переместить точку выстрела туда, где точно нет коллайдеров
    2) Отменить коллизию. Для этого нужно создать два Layer - для пистолета и пули, затем в Edit/Project Settings/Physics в самом низу есть схема коллизий. Там нужно снять одну галочку, между слоем пули и слоем пистолета.

    Если это не помогло, пришлите скрипт оружия и скрипт (если такой есть) пули в комментарий к этому сообщению, посмотрим, мб там что-то влияет.
    Ответ написан
    4 комментария