- Home /
FOV sensitive Lock-on?
Hey guys,
I was just wondering how I could make a lock on system FOV sensitive? Meaning that if I want to lock onto something it has to be within the FOV of the camera.
So if anything is outside of the FOV it will not target it.
I'm trying to refine the lock-on system I have in order to make it more efficient. I was also wondering how I can set a maximum lock on distance so that the enemy must be within a certain distance to be targetable and they must be actually in the FOV of the camera.
Here's my targetting code so far, for our lock on system.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Targetting : MonoBehaviour
{
GameObject[] enemies;
public Transform selectedTarget;
public Transform nearestEnemy;
public Vector3 enemyCenter;
public float minimumTargetDistance = 100.0f;
private float lastFrameLockOn;
GameObject[] lockOnTransforms;
//Transform of the UI element
public Transform lockOn;
// Use this for initialization
void Start ()
{
lastFrameLockOn = Input.GetAxis("LockOn");
selectedTarget = null;
}
// Update is called once per frame
void Update ()
{
if(Input.GetAxis("LockOn") > 0.5f )
{
if(Input.GetAxis("LockOn") > 0.5f && lastFrameLockOn < 0.5f)
{
targetCloseEnemies();
}
if(selectedTarget)
{
transform.LookAt(selectedTarget.position);
}
if(nearestEnemy)
{
if(selectedTarget != nearestEnemy)
{
TargetEnemy(nearestEnemy);
}
}
}
if(Input.GetAxis("LockOn") <= 0.5f)
{
selectedTarget = null;
nearestEnemy = null;
enemyCenter = Vector3.zero;
DestroyLockOns();
}
lastFrameLockOn = Input.GetAxis("LockOn");
}
private void targetCloseEnemies()
{
// Find all enemies within the scene and add them to a list
enemies = GameObject.FindGameObjectsWithTag("Enemy");
//Add enemies that are within range to a new list of targetable enemies
foreach(GameObject enemy in enemies) // list of all enemies
{
float enemyDistance = Vector3.Distance(transform.position, enemy.transform.position); // distance of new enemy to player
if(enemyDistance <= minimumTargetDistance) // checks if the new enemy is close enough to target
{
if(nearestEnemy)
{
if(enemyDistance < Vector3.Distance(transform.position, nearestEnemy.position )) // checks if new enemy is closer than existing enemy
{
nearestEnemy = enemy.transform;
}
}
else
{
nearestEnemy = enemy.transform; // if the nearest enemy doesn't exist, the new enemy is assigned to nearestenemy
}
}
}
if(nearestEnemy)
{
Bounds bounds = new Bounds (nearestEnemy.transform.position, Vector3.one);
Renderer[] renderers = nearestEnemy.GetComponentsInChildren<MeshRenderer>();
foreach (Renderer renderer in renderers)
{
bounds.Encapsulate (renderer.bounds);
}
renderers = nearestEnemy.GetComponentsInChildren<SkinnedMeshRenderer>();
foreach (Renderer renderer in renderers)
{
bounds.Encapsulate (renderer.bounds);
}
Debug.Log ("bounds center: "+bounds.center);
enemyCenter = bounds.center;
}
}
public void TargetEnemy(Transform target)
{
selectedTarget = target;
DestroyLockOns();
if (selectedTarget)
{
Transform lockOnClone = Instantiate(lockOn, Vector3.zero, Quaternion.identity) as Transform;
lockOnClone.parent = selectedTarget.transform;
lockOnClone.position = enemyCenter;
}
}
void DestroyLockOns()
{
lockOnTransforms = GameObject.FindGameObjectsWithTag("LockOn");
//Debug.Log ("found " + lockOnTransforms.Length + " lockons");
foreach(GameObject lockOnTransform in lockOnTransforms)
{
Debug.Log ("Destroying lockon");
Destroy(lockOnTransform);
}
}
}
Also, wondering if I can use the OnBecameVisible() function to possibly do this.
I don't have enough coding experience to figure this out on my own. :S
would it be possible to use raycast to accomplish both of these? for example, once a potential lockon target is acquired, a raycast is sent from the shooter in the direction of the target with the maximum distance requirement, and if the raycast doesnt hit anything between the shooter and the target (so a clear LoS), the lockon continues as normal.
I could try that, the only problem with that is I don't want the player to be able to lock onto a target if they are outside of the camera's FOV.
The Raycast would work for setting a maximum lock on distance though. I'll try giving that a shot right now.
Do you have any way that I might be able to make it FOV sensitive?
I see. I'm no pro myself, but it seems like OnBecameVisible would be your best bet.
In the OnBecameVisible function for the targets, you could put your raycast script to see if it were in range, and if it was you could call your lockon function. But things usually seem simpler in my head than they are in code...
Or in the targets OnBecameVisible script, it calls a function in your shooting objects script that has both the raycast distance check and lockon code
Answer by refardeon · Oct 10, 2012 at 07:35 PM
Hey there,
there is a neat way to do this using Camera.WorldToViewportPoint - http://docs.unity3d.com/Documentation/ScriptReference/Camera.WorldToViewportPoint.html
That returns a value between (0,0) and (1,1) when an object is somewhere on screen. If the object is outside, the values will be outside this range, see the example code in the reference.
This measures from the center of an object, not the bounds; so it might be necessary to include some tolerance in the check (maybe something like (0.05, 0.05) to (0.95, 0.95), that way the object has to be further on screen. It's also possible to use something like (-0.05, -0.05) to (1.05, 1.05), that way you'd also include objects that are somewhat off screen. Try and see what feels fun :)
The method is not too expensive, but as you'd have to call it every frame for every possible target: Try and restrict the amount of objects you check with this, maybe only include enemies that'd be in range. In any case, cache the reference to the camera you're using for this. In my game, that brought a significant boost in performance.
Happy coding!
Your answer
Follow this Question
Related Questions
Camera movement in a 2D? (like angry birds) 1 Answer
Unique names for Instantiated prefabs? 1 Answer
Knockback using Navmesh 1 Answer
Orthographic camera "cutting off" part of the frame 2 Answers
Minimap camera display size. 1 Answer