Космический радар

Программирование на Юнити.

Космический радар

Сообщение siriusspark 22 апр 2017, 23:52

Всем привет, нужна помощь.

Хочу сделать в космосиме, ну не то чтобы даже радар, а скорее целеуказатель. Суть в следующем: все объекты на экране, у которых есть тег, ну скажем Detected, должны отмечаться маркерами, что то типа ромбиков там каких, не суть. Вопрос в том, что что то оно у меня не получается. Как должно работать вроде понимаю, но делаю видимо что то не то.

Алгоритм работы как я его вижу (исполняется в Update):
1. Найти все объекты с тегом Detected в заданном радиусе вокруг корабля, загнать их в массив.
2. Создать массив маркеров, размером как и массив объектов.
3. Отсеять те цели, которые в данном кадре не попадают в камеру.
4. Получить экранные координаты каждого из видимых объектов.
5. Привязать к каждой из полученных координат по иконке маркера.

По идее как то так. Основных вопросов в принципе два - как найти все объекты вокруг (через триггеры или OverlapSphere или ещё как то) и как получить массив иконок из одного публичного Image? А может там вообще массив не нужен?

В общем плиз хелп))
Star Wars: Path of lust. 3D-адвенчур 18+ по мотивам Звездных войн | _www.patreon.com/starlordgames
Аватара пользователя
siriusspark
UNIт
 
Сообщения: 106
Зарегистрирован: 10 сен 2015, 09:14

Re: Космический радар

Сообщение Kabanelloo 23 апр 2017, 10:56

А почему бы просто не привязать иконку для каждого юнита ?
Зачем ее навязывать постоянно?

В увиденном окне отсканируй найденные цели , пусть слои разделяют своих и чужих пример Alliance - свои FirstOrder- чужие

а теги оставь для чего-нибудь другого. Потом из твоего от сканированного массива сравнивай враг ли это и включи таргет.

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

https://www.youtube.com/watch?v=PwF7ooHMPJU

// разошли приглашение каждому противнику в поле зрения и обратное когда выходит из видимости
Синтаксис:
Используется csharp
foreach(var item in ViewArrayEnemy)
{

if(item.gameObject.layer != Alliance)
{
  item.gameObject.SendMessage("EnabledTargetIco");
}

}
 


код для вcпомогатора

Синтаксис:
Используется csharp

public void EnabledTargetIco()
{
  //включение иконки на данном объекте например это спрайт билборд который смотрит в камеру или заставить его таращиться тебе в камеру через трансформ.
}

public void DisableTargetIco()
{
  //выключение иконки на данном объекте.
}
 
Kabanelloo
UNITрон
 
Сообщения: 163
Зарегистрирован: 03 фев 2012, 21:55
Откуда: Kaliningrad/Crimea

Re: Космический радар

Сообщение EagleOwle 23 апр 2017, 11:31

Я так делаю...
У префаба есть дочерний обьект Indicator c компонентом RectTransform и оправляющим скриптом.
Синтаксис:
Используется csharp
public abstract class UI_BotIndicatorBasys : MonoBehaviour
{
    [Header("Ссылка на данный RectTransform")]
    [SerializeField] protected RectTransform rectTarnsform;

    [SerializeField]
    protected BotControllerBasys botController;

    [Header("Высота над обьектом - целью")]
    [SerializeField]
    protected float upValue = 1;

    [Header("Максимальный угол видимости индикатора")]
    [SerializeField]
    protected float maxAngle;

    [Header("Обьект идикатор, который вкл/выкл")]
    [SerializeField]
    protected GameObject indicatorObj;

    [Header("Ссылка на ui обьект, к которому удачеряется данный обьект")]
    [SerializeField]
    protected Transform parentTransform;

    protected Camera camera;

    protected void Awake()
    {
        botController = GetComponentInParent<BotControllerBasys>();
    }

    protected virtual void OnEnable()
    {
        indicatorObj.SetActive(true);

        if (camera == null)
        {
            camera = GameObject.Find("Player").GetComponentInChildren<Camera>();
        }
    }

    protected virtual void Update()
    {
       
    }

    protected bool CheckAngle(float maxAngle, Vector3 front1, Vector3 front2)
    {
        if (Vector3.Angle(front1, front2) > maxAngle)
        {
            return false;
        }

        return true;
    }

    protected void SetScreenPosition(Vector3 position, float upValue)
    {
        rectTarnsform.position = camera.WorldToScreenPoint(position + Vector3.up * upValue);
    }
}

using UnityEngine;
using System.Collections;
using UnityEngine.UI;

public class UI_HeathIndicator : UI_BotIndicatorBasys
{
    [Header("Локальные переменные")]
    [SerializeField]
    private RectTransform healthImageTransform;

    [Header("Debug")]
    public float currentHealth;
    public Vector2 currentSize;

    protected override void Update()
    {
        base.Update();

        if (botController.Health <= 0)
        {
            indicatorObj.SetActive(false);
            return;
        }

        if (botController.gameObject.activeSelf == false)
        {
            indicatorObj.SetActive(false);
            return;
        }

        if (GameController.showBotIndicator == false)
        {
            indicatorObj.SetActive(false);
            return;
        }

        if (CheckAngle(maxAngle, PlayerController.selfTransform.TransformDirection(Vector3.forward * 100), botController.thisTransform.position - PlayerController.selfTransform.position) == false)
        {
            indicatorObj.SetActive(false);
            return;
        }


        indicatorObj.SetActive(true);
        SetScreenPosition(botController.thisTransform.position, upValue);
        SetSizeImage(botController.Health);
        //Debug
        currentHealth = botController.Health;
        currentSize = rectTarnsform.sizeDelta;
        //EndDebug
    }

    private void SetSizeImage(float value)
    {
        healthImageTransform.sizeDelta = new Vector2(value, 10);
    }
}
 


На старте indicator находит Canvas и удочеряется к нему.
В дальнейшем он имеет ссылку на класс обьект - цель и может оперировать его данными(здоровье, позиция, имя, все, что вам может понадобится отобразить на экране)
А свою видимость на экране он определяет расчетом угла между камерой и целью.

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

arrayEnemyBot = arrayEnemyBot.OrderByDescending(obj => ((botController.transform.position + tempVector) - (obj.transform.position + tempVector)).sqrMagnitude).ToList();

У меня этим занимается радар.
EagleOwle
UNIверсал
 
Сообщения: 493
Зарегистрирован: 02 янв 2015, 16:27

Re: Космический радар

Сообщение Kabanelloo 23 апр 2017, 12:27

https://habrahabr.ru/post/256273/ вот держи урок видимости и слышимости.
Kabanelloo
UNITрон
 
Сообщения: 163
Зарегистрирован: 03 фев 2012, 21:55
Откуда: Kaliningrad/Crimea

Re: Космический радар

Сообщение siriusspark 23 апр 2017, 16:57

Это не совсем то.

Вот примерно что я хочу получить.

Изображение

Цели, которые требуется уничтожить, должны подсвечиваться вот каким-то такими маркерами
Star Wars: Path of lust. 3D-адвенчур 18+ по мотивам Звездных войн | _www.patreon.com/starlordgames
Аватара пользователя
siriusspark
UNIт
 
Сообщения: 106
Зарегистрирован: 10 сен 2015, 09:14

Re: Космический радар

Сообщение Anonymyx 23 апр 2017, 17:39

Делаете префаб UI маркера, Находите все объекты которые надо уничтожить т.е. получаете массив, инстаншиируете префаб маркера для каждого объекта и передаете им Transform соотв. объекта.
У маркера в Update переводите мировые координаты объекта в экранные и перемещаете за ними маркер.
Аватара пользователя
Anonymyx
Адепт
 
Сообщения: 1973
Зарегистрирован: 05 апр 2015, 15:55

Re: Космический радар

Сообщение EagleOwle 23 апр 2017, 18:40

Я ж тебе скинул практически готовый код... пару правок под свою специфику, и всё.
EagleOwle
UNIверсал
 
Сообщения: 493
Зарегистрирован: 02 янв 2015, 16:27


Вернуться в Скрипты

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 6