- Home /
Camera keeps resenting after I'm no longer Locking ON target, and I don't know how to fix it.
The Camera follows the player really well while not engaging the Lock ON functionality. After lock on I made the camera always follow behind the player while the player will face the target. The problem is that after hitting the Lock on button again to go back to free camera, the camera position and rotation resets back to before you engage in Lock on. Below is the three scripts that make the follow camera work.
FreeCameraLook.cs
using UnityEngine; using UnityEditor;
public class FreeCameraLook : Pivot {
[SerializeField] private float moveSpeed = 5f;
[SerializeField] private float turnSpeed = 1.5f;
[SerializeField] private float turnsmoothing = .1f;
[SerializeField] private float tiltMax = 75f;
[SerializeField] private float tiltMin = 45f;
[SerializeField] private bool lockCursor = false;
private float lookAngle;
private float tiltAngle;
private const float LookDistance = 100f;
private float smoothX = 0;
private float smoothY = 0;
private float smoothXvelocity = 0;
private float smoothYvelocity = 0;
public GameObject player;
private PlayerController pc;
protected override void Awake()
{
base.Awake();
Cursor.lockState = CursorLockMode.Confined;
cam = GetComponentInChildren<Camera>().transform;
pivot = cam.parent;
player = target.gameObject;
pc = player.GetComponent<PlayerController>();
}
// Update is called once per frame
protected override void LateUpdate()
{
base.LateUpdate();
HandleRotationMovement();
if (lockCursor && Input.GetMouseButtonUp(0))
{
Cursor.lockState = CursorLockMode.Confined;
}
}
void OnDisable()
{
Cursor.lockState = CursorLockMode.None;
}
protected override void Follow(float deltaTime)
{
transform.position = Vector3.Lerp(transform.position, target.position, deltaTime * moveSpeed);
}
void HandleRotationMovement()
{
if (!pc.lockON_target )
{
float x = Input.GetAxis("Analog_X");
float y = Input.GetAxis("Analog_Y");
if (turnsmoothing > 0)
{
smoothX = Mathf.SmoothDamp(smoothX, x, ref smoothXvelocity, turnsmoothing);
smoothY = Mathf.SmoothDamp(smoothY, y, ref smoothYvelocity, turnsmoothing);
}
else
{
smoothX = x;
smoothY = y;
}
lookAngle += smoothX * turnSpeed;
transform.rotation = Quaternion.Euler(0f, lookAngle, 0);
tiltAngle -= smoothY * turnSpeed;
tiltAngle = Mathf.Clamp(tiltAngle, -tiltMin, tiltMax);
pivot.localRotation = Quaternion.Euler(tiltAngle, 0, 0);
}
else
{
transform.rotation = Quaternion.Lerp(transform.rotation, player.transform.rotation, Time.deltaTime * turnSpeed);
}
}
}
Pivot.cs
using UnityEngine; using System.Collections; [ExecuteInEditMode] public class Pivot : FollowTarget {
protected Transform cam;
protected Transform pivot;
protected Vector3 lastTargetPosition;
protected virtual void Awake()
{
cam = GetComponentInChildren<Camera>().transform;
pivot = cam.parent;
}
// Use this for initialization
protected override void Start () {
base.Start();
}
// Update is called once per frame
virtual protected void LateUpdate () {
if (!Application.isPlaying)
{
if(target != null)
{
Follow(999);
lastTargetPosition = target.position;
}
if(Mathf.Abs(cam.localPosition.x) > .5f || Mathf.Abs(cam.localPosition.y) > .5f)
{
cam.localPosition = Vector3.Scale(cam.localPosition, Vector3.forward);
}
cam.localPosition = Vector3.Scale(cam.localPosition, Vector3.forward);
}
}
protected override void Follow(float deltaTime)
{
}
}
FollowTarget.cs
using UnityEngine;
public abstract class FollowTarget : MonoBehaviour {
[SerializeField] public Transform target;
[SerializeField] private bool autoTargetPlayer = true;
virtual protected void Start()
{
if (autoTargetPlayer)
{
FindTargetPlayer();
}
}
void FixedUpdate ()
{
if (autoTargetPlayer && (target == null || !target.gameObject.activeSelf))
{
FindTargetPlayer();
}
if (target != null && (target.GetComponent<Rigidbody>() != null && !target.GetComponent<Rigidbody>().isKinematic))
{
Follow(Time.deltaTime);
}
}
protected abstract void Follow(float deltaTime);
public void FindTargetPlayer()
{
if (target == null)
{
GameObject targetObj = GameObject.FindGameObjectWithTag("Player");
if(targetObj)
{
SetTarget(targetObj.transform);
}
}
}
public virtual void SetTarget(Transform newTransform)
{
target = newTransform;
}
public Transform Target{get {return this.target;}}
}
I was thinking to writing the entire functionality again from scratch, but I then decided to see maybe someone here may be able to pinpoint the problem I have.
The LockON function is from another script bellow:
PlayerController.cs
using System.Collections; using System.Collections.Generic; using UnityEngine;
public class PlayerController : MonoBehaviour {
public Rigidbody rb;
public Animator anim;
public CapsuleCollider cc;
public Transform cam;
[HideInInspector]
public Transform cam_holder;
public bool grounded;
public bool lockON_target;
public int curr_target;
public bool change_target;
public bool can_move;
public List<GameObject> Enemies = new List<GameObject>();
public Transform cam_target;
public float cam_target_speed;
public float normal_speed = 0.5f;
public float lockON_speed = 0.2f;
public float turn_speed = 5;
float speed;
private Vector3 direction_position;
private Vector3 look_position;
private Vector3 store_direction;
private float horizontal;
private float vertical;
private bool roll_input;
private float target_turn_amount;
private float curr_turn_amount;
private Vector3 target_position;
private GameObject[] e_close;
// Use this for initialization
void Start()
{
rb = GetComponent<Rigidbody>();
anim = GetComponent<Animator>();
cc = GetComponent<CapsuleCollider>();
cam = Camera.main.transform;
cam_holder = cam.parent.parent;
GetComponent<PlayerAnimations>();
SetupAnimator();
}
// Update is called once per frame
void FixedUpdate()
{
HandleInput();
HandleCameraTarget();
if (can_move)
{
if (!lockON_target)
{
speed = normal_speed;
HandleMovementNormal();
}
else
{
speed = lockON_speed;
if (Enemies.Count > 0)
{
HandleMovementLockON();
HandleRotationLockON();
}
else
{
lockON_target = false;
}
}
}
}
void HandleInput()
{
horizontal = Input.GetAxis("Horizontal");
vertical = Input.GetAxis("Vertical");
roll_input = Input.GetButton("B_Button");
store_direction = cam_holder.right;
ChangeTargetLogic();
}
void ChangeTargetLogic()
{
Enemies.Add(FindClosestEnemies());
if (Input.GetButtonDown("R_Analog_Button"))
{
lockON_target = !lockON_target;
}
if (Input.GetKeyDown(KeyCode.Q))
{
if (curr_target < Enemies.Count - 1)
{
curr_target++;
}
else
{
curr_target = 0;
}
}
}
GameObject FindClosestEnemies()
{
e_close = GameObject.FindGameObjectsWithTag("Enemy");
GameObject closest = null;
float e_distance = Mathf.Infinity;
Vector3 e_position = transform.position;
foreach (GameObject en in e_close)
{
Vector3 diff = en.transform.position - e_position;
float curr_distance = diff.sqrMagnitude;
if (curr_distance < e_distance)
{
closest = en;
e_distance = curr_distance;
}
}
return closest;
}
void HandleCameraTarget()
{
if (!lockON_target)
{
target_position = transform.position;
}
else
{
if (Enemies.Count > 0)
{
Vector3 dir = Enemies[curr_target].transform.position - transform.position;
dir.y = 0;
float distance = Vector3.Distance(transform.position, Enemies[curr_target].transform.position);
target_position = dir.normalized * distance / 4;
target_position += transform.position;
if (distance > 10)
{
lockON_target = false;
}
}
}
}
void HandleMovementLockON()
{
Vector3 cam_forward = Vector3.Scale(cam_holder.forward, new Vector3(1, 0, 1)).normalized;
Vector3 cam_right = Vector3.Scale(cam_holder.right, new Vector3(1, 0, 1).normalized);
Vector3 move = vertical * cam_forward + horizontal * cam_right;
Vector3 move_forward = cam_forward * vertical;
Vector3 move_sideways = cam_right * horizontal;
rb.AddForce((move_forward + move_sideways).normalized * speed / Time.deltaTime);
MoveInputToAnim(move);
}
void MoveInputToAnim(Vector3 move_input)
{
Vector3 local_move = transform.InverseTransformDirection(move_input);
float turn_amount = local_move.x;
float forward_amount = local_move.z;
if (turn_amount != 0)
turn_amount *= 2;
anim.SetBool("LockON", true);
anim.SetFloat("Forward", forward_amount, 0.1f, Time.deltaTime);
anim.SetFloat("Sideways", turn_amount, 0.1f, Time.deltaTime);
}
void HandleRotationLockON()
{
Vector3 look_position = Enemies[curr_target].transform.position;
Vector3 look_direction = look_position - transform.position;
look_direction.y = 0;
Quaternion rotation = Quaternion.LookRotation(look_direction);
rb.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * turn_speed);
}
void HandleMovementNormal()
{
can_move = anim.GetBool("can_move");
Vector3 direction_forward = store_direction * horizontal;
Vector3 direction_sides = cam_holder.forward * vertical;
if (can_move)
{
rb.AddForce((direction_forward + direction_sides).normalized * speed / Time.deltaTime);
}
direction_position = transform.position + (store_direction * horizontal) + (cam.forward * vertical);
Vector3 direction = direction_position - transform.position;
direction.y = 0;
float angle = Vector3.Angle(transform.forward, direction);
float anim_value = Mathf.Abs(horizontal) + Mathf.Abs(vertical);
anim_value = Mathf.Clamp01(anim_value);
anim.SetFloat("Forward", anim_value);
anim.SetBool("LockON", false);
if (horizontal != 0 || vertical != 0)
{
if (angle != 0 && can_move)
{
rb.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(direction), turn_speed * Time.deltaTime);
}
}
}
void SetupAnimator()
{
foreach (var child_anim in GetComponentsInChildren<Animator>())
{
if (child_anim != anim)
{
anim.avatar = child_anim.avatar;
Destroy(child_anim);
break;
}
}
}
}
Hope you can help...
Your answer
![](https://koobas.hobune.stream/wayback/20220612120820im_/https://answers.unity.com/themes/thub/images/avi.jpg)