Daniel Bogdan
Daniel Bogdan

Reputation: 51

Why the camera never rotate facing to the next target?

I have this 3 scripts attached to the Main Camera.

Fly over terrain

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FlyToOverTerrain : MonoBehaviour
{
    public Transform target;
    public float desiredHeight = 10f;

    public float flightSmoothTime = 10f;
    public float maxFlightspeed = 10f;
    public float flightAcceleration = 1f;

    public float levelingSmoothTime = 0.5f;
    public float maxLevelingSpeed = 10000f;
    public float levelingAcceleration = 2f;

    private Vector3 flightVelocity = Vector3.zero;
    private float heightVelocity = 0f;

    private void LateUpdate()
    {
        Vector3 position = transform.position;
        float currentHeight = position.y;
        if (target && flightAcceleration > float.Epsilon)
        {
            position = Vector3.SmoothDamp(position, target.position, ref flightVelocity, flightSmoothTime / flightAcceleration, maxFlightspeed, flightAcceleration * Time.deltaTime);
        }

        if (levelingAcceleration > float.Epsilon)
        {
            float targetHeight = Terrain.activeTerrain.SampleHeight(position) + desiredHeight;

            position.y = Mathf.SmoothDamp(currentHeight, targetHeight, ref heightVelocity, levelingSmoothTime / levelingAcceleration, maxLevelingSpeed, levelingAcceleration * Time.deltaTime);
        }

        transform.position = position;
        transform.rotation = Quaternion.Euler(0, 0, 0);
    }
}

Patrol over terrain

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]
public class PatrolData
{
    public Transform target = null;
    public float minDistance = 5f;
    public float lingerDuration = 5f;
    public float desiredHeight = 10f;
    public float flightSmoothTime = 10f;
    public float maxFlightspeed = 10f;
    public float flightAcceleration = 1f;
    public float levelingSmoothTime = 0.5f;
    public float maxLevelingSpeed = 10000f;
    public float levelingAcceleration = 2f;
}

public class PatrolOverTerrain : MonoBehaviour
{
    public FlyToOverTerrain flyOverTerrain;
    public LookAtCamera lookAtCamera;
    public enum PatrolMode { Clamp, Wrap, PingPong };
    public PatrolData[] patrolPoints;
    public PatrolMode mode = PatrolMode.Wrap;

    private int iterator = 0;
    private int index = 0;
    private float lingerDuration = 0f;
    private int overallLength = 0;

    public bool autoFreedomPatrol = false;
    public List<GameObject> Targets = new List<GameObject>();
    public string tagName;
    public Vector3 distanceFromTarget;

    public void Start()
    {
        if (tagName != "")
        {
            GameObject[] tempObj = GameObject.FindGameObjectsWithTag(tagName);

            for (int i = 0; i < tempObj.Length; i++)
            {
                //Add to list only if it does not exist
                if (!Targets.Contains(tempObj[i]))
                {
                    Targets.Add(tempObj[i]);
                }
            }

            //Get the current Size
            if (tempObj != null)
            {
                overallLength = Targets.Count;
            }

            GeneratePatrolPoints();
        }
    }

    private void OnEnable()
    {
        if (patrolPoints.Length > 0)
        {
            lingerDuration = patrolPoints[index].lingerDuration;
        }
    }

    private void Update()
    {
        int length = patrolPoints.Length;
        if (!flyOverTerrain) return;
        if (patrolPoints.Length < 1) return;
        if (index < 0) return;

        var patrol = patrolPoints[index];
        if (lingerDuration <= 0)
        {
            iterator++;
            switch (mode)
            {
                case PatrolMode.Clamp:
                    index = (iterator >= length) ? -1 : iterator;
                    break;
                case PatrolMode.Wrap:
                    iterator = Modulus(iterator, length);
                    index = iterator;
                    break;
                case PatrolMode.PingPong:
                    index = PingPong(iterator, length);
                    break;
            }
            if (index < 0) return;

            patrol = patrolPoints[index];

            flyOverTerrain.target = patrol.target;
            flyOverTerrain.desiredHeight = patrol.desiredHeight;
            flyOverTerrain.flightSmoothTime = patrol.flightSmoothTime;
            flyOverTerrain.maxFlightspeed = patrol.maxFlightspeed;
            flyOverTerrain.flightAcceleration = patrol.flightAcceleration;
            flyOverTerrain.levelingSmoothTime = patrol.levelingSmoothTime;
            flyOverTerrain.maxLevelingSpeed = patrol.maxLevelingSpeed;
            flyOverTerrain.levelingAcceleration = patrol.levelingAcceleration;

            lookAtCamera.target = patrol.target;
            lookAtCamera.RotationSpeed = 3;

            lingerDuration = patrolPoints[index].lingerDuration;
        }

        Vector3 targetOffset = Vector3.zero;
        if ((bool)patrol.target)
        {
            targetOffset = transform.position - patrol.target.position;
        }

        float sqrDistance = patrol.minDistance * patrol.minDistance;
        if (targetOffset.sqrMagnitude <= sqrDistance)
        {
            flyOverTerrain.target = null;
            lookAtCamera.target = null;
            lingerDuration -= Time.deltaTime;
        }
        else
        {
            flyOverTerrain.target = patrol.target;
            lookAtCamera.target = patrol.target;
        }
        distanceFromTarget = transform.position - patrol.target.position;
    }

    private int PingPong(int baseNumber, int limit)
    {
        if (limit < 2) return 0;
        return limit - Mathf.Abs(limit - Modulus(baseNumber, limit + (limit - 2)) - 1) - 1;
    }

    private int Modulus(int baseNumber, int modulus)
    {
        return (modulus == 0) ? baseNumber : baseNumber - modulus * (int)Mathf.Floor(baseNumber / (float)modulus);
    }

    public void GeneratePatrolPoints()
    {
        patrolPoints = new PatrolData[Targets.Count];
        for (int i = 0; i < patrolPoints.Length; i++)
        {
            patrolPoints[i] = new PatrolData();
            patrolPoints[i].target = Targets[i].transform;
            patrolPoints[i].minDistance = 30f;
            patrolPoints[i].lingerDuration = 3f;
            patrolPoints[i].desiredHeight = 20f;
            patrolPoints[i].flightSmoothTime = 10f;
            patrolPoints[i].maxFlightspeed = 10f;
            patrolPoints[i].flightAcceleration = 3f;
            patrolPoints[i].levelingSmoothTime = 0.5f;
            patrolPoints[i].maxLevelingSpeed = 10000f;
            patrolPoints[i].levelingAcceleration = 2f;
        }
    }
}

And Look at camera

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LookAtCamera : MonoBehaviour {

    //values that will be set in the Inspector
    public Transform target;
    public float RotationSpeed;

    //values for internal use
    private Quaternion _lookRotation;
    private Vector3 _direction;

    // Update is called once per frame
    void Update()
    {
        //find the vector pointing from our position to the target
        if (target)
            _direction = (target.position - transform.position).normalized;

        //create the rotation we need to be in to look at the target
        _lookRotation = Quaternion.LookRotation(_direction);

        //rotate us over time according to speed until we are in the required rotation
        transform.rotation = Quaternion.Slerp(transform.rotation, _lookRotation, Time.deltaTime * RotationSpeed);
    }
}

The second script the Patrol over terrain is using the Look at camera: There is a public variable:

public LookAtCamera lookAtCamera;

Then in other 4 places:

lookAtCamera.target = patrol.target;
lookAtCamera.RotationSpeed = 3;
lookAtCamera.target = null;
lookAtCamera.target = patrol.target;

The idea is when running the game first before the camera is start moving if it's needed to rotate the camera facing to the first target then start moving to the first target.

Wait in the target X seconds then rotate facing to the next target and then start moving to the target it's facing.

The camera is moving between the targets and i'm not getting any errors or exceptions but the camera never rotate. The camera move to the side backwards forwards instead rotating first and then moving forward to the facing target.

I can't figure out why it's not rotating.

Upvotes: 2

Views: 63

Answers (1)

Woltus
Woltus

Reputation: 448

You'r overriding camera rotation every frame in FlyOverTerrain script:

private void LateUpdate()
    {
    [...]
    transform.rotation = Quaternion.Euler(0, 0, 0);
}

Upvotes: 3

Related Questions