Files
2026-02-21 16:45:37 +08:00

135 lines
3.3 KiB
C#

using System;
using UnityEngine;
using UnityEngine.Serialization;
namespace EnergyBarToolkit
{
[ExecuteInEditMode]
public class EnergyBarFollowObject : MonoBehaviour
{
public GameObject followObject;
public Vector3 offset;
[FormerlySerializedAs("barRotation")]
public Vector3 rotation;
public ObjectFinder worldCamera = new ObjectFinder(typeof(Camera), "/Main Camera", "MainCamera", ObjectFinder.Method.ByTag);
public bool lookAtCamera = true;
public bool updateLookupReference;
[SerializeField]
[HideInInspector]
private Camera renderCamera;
private Camera cameraReference;
private Canvas canvas;
public bool IsPossiblyVisible()
{
if (followObject != null && cameraReference != null)
{
Vector3 lhs = followObject.transform.position - cameraReference.transform.position;
float num = Vector3.Dot(lhs, cameraReference.transform.forward);
return num >= 0f;
}
Debug.LogError("Cannot determine visibility of this bar.", this);
return false;
}
private void OnEnable()
{
}
private void Start()
{
}
private void Update()
{
if (!(followObject != null))
{
return;
}
if (!Application.isPlaying || canvas == null)
{
canvas = GetComponentInParent<Canvas>();
if (canvas == null)
{
Debug.LogError("This object should be placed under a canvas", this);
}
}
if (!Application.isPlaying || cameraReference == null || updateLookupReference)
{
cameraReference = worldCamera.Lookup<Camera>(this);
}
UpdateFollowObject();
bool flag = IsPossiblyVisible();
EnergyBarBase component = GetComponent<EnergyBarBase>();
component.opacity = (flag ? 1 : 0);
if (cameraReference != null && canvas != null)
{
if (canvas.renderMode == RenderMode.WorldSpace && lookAtCamera)
{
component.transform.rotation = Quaternion.LookRotation(component.transform.position - cameraReference.transform.position);
}
else
{
component.transform.rotation = Quaternion.Euler(rotation);
}
}
}
private void UpdateFollowObject()
{
switch (canvas.renderMode)
{
case RenderMode.ScreenSpaceOverlay:
UpdateFollowObjectScreenSpaceOverlay();
break;
case RenderMode.ScreenSpaceCamera:
UpdateFollowObjectScreenSpaceCamera();
break;
case RenderMode.WorldSpace:
UpdateFollowObjectWorldSpace();
break;
default:
throw new ArgumentOutOfRangeException();
}
}
private void UpdateFollowObjectScreenSpaceOverlay()
{
UpdateScreenSpace();
}
private void UpdateFollowObjectScreenSpaceCamera()
{
UpdateScreenSpace();
}
private void UpdateScreenSpace()
{
if (cameraReference == null)
{
Debug.LogError("Render Camera must be set for the follow script to work.", this);
return;
}
Rect pixelRect = canvas.pixelRect;
float x = pixelRect.width / 2f;
float y = pixelRect.height / 2f;
Vector3 vector = cameraReference.WorldToScreenPoint(followObject.transform.position);
Vector3 vector2 = vector + offset - new Vector3(x, y);
MadTransform.SetLocalPosition(localPosition: new Vector3(vector2.x / canvas.scaleFactor, vector2.y / canvas.scaleFactor), transform: base.transform);
}
private void UpdateFollowObjectWorldSpace()
{
MadTransform.SetPosition(base.transform, followObject.transform.position + offset);
}
}
}