121 lines
2.9 KiB
C#
121 lines
2.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Managers;
|
|
using UnityEngine;
|
|
|
|
public class OffScreenIndicatorManager : MonoBehaviour
|
|
{
|
|
public GameObject[] Targets;
|
|
public GameObject IndicatorPrefab;
|
|
public Color DefaultColor = Color.yellow;
|
|
|
|
private MeshRenderer _meshRenderer;
|
|
|
|
private Camera _camera;
|
|
private Dictionary<GameObject, GameObject> _targetIndicators = new();
|
|
|
|
// Start is called before the first frame update
|
|
void Start()
|
|
{
|
|
_camera = Camera.main;
|
|
|
|
foreach (var target in Targets)
|
|
AddTarget(target);
|
|
}
|
|
|
|
// Update is called once per frame
|
|
void Update()
|
|
{
|
|
if (_camera == null)
|
|
{
|
|
if (Camera.main != null)
|
|
_camera = Camera.main;
|
|
return;
|
|
}
|
|
bool targetRemoved = false;
|
|
foreach (KeyValuePair<GameObject, GameObject> entry in _targetIndicators)
|
|
{
|
|
var target = entry.Key;
|
|
var indicator = entry.Value;
|
|
|
|
if (target != null)
|
|
{
|
|
UpdateTarget(target, indicator);
|
|
}
|
|
else
|
|
{
|
|
targetRemoved = true;
|
|
}
|
|
}
|
|
|
|
if (!targetRemoved)
|
|
return;
|
|
|
|
GameObject[] targets = _targetIndicators.Keys.ToArray();
|
|
for (int i = 0; i < targets.Count(); ++i)
|
|
{
|
|
if (targets[i] == null)
|
|
{
|
|
Destroy(_targetIndicators[targets[i]]);
|
|
_targetIndicators.Remove(targets[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void AddTarget(GameObject target)
|
|
{
|
|
AddTarget(target, DefaultColor);
|
|
}
|
|
|
|
public void AddTarget(GameObject target, Color color)
|
|
{
|
|
var indicator = Instantiate(IndicatorPrefab);
|
|
_meshRenderer = indicator.GetComponentInChildren<MeshRenderer>();
|
|
indicator.SetActive(false);
|
|
indicator.transform.SetParent(_camera.transform);
|
|
_targetIndicators.Add(target, indicator);
|
|
|
|
MaterialPropertyBlock materialPropertyBlock = new();
|
|
materialPropertyBlock.SetColor("_BaseColor", color);
|
|
_meshRenderer.SetPropertyBlock(materialPropertyBlock);
|
|
}
|
|
|
|
private void UpdateTarget(GameObject target, GameObject indicator)
|
|
{
|
|
if (MatchManager.G.matchState != MatchState.Match || target == null
|
|
|| !target.activeInHierarchy)
|
|
{
|
|
indicator.SetActive(false);
|
|
return;
|
|
}
|
|
var screenPos = _camera.WorldToViewportPoint(target.transform.position);
|
|
bool isOffScreen = screenPos.x <= 0 || screenPos.x >= 1 ||
|
|
screenPos.y <= 0 || screenPos.y >= 1;
|
|
if (!isOffScreen)
|
|
{
|
|
indicator.SetActive(false);
|
|
return;
|
|
}
|
|
indicator.SetActive(true);
|
|
|
|
float margin_x = 0.05f;
|
|
float margin_y = 0.05f;
|
|
|
|
screenPos.x = Mathf.Clamp(screenPos.x, margin_x, 1 - margin_x);
|
|
screenPos.y = Mathf.Clamp(screenPos.y, margin_y, 1 - margin_y);
|
|
screenPos.z = Mathf.Clamp(screenPos.z, 0, 1);
|
|
|
|
var worldPosition = _camera.ViewportToWorldPoint(screenPos);
|
|
|
|
var cameraDirection = _camera.transform.position - worldPosition;
|
|
|
|
indicator.transform.position = worldPosition;
|
|
|
|
var virtualIndicatorPosition = worldPosition + _camera.transform.localPosition.z * cameraDirection;
|
|
|
|
Vector3 direction = target.transform.position - virtualIndicatorPosition;
|
|
indicator.transform.rotation = Quaternion.FromToRotation(new Vector3(0, 0, 1), direction);
|
|
}
|
|
}
|