Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- public class HighlightGameObject : MonoBehaviour
- {
- public Texture iconTexture;
- public bool animated = false;
- // Позиция на экране, где следует разместить
- // иконку.
- Vector2 highlightIconPosition;
- // Насколько спустить иконку вниз,
- // без этого параметра иконка могла быть
- // впритык к нижнему краю меша.
- float downY = 10;
- // Если игрок (камера), находится к объекту
- // на расстоянии minDistance и меньше,
- // то ширина иконки будет maxIconWidth.
- // По мере удаления от объекта иконка в дальнешем
- // будет уменьшаться, как будто это реальный 3d объект.
- float minDistance = 2f;
- float maxIconWidth = 50;
- // Для корректного размера Rect.
- float iconAspect;
- // Если анимация включена, то понадобятся
- // эти параметры.
- // Сдвиг анимации по вертикали:
- float animationYDistance = 20;
- float animationSpeed = 0.87f;
- float lerp = 0;
- // Кешируем.
- Camera mainCamera;
- Rect rect = new Rect();
- Mesh mesh;
- void Start()
- {
- mainCamera = Camera.main;
- mesh = transform.GetComponent<MeshFilter>().mesh;
- iconAspect = iconTexture.width / iconTexture.height;
- }
- void Update()
- {
- SetHighlightIconPosition();
- }
- void OnGUI()
- {
- // Здесь реализуем изменение размеров иконки так, словно
- // это реальный 3d объект, то есть, если он близко, то
- // он большой, а если отходить - то он становится все меньше,
- // причем уменьшение должно быть реалистичным.
- // Расстояние от камеры игрока до объекта.
- float distance = (mainCamera.transform.position - transform.position).magnitude;
- // Какое значение должно быть, когда иконка должна быть
- // максимальной ширины. Допустим, сейчас там значение равно 450.
- float maxScale = minDistance * Camera.main.fieldOfView;
- // Какое значение сейчас? Допустим оно 900.
- float currentScale = distance * Camera.main.fieldOfView;
- // Это значит, 450/900 = 0.5 настолько надо
- // изменить масштаб иконки, чтобы он соотвествовал тому размеру
- // как если бы он был реальным 3d объектом, от которого отошли.
- float scale = maxScale / currentScale;
- // Такое возможно, если игрок слишком близко к
- // объекту, то есть, расстояние distance меньше
- // чем значение minDistance
- if (scale > 1) scale = 1;
- // Актульная ширина иконки.
- float width = maxIconWidth * scale;
- float height = width / iconAspect;
- // Выравниваем по центру, учитывая ее ширину.
- rect.x = highlightIconPosition.x - (width / 2);
- rect.y = highlightIconPosition.y + downY;
- if (animated)
- {
- lerp += Time.deltaTime * animationSpeed;
- lerp = Mathf.Clamp(lerp, 0, 1);
- if (lerp >= 1) lerp = 0;
- rect.y -= Mathf.Lerp(-animationYDistance * scale, 0, lerp);
- }
- rect.width = width;
- rect.height = height;
- GUI.DrawTexture(rect, iconTexture, ScaleMode.ScaleToFit, true);
- }
- void SetHighlightIconPosition()
- {
- // Перебираем все вершины и переводим
- // и в экранные координаты
- Vector3[] vertices = mesh.vertices;
- for (int i = 0; i < vertices.Length; i++)
- {
- vertices[i] = transform.TransformPoint(vertices[i]);
- vertices[i] = mainCamera.WorldToScreenPoint(vertices[i]);
- vertices[i].y = Screen.height - vertices[i].y;
- }
- // Ищем самые минимальные и максимальные координаты.
- // Например, если на экране нарисовать прямоугольник,
- // где левый нижий с координатами min, а правый верхний
- // с координатами max, то этот прямоугольник
- // впритык впишет в себя объект.
- Vector2 min = vertices[0];
- Vector2 max = vertices[0];
- for (int i = 1; i < vertices.Length; i++)
- {
- min = Vector3.Min(min, vertices[i]);
- max = Vector3.Max(max, vertices[i]);
- }
- max.x = (max.x + min.x) / 2;
- // В примере выше, эта координата - середина
- // нижней рамки прямоугольника, который
- // вписал в себя объект.
- highlightIconPosition = max;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment