Question by
luismgf321 · May 10, 2020 at 02:15 AM ·
c#camerarecttransformworldtoscreenpointindicator
Strange behaviour with WorldToScreenPoint
Hello, I am trying to make an off-screen target indicator (COD revive style) with WorldToScreenPoint, it works as expected on the orthographic camera, but in perspective it behaves strangely when z position is negative. Any suggestion is appreciated. Video of the behaviour.
using UnityEngine;
public class ReviveIndicator : MonoBehaviour
{
public RectTransform indicator;
public Transform target;
Camera mainCamera;
void Start()
{
mainCamera = Camera.main;
}
void Update()
{
Vector3 pos = mainCamera.WorldToScreenPoint(target.position);
if(pos.z < 0)
{
pos *= -1;
}
pos.x = Mathf.Clamp(pos.x, 0, Screen.width);
pos.y = Mathf.Clamp(pos.y, 0, Screen.height);
indicator.position = pos;
}
}
Comment
Best Answer
Answer by luismgf321 · May 10, 2020 at 06:56 AM
I got it.
using UnityEngine;
public class ReviveIndicator : MonoBehaviour
{
[Header("References")]
public RectTransform indicator;
public Transform target;
Transform canvas;
Camera mainCamera;
[Header("Variables")]
public Vector3 offset;
Vector3 screenCentre;
void Start()
{
canvas = UIReferences.instance.transform;
mainCamera = Camera.main;
}
void Update()
{
Vector3 screenPosition = mainCamera.WorldToScreenPoint(target.position);
if (IsTargetVisible(screenPosition))
{
Vector3 pos = mainCamera.WorldToScreenPoint(target.position + offset);
indicator.position = Vector3.MoveTowards(indicator.position, pos, 500 * Time.deltaTime);
return;
}
screenCentre = new Vector3(Screen.width, Screen.height, 0) / 2;
screenPosition -= screenCentre;
if (screenPosition.z < 0)
{
screenPosition *= -1;
}
float angle = Mathf.Atan2(screenPosition.y, screenPosition.x);
float slope = Mathf.Tan(angle);
if (screenPosition.x > 0)
{
screenPosition = new Vector3(screenCentre.x, screenCentre.x * slope, 0);
}
else
{
screenPosition = new Vector3(-screenCentre.x, -screenCentre.x * slope, 0);
}
if (screenPosition.y > screenCentre.y)
{
screenPosition = new Vector3(screenCentre.y / slope, screenCentre.y, 0);
}
else if (screenPosition.y < -screenCentre.y)
{
screenPosition = new Vector3(-screenCentre.y / slope, -screenCentre.y, 0);
}
screenPosition += screenCentre;
float x = indicator.rect.width * canvas.localScale.x / 2;
float y = indicator.rect.height * canvas.localScale.y / 2;
screenPosition.x = Mathf.Clamp(screenPosition.x, x, Screen.width - x);
screenPosition.y = Mathf.Clamp(screenPosition.y, y, Screen.height - y);
indicator.position = Vector3.MoveTowards(indicator.position, screenPosition, 500 * Time.deltaTime);
}
bool IsTargetVisible(Vector3 screenPosition)
{
if(Player.instance != null)
{
if (Vector3.Distance(target.position, Player.instance.transform.position) >= 14)
{
return false;
}
}
bool isTargetVisible = screenPosition.z > 0 && screenPosition.x > 0 && screenPosition.x < Screen.width && screenPosition.y > 0 && screenPosition.y < Screen.height;
return isTargetVisible;
}
}
Your answer
Follow this Question
Related Questions
[SOLVED] Check if gameobject without renderer is within camera view 2 Answers
Text Objects do Lerp 0 Answers
How to make an object go the direction it is facing? 0 Answers
Limit game object to camera view 0 Answers