I’m trying to design a configurable script that produces a list of objects in the player’s focus, and optionally a specific object that is “most” in focus. This is being used for a FPS like game, but could be used for a number of other genres.
Things it should take into account are a configurable field of focus (might be smaller than the camera FOV), object distance from the camera, and distance from the camera’s center focus point.
Any suggestions on implementation?
Currently, I’ve written this code:
public bool requireFieldOfView = true;
public GameObject Camera;
public float verticalFieldOfView = 15;
public float horizontalFieldOfView = 30;
public ArrayList findInteractiveObjects()
{
Vector3 distance, adj, vHyp, hHyp;
float hAngle, vAngle;
ArrayList interactiveObjects = new ArrayList();
// Determine Camera View
Transform FOV;
if (Camera != null)
FOV = Camera.transform;
else FOV = transform;
// Find current colliders
Collider[] proximityObjects = Physics.OverlapSphere(FOV.position, maximumInteractiveDistance, interactiveLayers.value);
foreach (Collider col in proximityObjects)
{
distance = col.transform.position - FOV.position;
adj = Vector3.Dot(distance, FOV.forward) * FOV.forward;
vHyp = distance - (Vector3.Dot(distance, FOV.right) * FOV.right);
vAngle = Mathf.Rad2Deg * Mathf.Acos(adj.magnitude / vHyp.magnitude);
hHyp = distance - (Vector3.Dot(distance, FOV.up) * FOV.up); ;
hAngle = Mathf.Rad2Deg * Mathf.Acos(adj.magnitude / hHyp.magnitude); ;
//Ensure they are in the Field of View
if ((hAngle <= horizontalFieldOfView vAngle <= verticalFieldOfView) || !requireFieldOfView)
{
Interactive interactiveObj = col.gameObject.GetComponent<Interactive>();
if (interactiveObj != null)
interactiveObjects.Add(interactiveObj);
}
}
return interactiveObjects;
}
Some of the problems I’m having are:
- This code requires that the object’s local origin to be within the field of view, not necessarily any part of the object
- Objects behind the player but within that field of view are also detected
- Doesn’t yet determine which object is “most in focus”. Determining this will probably have be some trade off between distance from the camera and distance from the center of the Field of View
- it would be nice to have some sort of gizmo to graphically alter the FOV, or at least a display mode to show which area of the camera will detect objects
I’m wondering if it might be easier to just create a 4 sided frustrum mesh and check for collisions. Maybe use scaling to configure the desired parameters? Would that method be considerably more expensive, computationally?
Any approaches that I haven’t thought of?
Thanks!