Ответы пользователя по тегу Unity
  • Как сделать бесконечное создание уровня платформер?

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    Ошибка No MonoBehaviour scripts in the file, or their names do not match the file name означает, что название файла и класса не совпадают.
    Ответ написан
    5 комментариев
  • Какими способами можно реализовать рандомное движение нпс по карте UNITY 2D?

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

    Ответ на ваш вопрос сильно кореллирует со спецификой игры. Но в общем случае я представляю себе город или лес и некий персонаж должен прийти к случайной точке интереса. В таком случае можно покрыть карту сеткой соединённых между собой нод-объектов. Персонаж идёт к одному из них. Дойдя, он смотрит какие ноды соседствуют с этой, исключая ту, от которой он сюда пришёл и идёт дальше. Например, так можно легко реализовать систему городского трафика.

    Но было бы здорово, уточни вы детальнее задачу.
    Ответ написан
    Комментировать
  • Как сделать переход между сценами в unity 3d?

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

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    Вопрос можно решить как-то так.

    1. В игрухе создаёте кнопку входа, открывающую страницу входа вашего сайта.
    2. В Google Cloud Console создаёте проект и настраиваете для работы с API Google Sign-In.
    3. Да, вам нужен сайт. Можно вообще склепать одностраничку с авторизацией гугл.
    4. После успешной авторизации гугл должен вернуть токен доступа, который шлётся на ваш сервак и там крутится в бд для идентификации/регистрации юзера (например Firebase).
    5. Обратно с сервака через тот же вебсокет отправляете в приложение запрос.

    Если влом с сайтом париться, можете попробовать Firebase Auth. Вот неплохой пример
    https://youtu.be/7D8Z9_tNrC8
    Ответ написан
    Комментировать
  • Где лучше получать ввод - в Update или FixedUpdate?

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    TLDR: Update

    Unity использует покадровую систему, то есть "вот новый кадр - обновим состояние". Это ключевой момент для понимания вашего вопроса, потому что появляется понятие тайминга, в который невозможно попасть способами, выполняющимися с постоянной периодичностью. Это почти как стрелочные часы без батареек. Могут ли они показать правильное время? Да, два раза в день на одну секунду.

    Речь идёт об использовании FixedUpdate и рекурсивного Invoke, а также корутин (без yield return null).

    Так как вы о LateUpdate не спрашивали, то и углубляться в него не будем. Остаётся только Update.

    Используемые методы можно поделить на две группы - кадрозависимсые и кадронезависимые. К первым можно отнести Input.GetKeyDown, ко вторым Input.GetAxis. Если с кадрозависимыми всё понятно (нелогично их использовать вне Update/LateUpdate), то кадронезавимые возвращают разные значения как для разных таймингов, так и для разной продолжительности нажатия. Поэтому для них можно и так и этак и будет это чисто особенностью вашей игры. Такой же как, например, реализация 2д поворота через scale, rotate или sprite flip.
    Ответ написан
    Комментировать
  • Как менять материал по нажатию кнопки в Unity 3d?

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    Можете вызвать свойство material и вставить туда ссылку на нужный вам материал
    https://docs.unity3d.com/ScriptReference/Renderer-...

    Типа:
    using UnityEngine;
    
    public class MaterialChangeExample : MonoBehaviour {
    
    	// ссылка на элемент отображения
    	[SerializeField] private Renderer m_Renderer;
    	// массив нужных материалов
    	[SerializeField] private Material[] m_Materials;
    
    	// привязываем к кнопкам, передаём номер материала из массива
    	public void OnSelected(int materialId) {
    		// накладываем
    		m_Renderer.material = m_Materials[materialId];
    	}
    }
    Ответ написан
    Комментировать
  • Как сделать отображение и закрытие меню при нажатии одной и той же клавиши?

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    public GameObject tabMenu; 
    bool isOpened; // статус
    
    void Update(){ // клавиши лучше слушать в адейте
    	if (Input.GetKeyDown(KeyCode.Tab)) {
    		isOpened = !isOpened; // меняем статус
    		tabMenu.SetActive(isOpened); // меняем состояние
    	}
    }
    Ответ написан
    1 комментарий
  • Как сделать чтобы партикал двигался за игроком?

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    В этой строке:
    Instantiate(bl_ParticalBlood, transform.position + new Vector3(horizontalInput, verticalInput, 0), Quaternion.identity);

    Добавьте в конец
    Instantiate(bl_ParticalBlood, transform.position + new Vector3(horizontalInput, verticalInput, 0), Quaternion.identity, transform);

    При условии, что сам скрипт на игроке висит.
    Ответ написан
    Комментировать
  • Как сохранить и загрузить массив объектов?

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    Ошибка возникает потому, что код не понимает, по шаблону какого класса ему десериализовать строку
    JsonUtility.FromJson(PlayePrefs.GetString("SecretKey007"));

    Здесь после FromJson должен стоять генерик с указанным типом. Например:
    JsonUtility.FromJson<GameObject>(jsonString);
    Правда это всё равно не будет работать, но это ответ на вопрос.

    UPD. Чтобы работало, подумайте не о сохранении самих объектов, а некоторых их, нужных вам свойств. Например, данных о местоположении, повороте, здоровье и т.д.
    Ответ написан
    Комментировать
  • Что я сделал не так, вход и выход из машины | UNITY | Что делать?

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    Вместо создания дополнительного скрипта можно создать дополнительную переменную. Логику CarTrue, CarFalse и Player я не понимаю, поэтому напишу без них, а вы сами добавите.
    using UnityEngine;
    using System.Collections;
    
    public class CarTrigger : MonoBehaviour {
    
    	// состояние - находится ли игрок в машине
    	private bool isPlayerInCar;
    	// состояние - присутствует ли игрок рядом с машиной
    	private bool isPlayerNearCar;
    
    	private void Update () {
    		// проверку лучше начинать с кнопки, потому что без её нажатия ничего дальше не должно быть запущено
    		if (Input.GetKeyDown(KeyCode.F)) {
    			// в машине? да - выходим!
    			if (isPlayerInCar) {
    				// код выхода
    				// не забываем про статус
    				isPlayerInCar = false;
    			// а если не в машине, то рядом ли мы с машиной? да - садимся
    			} else if (isPlayerNearCar) {
    				// соответствующий код
    				// ну и статус тоже
    				isPlayerInCar = true;
    			}
    		}
    	}
    
    	private void OnTriggerEnter(Collider col) {
    		if (col.tag == "Player") {
    			isPlayerNearCar = true;
    		}
    	}
    
    	private void OnTriggerExit(Collider col) {
    		if (col.tag == "Player") {
    			isPlayerNearCar = false;
    		}
    	}
    }
    Ответ написан
    Комментировать
  • Добрый день, проблема в том что когда я пытаюcь протекстурировать тирейн в юнити ничего не происходит, Что мне делать?

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    Для редактирования используйте палитру слоёв. В компоненте Terrain, раздел редактирования (кисть) в самом верху есть выпадающий список, откройте пункт Paint Textures.
    Если у вас нативный Terrain, то ближе к верху, а если Terrain Tools, то почти в самом низу инспектора ищите что-то типа Terrain Layers. Эти слои как палитра в пеинте/фотошопе, создаёте и рисуете им. Единственное замечание, самый первый станет фоновым, им закрасится весь рельеф.
    Сами Terrain Layer-ы это файл по типу материала, создаются во вкладке Project, в меню они почти в самом низу.

    Если же настроенные и добавленные к рельефу слои не рисуют, то нужен скриншот палитры (в коменты), а лучше всей вкладки Inspector. А также скриншот настроек (вкладка Inspector) одного или парочки слоёв рельефа.
    Ответ написан
    Комментировать
  • Как сделать вложенные объекты в массив в WWWForm?

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    Данный класс лишь вспомогательное средство для оформления запроса.
    Если вам нужно просто передать json строку куда-нибудь в интернет, например, методом POST, можно сделать так:
    public IEnumerator PostRequest(string endpoint, string jsonData, Action<UnityWebRequest> response) {
    	using (UnityWebRequest request = UnityWebRequest.Post(endpoint, new WWWForm())) {		
    		if (jsonData != null) {
    			byte[] postBytes = Encoding.UTF8.GetBytes(jsonData);
    			request.uploadHandler = new UploadHandlerRaw(postBytes);
    		}
    
    		request.SetRequestHeader("Content-Type", "application/json; charset=UTF-8");
    
    		yield return request.SendWebRequest();
    		response(request);
    	}
    }

    А вызывается это дело так:
    StartCoroutine(PostRequest(endpointUrl, jsonData, (e) => ReadResponse(e)));
    
    private void ReadLoginResponse(UnityWebRequest request) {
        // обработка ответа, если нужно
    }
    Ответ написан
  • Как узнать, активна ли на телефоне клавиатура и какова её высота (android 8++)?

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

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    Один коллайдер на комнату будет сложно повесить сразу как комната перестанет быть ровным прямоугольником. Хотя вы можете запариться с Mesh коллайдером, но придётся руками переписывать список вертексов меша каждый раз, когда вы захотите поменять геометрию комнаты.

    Самый простой вариант - реально повесить по коллайдеру на дверь и сделать скрипт, который будет смотреть откуда стучится игрок и в комнате с противоположной стороны запускать экшн.
    Ответ написан
    Комментировать
  • Как сделать толщину LineRenderer постоянной?

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

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    Проблема 100% в коде, которого нет, поэтому я вдамся в гипотезы. Начну с самого хардкорного и закончу тем, что по лайтовее.

    1. Авторазмер
    Возможно, у вас есть скрипт, который при каждом изменении текста пытается отмасштабировать не шрифт, а границы самой компоненты. Проблема в том, что при любом изменении элементов интерфейса юнити перерисовывает вообще весь затронутый канвас. Речь не о свойствах типа цвет, а о перемещении и изменении границ.
    Если у вас такая проблема, то стоит оставить текст в покое и изначально сделать задел по размеру текста на будущее.
    Сюда же можно отнести перерисовку других элементов для ScrollView или использование UI Layouts.

    2. GetComponent
    Возможно, вы используете GetComponent. И делаете это довольно часто. Что-то типа такого:
    public void SetupText(string textToDisplay) {
    	GetComponent<TextMeshPro>().text = textToDisplay;
    }

    Парни с ютуба часто советуют такой треш. Под капотом этот метод довольно тяжёлый и будет тем тяжелее, чем больше компонент на объекте и чем больше раз за единицу времени вызывается.
    Если это ваша проблема, то рекомендую заранее кешировать. Например, сделать это на старте:
    private void Start() {
    	someTextComponent = GetComponent<TextMeshPro>();
    }

    А ещё лучше просто создать видимое инспектором поле и руками туда передать ссылку.
    [SerializeField] TextMeshPro someTextComponent;

    3. Частота вызова
    Ещё один треш, которому учат в интернете - менять что-то или проверять не тогда, когда это нужно, а просто в том же Update. Проблема здесь кроется в множестве "холостых" вызовов.
    Если у вас обновление текста происходит всегда, а не только при необходимости, то стоит подумать лучше над архитектурой.

    4. Размер текста
    Особенность компонент пакета TMPro ещё в том, что метод SetText или аксессор .text не только просто берёт и вставляет, а ещё проводит довольно большую работу под капотом. Если у вас большой текст, вы реально увидите просадку даже на компе, не говоря уже о мобилках. Такая проблема очень актуальна. Например, если вы скриптом или твинами делаете постепенно появляющийся большой объём текста для диалога в игре.
    Решением в данном случае будет либо анимация, либо написание своей реализации нужной компоненты.

    Если среди проблем вашей нет, приложите код. Желательно весь, но в контексте задачи интересна цепочка вызовов от события к присвоению текста.

    PS. на будущее, FPS проекта в редакторе и FPS игры в билде не одно и то же. Сделайте простой счётчик FPS и посмотрите на ситуацию в игре.
    Ответ написан
    Комментировать
  • Пуля при попадании передает много энергии объекту?

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    Не знаю, поможет ли это в вашем случае, но вы можете попробовать:
    1. Внутри объекта по иерархии создаёте пустышку. вешаете ей коллайдер и твёрдое тело
    2. Твёрдому телу ставите Body Type = Kinematic (для 2д) или Is Kinematic = true (для 3д)
    3. Выставляете объект так, чтобы пуля ударилась сперва о его коллайдер.

    Как бонус, вы можете сделать несколько таких объектов (для рук, ног, головы, тела) и передавать скрипту игрока разные коэффициенты урона. Типа, например, попадание в руку 20%, а в голову 150%.
    Ответ написан
    Комментировать
  • Как правильно двигать объекты по нарисованным линиям?

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    Я не знаю, будет ли работать нормально сам код движения, но ваша проблема связана больше с логикой вызова кода движения. Сами посудите, сначала вызывается Update (каждый раз, когда обновляется экран), затем в нём вызывается метод Drive. Напоминаю, каждое обновление экрана, т.е. много раз в секунду.
    Сам же метод сходу берёт и обнуляет прогресс движения:
    targetPointIndex = 1;
    Всё, что ниже, уже просто не имеет смысла.

    Лично я рекомендую вам воспользоваться принципом SRP и делегировать функционал движения отдельному классу. Что-то типа такого:
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class LineRendererFollower : MonoBehaviour {
    
    	public LineRenderer lineRenderer;
    	public float speed;
    	public int nextPointIndex;
    
    	Vector3[] positions;
    
    	void Start() {
    		positions = new Vector3[lineRenderer.positionCount];
    		lineRenderer.GetPositions(positions);
    	}
    
    	void FixedUpdate() {
    		if (Vector3.Distance(transform.position, positions[nextPointIndex]) > 0) {
    			transform.position = Vector3.MoveTowards(transform.position, positions[nextPointIndex], speed * Time.fixedDeltaTime);
    		} else if (nextPointIndex + 1 < positions.Length) {
    			nextPointIndex++;
    			transform.right = (positions[nextPointIndex] - transform.position);
    		} else {
    			// то, что должно случится в конце пути
    		}
    	}
    }
    Ответ написан
    Комментировать
  • Как найти Image в Unity3D?

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    Учитывая, что
    .GetComponent<Image>();
    Может вернуть null без уведомлений, но не сработает, если объект найден не будет, у вас может быть одно из:
    а) Объект не найден вообще и ошибка на эту строку указывает;
    б) Не найден компонент;
    в) Компонент был удалён в промежутке между созданием объекта и вызовом метода столкновения.

    Рекомендую вам взять на вооружение замечательную функцию вкладки Inspector: режим Debug.
    Пример, компонент Image

    64177f43a8eb0086475123.png


    Сперва проверьте, получается ли полем crosshairImage ссылка на Image. Затем удостоверьтесь, что она остаётся на месте до и в момент столкновения. Если она не находится, то одно из двух:
    а) у вас есть несколько объектов с указанным тегом и первым находится объект без Image
    б) она создаётся после попытки её найти, пример: другой класс в Start её создаёт, но этот старт вызывается раньше. В настройках проекта это можно исправить (порядок выполнения скриптов).

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

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    Для начала, наведайтесь в меню "Edit / Project Settings... / Quality". И установите значение Anti Aliasing на Disabled. Оно бывает иногда нужно в 2д играх, но в вашей сейчас точно будет только мешать. Затем нужно создать спрайт атлас.
    Во вкладке Project создайте новый файл, в меню создания выберите "2D / Sprite Atlas". Затем выделите его, чтобы видеть его свойства в инспекторе. Внизу будет список, подписанный как Objects for Packing. Перетащите туда не отдельные картинки, а весь импортированный файл.
    В редакторе линии могут остаться, но при запуске и в билде их точно не должно быть.
    Если не сработало или не понятно объяснил - пишите в комменты.
    Ответ написан