Guest User

Untitled

a guest
Feb 13th, 2023
164
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 5.58 KB | Source Code | 0 0
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4.  
  5. public class HighlightGameObject : MonoBehaviour
  6. {
  7.  
  8.     public Texture iconTexture;
  9.     public bool animated = false;
  10.  
  11.     // Позиция на экране, где следует разместить
  12.     // иконку.
  13.     Vector2 highlightIconPosition;
  14.     // Насколько спустить иконку вниз,
  15.     // без этого параметра иконка могла быть
  16.     // впритык к нижнему краю меша.
  17.     float downY = 10;
  18.  
  19.  
  20.     // Если игрок (камера), находится к объекту
  21.     // на расстоянии minDistance и меньше,
  22.     // то ширина иконки будет maxIconWidth.
  23.     // По мере удаления от объекта иконка в дальнешем
  24.     // будет уменьшаться, как будто это реальный 3d объект.
  25.     float minDistance = 2f;
  26.     float maxIconWidth = 50;
  27.  
  28.     // Для корректного размера Rect.
  29.     float iconAspect;
  30.  
  31.     // Если анимация включена, то понадобятся
  32.     // эти параметры.
  33.     // Сдвиг анимации по вертикали:
  34.     float animationYDistance = 20;
  35.     float animationSpeed = 0.87f;
  36.     float lerp = 0;
  37.  
  38.     // Кешируем.
  39.     Camera mainCamera;
  40.     Rect rect = new Rect();
  41.     Mesh mesh;
  42.  
  43.     void Start()
  44.     {
  45.         mainCamera = Camera.main;
  46.         mesh = transform.GetComponent<MeshFilter>().mesh;
  47.         iconAspect = iconTexture.width / iconTexture.height;
  48.     }
  49.  
  50.     void Update()
  51.     {
  52.         SetHighlightIconPosition();
  53.     }
  54.  
  55.     void OnGUI()
  56.     {
  57.         // Здесь реализуем изменение размеров иконки так, словно
  58.         // это реальный 3d объект, то есть, если он близко, то
  59.         // он большой, а если отходить - то он становится все меньше,
  60.         // причем уменьшение должно быть реалистичным.
  61.  
  62.         // Расстояние от камеры игрока до объекта.
  63.         float distance = (mainCamera.transform.position - transform.position).magnitude;
  64.         // Какое значение должно быть, когда иконка должна быть
  65.         // максимальной ширины. Допустим, сейчас там значение равно 450.
  66.         float maxScale = minDistance * Camera.main.fieldOfView;
  67.         // Какое значение сейчас? Допустим оно 900.
  68.         float currentScale = distance * Camera.main.fieldOfView;
  69.         // Это значит, 450/900 = 0.5 настолько надо
  70.         // изменить масштаб иконки, чтобы он соотвествовал тому размеру
  71.         // как если бы он был реальным 3d объектом, от которого отошли.
  72.         float scale = maxScale / currentScale;
  73.         // Такое возможно, если игрок слишком близко к
  74.         // объекту, то есть, расстояние distance меньше
  75.         // чем значение minDistance
  76.         if (scale > 1) scale = 1;
  77.  
  78.         // Актульная ширина иконки.
  79.         float width = maxIconWidth * scale;
  80.         float height = width / iconAspect;
  81.         // Выравниваем по центру, учитывая ее ширину.
  82.         rect.x = highlightIconPosition.x - (width / 2);
  83.         rect.y = highlightIconPosition.y + downY;
  84.         if (animated)
  85.         {
  86.             lerp += Time.deltaTime * animationSpeed;
  87.             lerp = Mathf.Clamp(lerp, 0, 1);
  88.             if (lerp >= 1) lerp = 0;
  89.             rect.y -= Mathf.Lerp(-animationYDistance * scale, 0, lerp);
  90.         }
  91.         rect.width = width;
  92.         rect.height = height;
  93.         GUI.DrawTexture(rect, iconTexture, ScaleMode.ScaleToFit, true);
  94.     }
  95.  
  96.     void SetHighlightIconPosition()
  97.     {
  98.         // Перебираем все вершины и переводим
  99.         // и в экранные координаты
  100.         Vector3[] vertices = mesh.vertices;
  101.         for (int i = 0; i < vertices.Length; i++)
  102.         {
  103.             vertices[i] = transform.TransformPoint(vertices[i]);
  104.             vertices[i] = mainCamera.WorldToScreenPoint(vertices[i]);
  105.             vertices[i].y = Screen.height - vertices[i].y;
  106.         }
  107.         // Ищем самые минимальные и максимальные координаты.
  108.         // Например, если на экране нарисовать прямоугольник,
  109.         // где левый нижий с координатами min, а правый верхний
  110.         // с координатами max, то этот прямоугольник
  111.         // впритык впишет в себя объект.
  112.         Vector2 min = vertices[0];
  113.         Vector2 max = vertices[0];
  114.         for (int i = 1; i < vertices.Length; i++)
  115.         {
  116.             min = Vector3.Min(min, vertices[i]);
  117.             max = Vector3.Max(max, vertices[i]);
  118.         }
  119.         max.x = (max.x + min.x) / 2;
  120.         // В примере выше, эта координата - середина
  121.         // нижней рамки прямоугольника, который
  122.         // вписал в себя объект.
  123.         highlightIconPosition = max;
  124.     }
  125. }
  126.  
Advertisement
Add Comment
Please, Sign In to add comment