Unity 中的平滑相机缩放问题
Issue with smooth camera zoom in Unity
每当我使用鼠标滚轮时,我都试图让我的相机平滑地放大和缩小,但由于某种原因,它会立即且不平滑地缩放。
这就是我更新缩放的方式:
[SerializeField, Range(10, 100)] float scrollSpeed = 10f;
[SerializeField] Vector2 zoomAmount = Vector2.zero;
private float ScrollWheel
{
get { return Input.GetAxis("Mouse ScrollWheel"); }
}
private new Camera camera = null;
void Update()
{
if (camera == null) return;
UpdateZoom();
}
void UpdateZoom()
{
pos = camera.transform.position;
pos = Vector3.Lerp(pos, new Vector3(pos.x, pos.y - scrollSpeed * 10 * ScrollWheel, pos.z), Time.deltaTime * 2);
pos.y = Mathf.Clamp(pos.y, zoomAmount.x, zoomAmount.y);
camera.transform.position = pos;
}
我认为您对 Lerp
有点困惑(我开始使用它时也有同样的困惑)。当您为时间参数(第三个参数)传入 0 时,它将 return 您的 "starting" 向量。当您为时间参数传递 1 或更大的值时,它将 return 您的 "ending" 向量。 但是,如果您传递 Time.deltaTime * 2
,那么您将 return 每帧都使用大致相同的插值向量。 Lerp
不会 "track" 它已经插值了多远,因此通过每帧传递相同的时间值,Lerp
实际上永远不会 return 您的结束向量。因此,与其传递 Time.deltaTime * 2
,不如这样做
float interpolatedTime = 0;
void Update()
{
var myVector = Vector3.Lerp(vector1, vector2, this.interpolatedTime);
this.interpolatedTime += Time.deltaTime;
}
给你的相机装这样的东西怎么样:
float zoomTime;
float zoomTarget;
float lastScrollWheelDirection;
void Update()
{
// If this camera is currently zooming in and the player started zooming
// out (or vice versa), reset the amount that is remaining to be zoomed
if ((this.lastScrollWheelDirection > 0 && this.ScrollWheel < 0) ||
(this.lastScrollWheelDirection < 0 && this.ScrollWheel > 0))
{
this.zoomTarget = 0;
}
if (this.ScrollWheel != 0)
{
this.lastScrollWheelDirection = this.ScrollWheel;
}
// zoomTarget is the total distance that is remaining to be zoomed.
// Each frame that the scroll wheel is moved, we'll add a little more
// to the distance that we want to zoom
zoomTarget += this.ScrollWheel * this.scrollSpeed;
// zoomTime is used to do linear interpolation to create a smooth zoom.
// Each time the player moves the mouse wheel, we reset zoomTime so that
// we restart our linear interpolation
if (this.ScrollWheel != 0)
{
this.zoomTime = 0;
}
if (this.zoomTarget != 0)
{
this.zoomTime += Time.deltaTime;
// Calculate how much our camera will be moved this frame using linear
// interpolation. You can adjust how fast the camera zooms by
// changing the divisor for zoomTime
var translation = Vector3.Lerp(
new Vector3(0, 0, 0),
new Vector3(0, this.zoomTarget, 0),
zoomTime / 4f); // see comment above
// Zoom the camera by the amount that we calculated for this frame
this.transform.position -= translation;
// Decrease the amount that's remaining to be zoomed by the amount
// that we zoomed this frame
this.zoomTarget -= translation.y;
}
}
每当我使用鼠标滚轮时,我都试图让我的相机平滑地放大和缩小,但由于某种原因,它会立即且不平滑地缩放。
这就是我更新缩放的方式:
[SerializeField, Range(10, 100)] float scrollSpeed = 10f;
[SerializeField] Vector2 zoomAmount = Vector2.zero;
private float ScrollWheel
{
get { return Input.GetAxis("Mouse ScrollWheel"); }
}
private new Camera camera = null;
void Update()
{
if (camera == null) return;
UpdateZoom();
}
void UpdateZoom()
{
pos = camera.transform.position;
pos = Vector3.Lerp(pos, new Vector3(pos.x, pos.y - scrollSpeed * 10 * ScrollWheel, pos.z), Time.deltaTime * 2);
pos.y = Mathf.Clamp(pos.y, zoomAmount.x, zoomAmount.y);
camera.transform.position = pos;
}
我认为您对 Lerp
有点困惑(我开始使用它时也有同样的困惑)。当您为时间参数(第三个参数)传入 0 时,它将 return 您的 "starting" 向量。当您为时间参数传递 1 或更大的值时,它将 return 您的 "ending" 向量。 但是,如果您传递 Time.deltaTime * 2
,那么您将 return 每帧都使用大致相同的插值向量。 Lerp
不会 "track" 它已经插值了多远,因此通过每帧传递相同的时间值,Lerp
实际上永远不会 return 您的结束向量。因此,与其传递 Time.deltaTime * 2
,不如这样做
float interpolatedTime = 0;
void Update()
{
var myVector = Vector3.Lerp(vector1, vector2, this.interpolatedTime);
this.interpolatedTime += Time.deltaTime;
}
给你的相机装这样的东西怎么样:
float zoomTime;
float zoomTarget;
float lastScrollWheelDirection;
void Update()
{
// If this camera is currently zooming in and the player started zooming
// out (or vice versa), reset the amount that is remaining to be zoomed
if ((this.lastScrollWheelDirection > 0 && this.ScrollWheel < 0) ||
(this.lastScrollWheelDirection < 0 && this.ScrollWheel > 0))
{
this.zoomTarget = 0;
}
if (this.ScrollWheel != 0)
{
this.lastScrollWheelDirection = this.ScrollWheel;
}
// zoomTarget is the total distance that is remaining to be zoomed.
// Each frame that the scroll wheel is moved, we'll add a little more
// to the distance that we want to zoom
zoomTarget += this.ScrollWheel * this.scrollSpeed;
// zoomTime is used to do linear interpolation to create a smooth zoom.
// Each time the player moves the mouse wheel, we reset zoomTime so that
// we restart our linear interpolation
if (this.ScrollWheel != 0)
{
this.zoomTime = 0;
}
if (this.zoomTarget != 0)
{
this.zoomTime += Time.deltaTime;
// Calculate how much our camera will be moved this frame using linear
// interpolation. You can adjust how fast the camera zooms by
// changing the divisor for zoomTime
var translation = Vector3.Lerp(
new Vector3(0, 0, 0),
new Vector3(0, this.zoomTarget, 0),
zoomTime / 4f); // see comment above
// Zoom the camera by the amount that we calculated for this frame
this.transform.position -= translation;
// Decrease the amount that's remaining to be zoomed by the amount
// that we zoomed this frame
this.zoomTarget -= translation.y;
}
}