如何让相机查看下一个目标,然后旋转并移动到下一个目标?

时间:2017-05-19 08:08:14

标签: c# unity3d unity5

第一个脚本只是让相机在地形上移动这个脚本我没有改变任何东西。第二个脚本是PatrolData,我用第一个脚本提供数据。最后一个脚本是LookAt,它应该在移动到下一个目标(航点)之前稍微旋转相机。

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 ((bool)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;
     }
 }

然后是数据脚本:

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 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;

     public Vector3 distanceFromTarget;

     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:
                     iterator = Modulus(iterator, length * 2);
                     index = length - Mathf.Abs(length - iterator);
                     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;

             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;
             lingerDuration -= Time.deltaTime;
         }
         else
         {
             flyOverTerrain.target = patrol.target;
         }

         distanceFromTarget = transform.position - patrol.target.position;
     }


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

以及lookat脚本

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
         _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);
     }
 }

所有脚本都附加到主摄像头。到目前为止,相机在目标之间移动时效果很好。现在我想做的是当相机在相机开始移动到下一个目标之前稍微停在每个目标附近时,使旋转面向将要移动到的目标。

问题是我不知道如何让它等待以及在LookAtCamera脚本中启动旋转的时间和时间。

现在它在运行游戏时会做什么,它会立即开始旋转到下一个目标(在检查员中我拖动以测试第二个目标)。

我的问题是如何使用LookAtCamera脚本。

1 个答案:

答案 0 :(得分:-1)

找到了怎么做。 首先在LookAtCamera脚本中将它附加到主摄像头我还检查更新功能中是否存在目标:

if(target)

所以更新功能:

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);
    }

然后在脚本PatrolData中: 脚本PatrolData可以附加到任何游戏对象,在这种情况下我也将它附加到主摄像头。

在FlyToVerTerrain的顶部,我添加了:

public LookAtCamera lookAtCamera;

然后在更新功能中:

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

然后在这一部分:

if (targetOffset.sqrMagnitude <= sqrDistance)
        {
            flyOverTerrain.target = null;
            lookAtCamera.target = null;
            lingerDuration -= Time.deltaTime;
        }
        else
        {
            flyOverTerrain.target = patrol.target;
            lookAtCamera.target = patrol.target;
        }

最后,所有3个脚本都会使摄像机移动到每个航路点(目标),摄像机将旋转并面向下一个航点,然后再移动到下一个航路点。

工作完美。