我正在制作一个围绕鸡蛋旋转的相机。我无法弄清楚如何做到这一点。旋转在x和y各自夹紧-90 +90。我制作了一个代码,根据枢轴的当前x旋转更改摄像机位置,但它不能给我一个准确的结果。这是代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraMotionScript : MonoBehaviour {
public Transform thePivot, theCamera;
public float rotSpeed = 5f, lerpSpeed, minX, maxX, minY, maxY, maxDist, divRatio;
private float rotX = 0f,
rotY = 0f,
dX = 0f,
dY = 0f,
rotateDirection = -1f,
cachedRotSpeed = 0f,
minDist = 0f;
private bool rotationActive = false;
void Start () {
cachedRotSpeed = rotSpeed;
minDist = Mathf.Abs (theCamera.localPosition.z);
divRatio = maxX / maxDist;
}
void Update () {
if (Input.GetMouseButton (0)) {
rotSpeed = cachedRotSpeed;
dX = Input.GetAxis ("Mouse X");
dY = Input.GetAxis ("Mouse Y");
rotationActive = true;
}
if (Input.GetMouseButtonUp (0)) {
rotationActive = false;
}
rotX += dY * rotSpeed * rotateDirection * Time.deltaTime;
rotY += dX * rotSpeed * -rotateDirection * Time.deltaTime;
rotX = Mathf.Clamp (rotX, minX, maxX);
rotY = Mathf.Clamp (rotY, minY, maxY);
if (thePivot != null)
thePivot.eulerAngles = new Vector3 (rotX, rotY, 0f);
if (!rotationActive) {
rotSpeed = Mathf.Lerp (rotSpeed, 0, Time.deltaTime * lerpSpeed);
if (rotSpeed < 1)
rotSpeed = 0;
}
MaintainDistanceAt (Mathf.Abs (rotX));
}
void MaintainDistanceAt (float f) {
if (f != 0) {
float zVal = f / divRatio;
if (zVal < minDist)
zVal = minDist;
theCamera.localPosition = new Vector3 (0f, 0f, zVal * -1f);
}
}
}
对于此代码,我的相机是枢轴的子项,我通过鼠标单击旋转轴。我接受枢轴的x旋转并计算相机的距离。我根据枢轴的运行时间x旋转来修改它。 我也在其中添加了平滑的速度代码,但暂时忽略了它。
所以问题是,我写的距离代码将相机的位置设置为线性矢量,因此它会穿过蛋网并剪切它。
我希望能够将相机移动到蛋周围的椭圆轨道上。 有关如何解决此问题的任何建议? 提前谢谢。
答案 0 :(得分:2)
获得椭圆模式的简便方法是使用cos / sin函数。
void Update ()
{
float x = xAmplitude * Mathf.Cos (Time.time + phase);
float z = zAmplitude * Mathf.Sin (Time.time + phase)
transform.localPosition = new Vector3(x, 0, z);
}
对您而言,重要的部分是您从输入中获得的xAmplitude和zAmplitude。
我建议你从这个方法开始,这样你就可以看到它的表现,然后一直玩它,直到你做到你想要的为止。
编辑: 什么是“阶段”? 相位是用于替换起点的值。在你的情况下,我知道你不想连续旋转但是根据鼠标位置找到椭圆上的位置。您可以丢弃创建连续移动的Time.time。然后你可以找出起点(0)和当前鼠标位置之间的角度(或使用鼠标的delta移动,你的选择)并将其转换为0到360或0和2Pi之间的值(我想Unity在cos / sin中使用那个。
这是一个简单的例子,让我们看看你是不是想要的。
创建新的Movement.cs脚本
公共课运动:MonoBehaviour { public Transform child = null; public float xAmplitude = 1f; public float zAmplitude = 1f; private float phase = 0; 公共滑块滑块;
void Start()
{
slider.onValueChanged.AddListener(delegate
{
this.phase = 2 * Mathf.PI * slider.value;
float x = xAmplitude * Mathf.Cos(phase);
float z = zAmplitude * Mathf.Sin(phase);
child.localPosition = new Vector3(x, 0, z);
});
}
}
将脚本添加到父级并将子项拖动到子级中,将滑块拖动到滑块中。
你已经完成了。然后你可以跑,拖动滑块,看看孩子四处走动。给xAmplitude和zAmplitude赋予不同的值,你有一个椭圆。
this.phase = 2 * Mathf.PI * slider.value;
float x = xAmplitude * Mathf.Cos(phase);
float z = zAmplitude * Mathf.Sin(phase);
看看时间如何消失,这将停止恒定运动,因为cos / sin中的值是固定的(但仍然可以根据我们的滑块改变)。 现在,相位值由滑块值(0到1)转换为2Pi范围。 相位被传递给sin / cos,并且这些值被相应的幅度相应地延长。
答案 1 :(得分:0)
我一直想做同样的事情。我使用了@Everts阶段作为起点。
代码可在此处找到:https://gist.github.com/xepherys/1a22ed93e6c6efde61f1667f45a80a72 动作的视频可以在这里找到:https://youtu.be/4z27uTwS-gU
带有注释的完整代码:
using System;
using UnityEngine;
/// <summary>
/// The MainCameraEllipticalMWE class provides motion of the camera in an ellipse (or a circle)
/// given sizeX and sizeZ where one is the major axis and the other the minor axis. Which is
/// which isn't important, and they can be equal (x == z) if the camera is to track in a circle.
///
/// The size values assume a 2D surface where x=0, z=0 is at the bottom left and built in both x+
/// and z+ directions.
/// </summary>
public class MainCameraEllipticalMWE : MonoBehaviour
{
// sizeX and sizeZ are provided here to provide a reference point. In use, my version
// of this script omits these values and gets values from a manager object fed into
// the FixCamera() method where xAmplitude and zAmplitude are set.
int sizeX = 12;
int sizeZ = 3;
Vector3 center;
float height;
float fudgeFactor = 1.0f;
float phase = 0f;
float xAmplitude = 0f;
float zAmplitude = 0f;
float x;
float z;
void Awake()
{
this.FixCamera(sizeX, sizeZ);
}
/// <summary>
/// On Update(), if the appropriate key is pressed, rotate the camera around the center
/// of the area defined. The camera will tilt as appropriate to maintain the same center
/// point of view. The greater the difference between the major and minor axes, the
/// greater the difference of speed as the camera traverses the outsides of the major axis.
/// </summary>
void Update()
{
if (Input.GetKey(KeyCode.A))
{
// Move left
phase -= 0.01f;
x = xAmplitude * Mathf.Cos(phase);
z = zAmplitude * Mathf.Sin(phase);
transform.localPosition = new Vector3(x, height, z) + center;
this.GetComponent<Camera>().transform.LookAt(center);
}
else if (Input.GetKey(KeyCode.F))
{
// Move right
phase += 0.01f;
x = xAmplitude * Mathf.Cos(phase);
z = zAmplitude * Mathf.Sin(phase);
transform.localPosition = new Vector3(x, height, z) + center;
this.GetComponent<Camera>().transform.LookAt(center);
}
}
/// <summary>
/// FixCamera() provides the initial camera position, sets the camera height, and
/// resolves the center position based on the horizontal and vertical sizes of
/// the screen area.
/// </summary>
/// <param name="horizontalSize"></param>
/// <param name="verticalSize"></param>
public void FixCamera(int horizontalSize, int verticalSize)
{
xAmplitude = horizontalSize;
zAmplitude = verticalSize;
height = Math.Max(horizontalSize, verticalSize) + fudgeFactor;
center = new Vector3((float)horizontalSize / 2, 0, (float)verticalSize / 2);
float x = xAmplitude * Mathf.Cos(phase);
float z = zAmplitude * Mathf.Sin(phase);
transform.localPosition = new Vector3(x, height, z) + center;
this.GetComponent<Camera>().transform.LookAt(center);
}
}