gpt4 book ai didi

c# - Unity3D 平滑的相机移动和注视

转载 作者:太空宇宙 更新时间:2023-11-03 12:33:35 27 4
gpt4 key购买 nike

在我的 Unity3D C# 项目中遇到相机移动问题。

我有什么:

  • 现场的一些元素
  • 一个相机,可以从任何物体的位置或它自己的当前位置飞行

我需要什么:

  • 平滑旋转相机到物体的原点之一
  • 飞到物体附近的地方(有一个,所以我飞到空的坐标)

算法:旋转到物体的原点,旋转完成后,开始飞到空的位置。飞行时,观察物体的来源。

问题是它不流畅,相机在运动结束时“跳跃”。

我的C#代码(附在相机上):

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

public class testMove : MonoBehaviour {
public GameObject startObj;
public GameObject endObj;
public float speed = 1.0F;
private float startTime;
private float journeyLength;
private string endObjName;
private GameObject endObjLookAt;
void Start () {
startTime = Time.time;
if (startObj) {
} else {
startObj = this.gameObject;
}
journeyLength = Vector3.Distance(startObj.transform.position, endObj.transform.position);
endObjName = endObj.name;
endObjLookAt = GameObject.Find(endObjName + "LookAt");
}

void Update () {
if (endObj) {
float distCovered = (Time.time - startTime) * speed;
float fracJourney = distCovered / journeyLength;
tweenLook(endObjLookAt, fracJourney);
float angle = Quaternion.Angle(transform.rotation, Quaternion.LookRotation(endObjLookAt.transform.position - transform.position));
if (angle <= 0.0001) {
Debug.Log("rotation finished");
tweenPos(startObj, endObj, fracJourney);
transform.LookAt(endObjLookAt.transform.position);
}
}
}

private void tweenPos(GameObject startObj, GameObject endObj, float fracJourney) {
Vector3 newposition = Vector3.Lerp(startObj.transform.position, endObj.transform.position, fracJourney);
transform.position = newposition;
}

private void tweenLook(GameObject endObjLookAt, float fracJourney) {
Quaternion newrotation = Quaternion.LookRotation(endObjLookAt.transform.position - transform.position);
transform.rotation = Quaternion.Slerp(transform.rotation, newrotation, fracJourney);
}
}

最佳答案

由于您要实现的目标意味着一个接一个地执行操作,因此我建议使用Coroutine:

public class testMove : MonoBehaviour
{
public Transform startObj;
public Transform endObj;
private Transform endObjLookAt;

public float rotationDuration;
public AnimationCurve rotationCurve;

public float movementDuration;
public AnimationCurve movementCurve;

private IEnumerator moveAndRotateCameraIEnumerator;

void Start()
{
// If you want to do it on start just call MoveAndRotateCamera() here, else call if from anywhere you want (a script, a game button, ...)
}

void Update()
{
if(Input.GetKeyDown(KeyCode.Space))
{
MoveAndRotateCamera();
}
}

public void MoveAndRotateCamera(Transform startTransform = null, Transform endTransform = null)
{
if(startTransform)
{
startObj = startTransform;
}
else
{
startObj = this.transform;
}

if(endTransform)
{
endObj = endTransform;
}
endObjLookAt = GameObject.Find(endObj.name + "LookAt").transform;

if(moveAndRotateCameraIEnumerator != null)
{
StopCoroutine(moveAndRotateCameraIEnumerator);
}
moveAndRotateCameraIEnumerator = MoveAndRotateCameraCoroutine();
StartCoroutine(moveAndRotateCameraIEnumerator);
}

private IEnumerator MoveAndRotateCameraCoroutine()
{
//ROTATION
Vector3 startEulerAngles = transform.eulerAngles;
transform.LookAt(endObjLookAt);
Vector3 deltaEulerAngles = new Vector3(Mathf.DeltaAngle(startEulerAngles.x, transform.eulerAngles.x), Mathf.DeltaAngle(startEulerAngles.y, transform.eulerAngles.y), Mathf.DeltaAngle(startEulerAngles.z, transform.eulerAngles.z));

Debug.Log("Starting rotation...");
float timer = 0.0f;
while(timer < rotationDuration)
{
timer += Time.deltaTime;
transform.eulerAngles = startEulerAngles + deltaEulerAngles * rotationCurve.Evaluate(timer / rotationDuration);
yield return new WaitForEndOfFrame();
}
transform.eulerAngles = startEulerAngles + deltaEulerAngles;
Debug.Log("Rotation done!");
//----

//MOVEMENT
Vector3 startPosition = transform.position;

Debug.Log("Starting movement...");
timer = 0.0f;
while(timer < movementDuration)
{
timer += Time.deltaTime;
transform.position = Vector3.Lerp(startPosition, endObj.position, movementCurve.Evaluate(timer / movementDuration));
transform.LookAt(endObjLookAt);
yield return new WaitForEndOfFrame();
}
transform.position = endObj.position;
transform.LookAt(endObjLookAt);
Debug.Log("Movement done!");
//----
}
}

请注意这里的一些事情:

  • 将您的 GameObject 变量更改为Transform 变量,因为您总是使用它们来访问Transform 组件,因此您可以直接使用它
  • 为旋转和移动添加了时间概念而不是速度概念(您也可以使用速度代替:只需将 Time.deltaTime 乘以您的速度因子即可)
  • 使用 AnimationCurve 可以调整旋转/移动的方式:只需在 Inspector 中设置曲线(曲线必须从 (0, 0) 开始并在 (1, 1) 结束)

希望这对您有所帮助,

关于c# - Unity3D 平滑的相机移动和注视,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41846858/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com