c# - 为什么相机不旋转以面对第一个航路点?
问题描述
游戏开始时,从数组中随机选择一个航路点。然后相机应旋转以面向选定的随机航点并开始向其移动。
一旦相机到达路点,它应该等待 3 秒钟,然后再旋转面对并朝着下一个随机路点移动。
我遇到的问题在Start()
. 在开始向第一个航路点移动之前,相机不会旋转以面对第一个航路点。相反,它向后移动到第一个航路点。然后,当它到达路点时,它会等待 3 秒旋转并朝下一个路点移动。
它工作正常,只是相机不会旋转以面对第一个选择的随机航点。它在没有先旋转面对它的情况下向后移动。
这是我的代码:
航点脚本
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Waypoints : MonoBehaviour
{
public GameObject[] waypoints;
public GameObject player;
public float speed = 5;
public float WPradius = 1;
public LookAtCamera lookAtCam;
private int current = 0;
private bool rot = false;
public void Init()
{
waypoints = GameObject.FindGameObjectsWithTag("Target");
if(waypoints.Length > 0)
{
StartCoroutine(RotateFacingTarget(waypoints[UnityEngine.Random.Range(0, waypoints.Length)].transform));
}
}
void Update()
{
if (waypoints.Length > 0)
{
if (Vector3.Distance(waypoints[current].transform.position, transform.position) < WPradius)
{
current = UnityEngine.Random.Range(0, waypoints.Length);
rot = false;
StartCoroutine(RotateFacingTarget(waypoints[current].transform));
if (current >= waypoints.Length)
{
current = 0;
}
}
if (rot)
transform.position = Vector3.MoveTowards(transform.position, waypoints[current].transform.position, Time.deltaTime * speed);
}
}
IEnumerator RotateFacingTarget(Transform target)
{
yield return new WaitForSeconds(3);
lookAtCam.target = target;
rot = true;
}
}
看看相机脚本
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);
}
}
}
我怎样才能解决这个问题?
解决方案
假设Waypoints.Init()
正在调用它,并且您的waypoints
变量的数组为 3。
Waypoints.Init()
启动协程- 你的协程等待 3 秒
- 3秒后,您将相机目标设置
Slerp
为朝向该位置
Update
在它的第一帧上说waypoints.Length > 0 == true
- 它没有靠近它的目标,并且
rot
是假的,所以它不会移动
- 它没有靠近它的目标,并且
现在,您等待 3 秒,不旋转,也不移动。
- 你的协程的 3 秒等待时间到了,开始向你的目标旋转
rot
现在在您的旋转开始时为真,因此您的Update
方法也开始向目标移动
看起来您的逻辑在操作顺序的工作方式上是错误的。如果它需要像你描述的那样行动,我建议你对目标进行不同的操作。
我已经使用枚举实现了以下内容:
航点
public class Waypoints : MonoBehaviour
{
private GameObject[] waypoints;
private Transform currentWaypoint;
private enum CameraState
{
StartRotating,
Rotating,
Moving,
Waiting
}
private CameraState cameraState;
public GameObject player;
public float speed = 5;
public float WPradius = 1;
public LookAtCamera lookAtCam;
private int current = 0;
private bool isCameraRotating = false;
void Start()
{
cameraState = CameraState.StartRotating;
}
void Update()
{
switch (cameraState)
{
// This state is used as a trigger to set the camera target and start rotation
case CameraState.StartRotating:
{
// Sanity check in case the waypoint array was set to length == 0 between states
if (waypoints.Length == 0)
break;
// Tell the camera to start rotating
currentWaypoint = waypoints[UnityEngine.Random.Range(0, waypoints.Length)].transform;
lookAtCam.target = currentWaypoint;
cameraState = CameraState.Rotating;
break;
}
// This state only needs to detect when the camera has completed rotation to start movement
case CameraState.Rotating:
{
if (lookAtCam.IsFinishedRotating)
cameraState = CameraState.StartMoving;
break;
}
case CameraState.Moving:
{
// Move
transform.position = Vector3.MoveTowards(transform.position, currentWaypoint.position, Time.deltaTime * speed);
// Check for the Waiting state
if (Vector3.Distance(currentWaypoint.position, transform.position) < WPradius)
{
// Set to waiting state
cameraState = CameraState.Waiting;
// Call the coroutine to wait once and not in CameraState.Waiting
// Coroutine will set the next state
StartCoroutine(WaitForTimer(3));
}
break;
}
case CameraState.Waiting:
// Do nothing. Timer has already started
break;
}
}
IEnumerator WaitForTimer(float timer)
{
yield return new WaitForSeconds(timer);
cameraState = CameraState.StartRotating;
}
public void RefreshWaypoints()
{
waypoints = GameObject.FindGameObjectsWithTag("Target");
}
}
看相机
public class LookAtCamera : MonoBehaviour
{
// Values that will be set in the Inspector
public Transform target;
public float RotationSpeed;
private float timer = 0.0f;
public bool IsRotationFinished
{
get { return timer > 0.99f; }
}
// Update is called once per frame
void Update()
{
if (target != null && timer < 0.99f)
{
// Rotate us over time according to speed until we are in the required rotation
transform.rotation = Quaternion.Slerp(transform.rotation,
Quaternion.LookRotation((target.position - transform.position).normalized),
timer);
timer += Time.deltaTime * RotationSpeed;
}
}
}
推荐阅读
- blender - Cesium:gltf 文件的随机轮廓渲染
- python - 在python类的方法中获取self和class对象
- phpmyadmin - phpmyadmin mysql 数据库托管
- azure - Azure Blob 存储,如何实现任何文档或文件的版本
- php - 如何在找到单个记录时执行 mysql 查询,目标是返回 2 行
- javascript - setInterval 调用函数和html样式没有变化?
- ssh - 无法启动 openssh 服务器,Ubuntu 上的主机名未知
- scala - 使用 spark / scala 计算平均值和标准偏差
- reactjs - Nextjs getInitialProps 在页面重新加载时不起作用
- java - Java Spring - 显示或列出 application.yml 中的所有属性