Top.Mail.Ru
Ответы

Unity: Почему не отображается плавающий текст урона/лечения?

Здравствуйте!
Я создаю 2D игру на Unity для мобильных устройств (в пиксель-арте), и пытаюсь реализовать всплывающий текст урона и лечения — например, при получении урона появляется “-1”, при восстановлении “+1”, при полном исцелении — “Full”.

Использую TextMeshProUGUI внутри префаба, который появляется через Canvas. Позицию текста определяю через Camera.main.WorldToScreenPoint(...), чтобы он появлялся над персонажем.

Но вот в чём проблема:
1. Текст появляется на сцене, но не отображается в игре.
2. Если посмотреть в режиме Scene — текст улетает на координаты вроде X = 8000+.
3. Иногда вообще появляется без цвета или шрифта.
4. Canvas существует, создан отдельно (в Screen Space - Overlay).
5. Префаб корректно назначен и спавнится при получении урона.

Я уже пробовал:
• Использовать World Space / Overlay
• Привязку к пустому textSpawnPoint на голове персонажа
• Задержку и Destroy через скрипт
• Разные камеры и Canvas’ы

Вопрос:
Что может быть причиной такой ошибки? Как правильно отобразить TextMeshProUGUI, чтобы он появлялся строго над игроком в нужной точке экрана?

Буду рад любой помощи. С меня плюсик!

По дате
По Рейтингу
Аватар пользователя
Мастер
1мес

Ответ от LLM O4-mini: Привет! Часто такая «уплывающая» цифра урона — это просто неверное позиционирование UI-элемента: ты инстанцируешь TextMeshProUGUI-префаб без привязки к Canvas и тупо пишешь в world-координатах значение экранных пикселей. В результате RectTransform берет эти «пиксели» как мировые юниты и уходит на несколько тысяч.

Как это обычно делается правильно:

1) Один единственный Canvas в режиме Screen Space – Overlay (или Screen Space – Camera)
2) Пре-фаб всплывающего текста имеет TextMeshProUGUI + RectTransform
3) При спавне ты сразу делаешь его дочерним к Canvas (с false-сбросом локальных трансформ), а позицию задаёшь уже в UI-координатах

Ниже пример кода (C#) для Screen Space – Overlay:

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
 using UnityEngine;  
 
using TMPro;  
 
  
 
public class FloatingTextSpawner : MonoBehaviour  
 
{  
 
    [SerializeField] private RectTransform canvasRect;      // Ссылка на RectTransform Canvas  
 
    [SerializeField] private GameObject textPrefab;         // Префаб с TextMeshProUGUI  
 
  
 
    public void Spawn(Vector3 worldPosition, string message)  
 
    {  
 
        // 1) Конвертируем world→screen  
 
        Vector2 screenPoint = RectTransformUtility.WorldToScreenPoint(Camera.main, worldPosition);  
 
  
 
        // 2) Создаём UI-объект сразу под Canvas  
 
        GameObject go = Instantiate(textPrefab, canvasRect);  
 
        go.transform.localScale = Vector3.one; // сброс масштабов  
 
  
 
        // 3) Переводим screenPoint в локальные координаты Canvas  
 
        RectTransformUtility.ScreenPointToLocalPointInRectangle(  
 
            canvasRect, screenPoint, null, out Vector2 localPoint);  
 
  
 
        // 4) Устанавливаем на местоположение  
 
        RectTransform rt = go.GetComponent<RectTransform>();  
 
        rt.anchoredPosition = localPoint;  
 
  
 
        // 5) Пишем текст  
 
        TextMeshProUGUI tmp = go.GetComponent<TextMeshProUGUI>();  
 
        tmp.text = message;  
 
  
 
        // 6) (Опционально) старт анимации и уничтожение  
 
        Destroy(go, 1.0f);  
 
    }  
 
}  



Разбор по пунктам:
- Canvas в режиме Screen Space – Overlay не требует камеры в `ScreenPointToLocalPointInRectangle` (ставим `null`).
- `Instantiate(textPrefab, canvasRect)` сразу делает префаб дочерним по-умолчанию и сбрасывает мировую позицию → ты не получишь этих 8000+ юнитов.
- `anchoredPosition` — правильный способ сместить элемент внутри Canvas.
- Убедись, что `textPrefab` имеет `RectTransform` и компонент `TextMeshProUGUI`, и что шрифт (Font Asset) действительно включён в билд.

Если ты используешь Screen Space – Camera:
- В Canvas ставишь Render Mode = Screen Space – Camera и в поле «Render Camera» указываешь свою камеру.
- При вызове `ScreenPointToLocalPointInRectangle` вместо `null` передаёшь эту камеру.

Ещё пара советов:
• Проверь CanvasScaler: на каком разрешении ты тестишь и какое в билде (от этого тоже зависят UI-координаты).
• Убедись, что у префаба локальные Scale = (1,1,1), Rotation = (0,0,0).
• Если текст «без шрифта» — вероятно, Font Asset не попал в билд. Принудительно засвети его в Resources или в настройках Addressables/AssetBundle.

Вариант «в мире» (World Space Canvas):
- Меняешь Canvas на World Space, прикрепляешь его к персонажу (или в корень сцены),
- Тогда при инстансе просто пишешь `go.transform.position = worldPosition + Vector3.up * offset;`
- Но, IMHO, проще иметь один Overlay-Canvas и рисовать цифры через конвертацию world→screen.

Надеюсь, это поможет. Если что-то остальное не работает, напиши, посмотрим лог ошибок или конкретные настройки Canvas/камер. Удачи! 🚀