简体   繁体   English

相机行为

[英]Camera Behaviour

This camera script is intended to rotate and look at the player while it is moving and snapping to the player slowly while it isn't. 该摄像机脚本旨在旋转并观察播放器,以使其移动,并在不移动时缓慢地捕捉到播放器。 (Player passes over a Vector3 beforeMoving before it is starting movement). (播放器在开始移动之前先经过Vector3,然后再进行移动)。 My issue is I want to "feed" the deltaPosition slowly so it isn't a sudden snap but rather a slow and smooth transition, also stop adding if arrived. 我的问题是我想缓慢地“喂入” deltaPosition,所以这不是突然的,而是一个缓慢而平稳的过渡,如果到达,也要停止添加。

    private void LateUpdate()
{
    if (player.isMoving)
    {
        desiredPosition = player.beforeMoving + offset;
    }
    else
    {
        Vector3 deltaPosition = player.transform.position - player.beforeMoving; 
        desiredPosition += deltaPosition * Time.deltaTime;
    }
    Quaternion camTurnAngle =
    Quaternion.AngleAxis(input * rotationSpeed, Vector3.up);
    desiredPosition = camTurnAngle * desiredPosition;
    transform.position = Vector3.Slerp(transform.position, desiredPosition, smoothFactor);
    transform.LookAt(player.transform);
}

Edit: I thought I would share the final code. 编辑:我想我会分享最终代码。

    private void LateUpdate()
{
    Quaternion rotation = Quaternion.Euler(GetDegree(), input.x * rotationSpeed, 0f);
    if (player.isMoving)
    {
        desiredPosition = player.beforeMoving + offset;
        CalculatePanTime();
    }
    else if (!player.isMoving)
    {
        desiredPosition = player.transform.position + offset;
    }
    transform.position = Vector3.Slerp(transform.position, rotation * desiredPosition, GetSpeed());
    transform.LookAt(player.transform);
}

private void CalculatePanTime()
{
    stoppedTime = Time.time;
    playerDelta = Vector3.Distance(player.transform.position, player.beforeMoving);
    timeToPan = (playerDelta / snappingSpeed) * Time.deltaTime;
}

private float GetSpeed()
{
    if (Time.time < stoppedTime + timeToPan)
    {
        controlsDisabled = true; return snappingSpeed;
    }
    else
    {
        controlsDisabled = false; return smoothSpeed;
    }
}

You are telling us what you want the code to do, that is good. 您告诉我们您想要代码做什么,那很好。 You are also posting the code you implemented to achieve your goal, that is also good. 您还将发布为实现目标而实现的代码,这也很好。 Can you also tell us what is not working as you want it to work as a result of that code? 您还可以告诉我们,由于该代码的作用而导致什么不起作用?

From what I understand it is the "Vector3 deltaPosition = player.transform.position - player.beforeMoving; desiredPosition += deltaPosition * Time.deltaTime; " that is not behaving as you expect it to 根据我的理解,这是“ Vector3 deltaPosition = player.transform.position-player.beforeMoving; dessertPosition + = deltaPosition * Time.deltaTime;”,这与您期望的不一样

maybe try something like this: 也许尝试这样的事情:

private void LateUpdate()
{
    // snap the rotation center slowly to the player's position if not moving, or player's position before he started moving
    desiredPosition = Vector3.Lerp(desiredPosition, player.beforeMoving, 0.1f);

    // rotate around rotation center
    Quaternion camTurnAngle = Quaternion.AngleAxis(rotationSpeed * Time.time, Vector3.up);      
    desiredPosition += camTurnAngle * offset;

    // set the position to rotate around rotation center, and look towards player
    transform.position = Vector3.Lerp(transform.position, desiredPosition, smoothFactor);
    transform.LookAt(player.transform);
}

the problem with your code is that you are overshooting. 您的代码的问题是您超调了。 If you want to implement something that decides how fast the camera snaps, or how much time it should take to snap, try introducing a float player.timeStopMoving = Time.time that you can use to correctly compute the position correction while he is not moving. 如果要实现一些决定相机拍摄速度或拍摄时间的方法,请尝试引入一个浮动播放器。timeStopMoving= Time.time,可用于在他不移动时正确计算位置校正。

if(player.isMoving)
{
    desiredPosition = player.beforeMoving;
}
else
{
    const float timeNeededToSnap = 2f;
    // or float timeNeededToSnap = (player.transform.position - player.beforeMoving).magnitude; // (which you could compute only once in player script, when he stops moving, and then reuse the value instead of performing a ".magnitude" every frame)
    if(Time.time < player.timeStopMoving + timeNeededToSnap)
    {
        desiredPosition = Vector3.Lerp(desiredPosition, player.transform.position, (Time.time - player.timeStopMoving) / timeNeededToSnap);
    }
    else
    {
        // an other problem here is: if the player starts moving AGAIN before your desiredPosition got the value, do you want desired position to glich to the new player.beforeMoving?...
        desiredPosition = player.transform.position;
    }
}

EDIT: 编辑:

To make he lerp less linear, you can use: 要使他的约束线性度降低,可以使用:

if(Time.time < player.timeStopMoving + timeNeededToSnap)
{
    var t = Mathf.Cos(Maths.Pi * 0.5f * (Time.time - player.timeStopMoving) / timeNeededToSnap); // as timeDelta/totalTime goes from 0->1, multiply it by Pi/2 and the Cos will also go from 0->1 but with a smoothing speed
    desiredPosition = Vector3.Lerp(desiredPosition, player.transform.position, t);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM