- Home /
IF gameObject is in cameras FOV (rotationally)
// Initialize variables
private Transform trans;
private Vector3 screenPoint, cameraRelative;
private bool onScreen;
private Camera mainCam;
private void Awake()
{
// Assign Transform reference
trans = gameObject.transform;
// Assign Camera reference
mainCam = Camera.main;
}
// Use this for initialization
void Start()
{
// Store initial positions relative to the Camera
cameraRelative = mainCam.transform.InverseTransformPoint(trans.position);
}
// Update is called once per frame
void Update()
{
if (trans != null)
{
// Convert the position of the object into viewport space.
screenPoint = mainCam.WorldToViewportPoint(trans.position);
// If the viewport space is within 0-1 you are in the cameras frustum
onScreen = screenPoint.z > 0 && screenPoint.x > 0 &&
screenPoint.x < 1 && screenPoint.y > 0 && screenPoint.y < 1;
}
if (!onScreen)
{
trans.position = cameraRelative + mainCam.transform.position;
}
}
Walking through this clip, one will see a plane facing toward the camera. When the camera moves positionally so that the plane is not in its viewing frustrum, the plane moves to its original position relative to the camera (acquired at the start using InverseTransformPoint). If one continues watching, when the camera is rotated so that the plane is not in its viewing frustrum, the plane shows little signs of movement, if any. What gives? Code for plane movement provided below. (Camera movement code is irrelevant. Simply using key inputs to adjust position and/or rotation).
You'd need to rotate the relative position—for example, if the relative position of the object to the camera was at (0, 0, 1), then when the camera rotates down 90 degrees you'd want the object to be at (0, -1, 0) relative to the camera.
Answer by Taylor-Libonati · Dec 05, 2017 at 10:45 PM
Well first thing is to narrow the problem. You are doing two things here: Checking if an object is off-screen and then Moving an object. So try logging Debug.Log("OFF SCREEN") on line 36 and see if that is fireing when you rotate the camera. I am guessing it will since the plane seems to move the first time you do that in the gif. So then its a matter of solving your position offset. The reason your position offset doesn't work is because you are storing the original position of the object local to the camera but then you are applying that position back to the object in world space.
trans.position = cameraRelative + mainCam.transform.position;
Should be something like:
trans.position = mainCam.transform.TransformPoint(cameraRelative);
Wow. I consider myself somewhat experienced in Unity but anytime I come across transform related calculations I am always at a loss. Sublime work @Taylor-Libonati, this is exactly right. How did you know TransformPoint was the correct method for this functionality? Edit: I see. The answer is in the wording of exactly what you said. Storing the original position of the object local to the camera but, it was then being applied in world space. TransformPoint converts a Vector3 from local to world so the offset can be applied correctly. It should be noted to ensure the object is always facing the user the following line needs to be included after TransformPoint: trans.rotation = mainCam.transform.rotation;
Feel silly for not reversing what is done in Start (InverseTransformPoint applied to mainCam) but then again transform calculation is not my forte
Glad I could help! Understanding some Vector / Transform math can help. But the way I think about it is that every Transform in Unity is relative to something. By defualt everything is relative to the root or "World" transform. You stored a position value of object A relative to object B. So if you want to reset A to be where it was you have to move its position relative to B. But transform.position is the world position. So you somehow have to convert your B relative position to world position which is what TransformPoint does. Another solution would be to make A a child of B and then apply your B relative position to its transform.localPosition and then unparent. But that is slower and more steps. Also just another contextual clue for the future is to know that if you convert something with InvertTransformPoint to get it back to where it was you use TransformPoint. Hopefully that helps. It is hard to talk through it text form lol
Also I draw everything out on a whiteboard if I need to work with space transformations. Especially if they involve Quaternions.
Amazing. I never got to this level of understanding with Vector|Transform|Quaternion math. Nor have I ever used Inverse/TransformPoint before today (that I can remember). Seems I stumble upon these (edit:: these being transform methods I've never heard of before) by the grace of another's knowledge when the implementation desired requires behavior I have yet implemented before. So, thank you very much. I deeply appreciate the wisdom you have instilled in me. Hopefully I can impart this to another in the future.