130 lines
4.3 KiB
C#
130 lines
4.3 KiB
C#
using Newtonsoft.Json.Linq;
|
|
using UnityEngine;
|
|
using UnityEngine.Events;
|
|
|
|
namespace UHFPS.Runtime
|
|
{
|
|
public class LookAtTrigger : MonoBehaviour, ISaveable
|
|
{
|
|
public enum TriggerTypeEnum { Once, MoreTimes }
|
|
|
|
public TriggerTypeEnum TriggerType;
|
|
public LayerMask CullMask;
|
|
public Vector2 ViewportOffset = Vector2.one;
|
|
|
|
public bool LookAwayViewport = false;
|
|
public bool UseDistance = false;
|
|
|
|
public bool CallEventOutsideDistance = false;
|
|
public bool VisualizeDistance = false;
|
|
public float TriggerDistance = 5f;
|
|
|
|
public UnityEvent OnLookAt;
|
|
public UnityEvent OnLookAway;
|
|
|
|
private PlayerPresenceManager playerPresence;
|
|
private bool isLookedOnce = false;
|
|
private bool resetLook = false;
|
|
|
|
private void Awake()
|
|
{
|
|
playerPresence = PlayerPresenceManager.Instance;
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
Camera playerCamera = playerPresence.PlayerCamera;
|
|
Transform cameraTransform = playerCamera.transform;
|
|
bool inDistance = true;
|
|
|
|
if (UseDistance)
|
|
{
|
|
Vector3 playerPos = playerPresence.Player.transform.position;
|
|
float distance = Vector3.Distance(transform.position, playerPos);
|
|
inDistance = distance <= TriggerDistance;
|
|
}
|
|
|
|
if(inDistance && !Physics.Linecast(transform.position, cameraTransform.position, CullMask))
|
|
{
|
|
Vector3 screenPoint = playerCamera.WorldToViewportPoint(transform.position);
|
|
if(screenPoint.x >= 0 && screenPoint.x <= 1 && screenPoint.y >= 0 && screenPoint.y <= 1 && screenPoint.z > 0)
|
|
{
|
|
float xMin = 1 - Remap(ViewportOffset.x);
|
|
float xMax = Remap(ViewportOffset.x);
|
|
|
|
float yMin = 1 - Remap(ViewportOffset.y);
|
|
float yMax = Remap(ViewportOffset.y);
|
|
|
|
if (screenPoint.x >= xMin && screenPoint.x <= xMax && screenPoint.y >= yMin && screenPoint.y <= yMax)
|
|
{
|
|
if (!isLookedOnce)
|
|
{
|
|
OnLookAt?.Invoke();
|
|
isLookedOnce = true;
|
|
resetLook = false;
|
|
}
|
|
}
|
|
else if (LookAwayViewport && isLookedOnce && !resetLook)
|
|
{
|
|
OnLookAway?.Invoke();
|
|
resetLook = true;
|
|
|
|
if (TriggerType == TriggerTypeEnum.MoreTimes)
|
|
{
|
|
isLookedOnce = false;
|
|
}
|
|
}
|
|
}
|
|
else if(!LookAwayViewport && isLookedOnce && !resetLook)
|
|
{
|
|
OnLookAway?.Invoke();
|
|
resetLook = true;
|
|
|
|
if (TriggerType == TriggerTypeEnum.MoreTimes)
|
|
{
|
|
isLookedOnce = false;
|
|
}
|
|
}
|
|
}
|
|
else if (TriggerType == TriggerTypeEnum.MoreTimes)
|
|
{
|
|
if (CallEventOutsideDistance && isLookedOnce)
|
|
OnLookAway?.Invoke();
|
|
|
|
isLookedOnce = false;
|
|
resetLook = true;
|
|
}
|
|
}
|
|
|
|
private float Remap(float value)
|
|
{
|
|
return (value - 0) / (1 - 0) * (1 - 0.5f) + 0.5f;
|
|
}
|
|
|
|
private void OnDrawGizmosSelected()
|
|
{
|
|
if (!UseDistance || !VisualizeDistance)
|
|
return;
|
|
|
|
#if UNITY_EDITOR
|
|
UnityEditor.Handles.color = Color.yellow;
|
|
UnityEditor.Handles.DrawWireDisc(transform.position, Vector3.up, TriggerDistance);
|
|
#endif
|
|
}
|
|
|
|
public StorableCollection OnSave()
|
|
{
|
|
return new StorableCollection()
|
|
{
|
|
{ nameof(isLookedOnce), isLookedOnce },
|
|
{ nameof(resetLook), resetLook }
|
|
};
|
|
}
|
|
|
|
public void OnLoad(JToken data)
|
|
{
|
|
isLookedOnce = (bool)data["isLookedOnce"];
|
|
resetLook = (bool)data["resetLook"];
|
|
}
|
|
}
|
|
} |