Input Toggle system?

Made a simple Lock on system for a top down. I have some to dos, like limiting the search to a collider only, and make the rotation smooth instead of instant.

Im just learning so this is probably basic stuff, but how would i approach making it a toggle instead of holding the key down?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering.Universal;
using UnityEngine.Experimental.Rendering.Universal;

public class LockOn : MonoBehaviour {

private CharMovementBehaviour m_xMove;
private GameObject m_xPlayer;
private GameObject Enemy;
GameObject [] enemy;
private Transform playerpos;
GameObject closest;
private GameObject CloseEnemyInstance;
Vector2 target;

    GameObject FindClosestEnemy() 
    {
        enemy = GameObject.FindGameObjectsWithTag("Enemy");
        float distance = Mathf.Infinity;
        Vector3 position = transform.position;
        foreach (GameObject go in enemy) {
            Vector3 diff = go.transform.position - position;
            float curDistance = diff.sqrMagnitude;
            if(curDistance< distance)
            {
                closest = go;
                distance = curDistance;
            }
        }
        return closest;
    }
    

    
    void Update()
  {
        if (Input.GetKey(KeyCode.Tab) ){
        CloseEnemyInstance = FindClosestEnemy();
        Vector2 target = CloseEnemyInstance.transform.position;
        m_xPlayer = GameUtil.xGetPlayer();
        playerpos = m_xPlayer.GetComponent<Transform> ();
        Vector2 ppos = playerpos.transform.position;
        m_xMove = m_xPlayer.GetComponent<CharMovementBehaviour>();

     float dist = Vector2.Distance (target, ppos);
    if (dist <= 30 ){
   m_xMove.vInstantFacePoint(target);

    }
    }
    }
    }

Use Input.GetKeyDown to flip a boolean. Then do your lock on logic if the boolean is true.

bool isLockingOn = false;

private void Update()
{
    if(Input.GetKeyDown(Keycode.Tab)
    {
        isLockingOn = !isLockingOn;
    }
    if(isLockingOn)
    {
        //Do locking logic
    }
}

A toggle implies a simple boolean to control it.

In this case, you actually need a target, whatever enemy you are locked onto.

This lets you be clever and combine the function of the target variable.

The target can both tell you “This is the target I’m locked onto” as well as inform you that you actually ARE locked on.

So let’s review:

// controls if there is a valid target or not
private GameObject CurrentTargetOrNullIfNone;

Now when you lock on, assign it to that variable!!

CurrentTargetOrNullIfNone = ... however you get what the target is

When you tap again to untarget, set it to null:

CurrentTargetOrNullIfNone = null;

To check if you ARE targeted, thanks to Unity’s boolean operator overload (google for more), you can just do:

if (CurrentTargetOrNullIfNone)
{
  // do lock-on behaviour
}
else
{
  // you are not locked on
}

This pattern is SUPER common, used all over the place. By combining the function of the variable to both indicate which target it is as well as if you even have a target, it gets you out of a whole class of related bugs, such as getting into some kind of condition where:

  • you are locked on, but there is no target
  • there is a target, but you are not locked on

Additionally, in Unity you can be confident that if you Destroy() the target, all references to it (including your variable above) will now be considered both null and false!

Hey, first of all, thanks to both, i got into the logic and adapted the script and made it work with some patience. Kurt i have to say im a little behind the knowledge to fully graps your explanation, but im working hard to study, and for that ill come back to that logic.

Woods i essentially adapted that to the script and divided some of the logic to make it make more sense. Still work to be done but im closer now.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering.Universal;
using UnityEngine.Experimental.Rendering.Universal;

public class LockOn : MonoBehaviour {

private CharMovementBehaviour m_xMove;
private GameObject m_xPlayer;
private GameObject Enemy;
GameObject [] enemy;
private Transform playerpos;
GameObject closest;
private GameObject CloseEnemyInstance;
Vector2 target;

bool isLockingOn = false;

    GameObject FindClosestEnemy() 
    {
        enemy = GameObject.FindGameObjectsWithTag("Enemy");
        float distance = Mathf.Infinity;
        Vector3 position = transform.position;
        foreach (GameObject go in enemy) {
            Vector3 diff = go.transform.position - position;
            float curDistance = diff.sqrMagnitude;
            if(curDistance< distance)
            {
                closest = go;
                distance = curDistance;
            }
        }
        return closest;
    }

void Locking(GameObject enemy){

      CloseEnemyInstance = FindClosestEnemy();
        Vector2 target = CloseEnemyInstance.transform.position;
        m_xPlayer = GameUtil.xGetPlayer();
        playerpos = m_xPlayer.GetComponent<Transform> ();
        Vector2 ppos = playerpos.transform.position;
        m_xMove = m_xPlayer.GetComponent<CharMovementBehaviour>();

     float dist = Vector2.Distance (target, ppos);
    if (dist <= 30 ){
   m_xMove.vInstantFacePoint(target);
}

}
    
   private void Update()
   {
      if (Input.GetKeyDown(KeyCode.Tab) )
    {
        isLockingOn = !isLockingOn;
    }
    if(isLockingOn)
    {
      Locking(Enemy);
    }
    }
}
    

i managed to now make it deactivate once you kill the target, it will also not change targets automatically

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering.Universal;
using UnityEngine.Experimental.Rendering.Universal;

public class LockOn : MonoBehaviour {

private CharMovementBehaviour m_xMove;
private GameObject m_xPlayer;
private GameObject Enemy;
GameObject [] enemy;
private Transform playerpos;
GameObject closest;
private GameObject CloseEnemyInstance;
Vector2 target;

bool isLockingOn = false;

    GameObject FindClosestEnemy() 
    {
        enemy = GameObject.FindGameObjectsWithTag("Enemy");
        float distance = Mathf.Infinity;
        Vector3 position = transform.position;
        foreach (GameObject go in enemy) {
            Vector3 diff = go.transform.position - position;
            float curDistance = diff.sqrMagnitude;
            if(curDistance< distance)
            {
                closest = go;
                distance = curDistance;
            }
        }
        return closest;
    }

void Locking(GameObject enemy){
     
        Vector2 target = CloseEnemyInstance.transform.position;
        m_xPlayer = GameUtil.xGetPlayer();
        playerpos = m_xPlayer.GetComponent<Transform> ();
        Vector2 ppos = playerpos.transform.position;

        m_xMove = m_xPlayer.GetComponent<CharMovementBehaviour>();

     float dist = Vector2.Distance (target, ppos);
    if (dist <= 30 ){
   m_xMove.vInstantFacePoint(target);
}
      }

    
   private void Update()
   {
      if (Input.GetKeyDown(KeyCode.Tab) ){
        CloseEnemyInstance = FindClosestEnemy();

        isLockingOn = !isLockingOn;
    }
    if(isLockingOn)
    {
   
    if (CloseEnemyInstance != null){
      Locking(Enemy);


    }
    }
}}