如何在Unity中使摄像机从球后面跟随滚动的球?

huangapple go评论62阅读模式
英文:

How to make camera follow a rolling ball from behind it in Unity?

问题

以下是您提供的脚本的中文翻译部分:

// 开始时设置偏移量
void Start()
{
    offset = transform.position - player.transform.position;
}

// 每帧更新
void LateUpdate()
{
    CameraMovement();
}

// 摄像机移动逻辑
private void CameraMovement()
{
    float inputX = Input.GetAxis("Horizontal");
    float inputZ = Input.GetAxis("Vertical");

    if (inputX > 0)
    {
        transform.position = player.transform.position + new Vector3(-3.5f, 2f, 0f);
        transform.LookAt(player.position);
    }
    else if (inputX < 0)
    {
        transform.position = player.transform.position + new Vector3(3.5f, 2f, 0f);
        transform.LookAt(player.position);
    }

    if (inputZ > 0)
    {
        transform.position = player.transform.position + new Vector3(0f, 2f, -3.5f);
        transform.LookAt(player.position);
    }
    else if (inputZ < 0)
    {
        transform.position = player.transform.position + new Vector3(0f, 2f, 3.5f);
        transform.LookAt(player.position);
    }
    else if (inputX == 0 && inputZ == 0)
    {
        transform.position = player.transform.position + new Vector3(0f, 5f, 0f);
        transform.LookAt(player.position);
    }
}

请注意,这段代码描述了一个相机跟随玩家控制的滚动球的脚本,始终保持在球的后方,面向球移动的方向,而不会在x和z轴上旋转。

英文:

So I need help making a script where the camera follows a rolling ball (controlled by the player) always from behind it, so if it rotates right, the camera will too but still remain behind the ball facing in the direction the ball is moving and without exactly rotating around the x and z axis.

Its been a month since I've started programming and this is the best I could do however it's very janky, doesn't flow nicely and isn't exactly what I want:

void Start()
{
    offset = transform.position - player.transform.position;
}

// Update is called once per frame
void LateUpdate()
{
    CameraMovement();
    
}

private void CameraMovement()
{
    float inputX = Input.GetAxis(&quot;Horizontal&quot;);
    float inputZ = Input.GetAxis(&quot;Vertical&quot;);

    if (inputX &gt; 0)
    {
        transform.position = player.transform.position + new Vector3(-3.5f, 2f, 0f);
        transform.LookAt(player.position);
    }
    else if (inputX &lt; 0)
    {
        transform.position = player.transform.position + new Vector3(3.5f, 2f, 0f);
        transform.LookAt(player.position);
    }

    if(inputZ &gt; 0)
    {
        transform.position = player.transform.position + new Vector3(0f, 2f, -3.5f);
        transform.LookAt(player.position);
    } else if(inputZ &lt; 0)
    {
        transform.position = player.transform.position + new Vector3(0f, 2f, 3.5f);
        transform.LookAt(player.position);
    }
    else if(inputX == 0 &amp;&amp; inputZ == 0)
    {
        transform.position = player.transform.position + new Vector3(0f, 5f, 0f);
        transform.LookAt(player.position);
    }
}`   

答案1

得分: 0

以下是您要求的代码部分的中文翻译:

如前所述,我会将这部分与输入解耦,并且更好地处理球的移动,做一些类似于:

public class CameraController : MonoBehaviour
{
    public Transform player;

    private Vector3 offset;
    private Vector3 previousPosition;
    private Quaternion targetRotation;
    private Vector3 targetPosition;
    private Vector3 currentVelocity;
    private float currentRotVel;

    // 在第一帧更新之前调用
    private void Start()
    {
        previousPosition = player.position;
        offset = transform.position - previousPosition;

        targetRotation = transform.rotation;
        targetPosition = transform.position;
    }

    // 每帧调用一次
    private void LateUpdate()
    {
        var position = player.position;
        // 方向只是上一帧和这一帧位置之间的差值
        var direction = position - previousPosition;
        previousPosition = position;

        if (direction != Vector3.zero)
        {
            // 朝着移动方向看
            targetRotation = Quaternion.LookRotation(direction);
            // 在移动方向上应用偏移
            targetPosition = position + targetRotation * offset;
        }

        // [可选] 平稳地移动到位置和旋转
        transform.rotation = QuaternionUtils.SmoothDamp(transform.rotation, targetRotation, ref currentRotVel, 0.5f);
        transform.position = Vector3.SmoothDamp(transform.position, targetPosition, ref currentVelocity, 0.5f);
    }
}

// 用于Quaternion的SmoothDamp等效的小助手
public static class QuaternionUtils
{
    public static Quaternion SmoothDamp(Quaternion from, Quaternion to, ref float currentAngularVelocity, float smoothTime)
    {
        var delta = Quaternion.Angle(from, to);
        if (delta > 0f)
        {
            var t = Mathf.SmoothDampAngle(delta, 0.0f, ref currentAngularVelocity, smoothTime);
            t = 1.0f - t / delta;
            return Quaternion.Slerp(from, to, t);
        }

        return to;
    }
}

根据您的用例,您当然也可以继续直接应用输入并以基本上反映您使用和应用用户输入到玩家移动的方式获取“direction”,例如:

var direction = player.transform.right * Input.GetAxis("Horizontal") + player.transform.forward * Input.GetAxis("Vertical");

请注意,代码中的引号已根据需要进行了修正。如果有其他翻译需求,请告诉我。

英文:

As mentioned I would decouple this from the input and rather handle the balls movement and do something like e.g.

public class CameraController : MonoBehaviour
{
    public Transform player;

    private Vector3 offset;
    private Vector3 previousPosition;
    private Quaternion targetRotation;
    private Vector3 targetPosition;
    private Vector3 currentVelocity;
    private float currentRotVel;

    // Start is called before the first frame update
    private void Start()
    {
        previousPosition = player.position;
        offset = transform.position - previousPosition;

        targetRotation = transform.rotation;
        targetPosition = transform.position;
    }

    // Update is called once per frame
    private void LateUpdate()
    {
        var position = player.position;
        // direction is simply the delta between last and this frame positions
        var direction = position - previousPosition;
        previousPosition = position;

        if (direction != Vector3.zero)
        {
            // look in move direction
            targetRotation = Quaternion.LookRotation(direction);
            // apply offset in move direction
            targetPosition = position + targetRotation * offset;
        }

        // [optional] smoothly move into position and rotation
        transform.rotation = QuaternionUtils.SmoothDamp(transform.rotation, targetRotation, ref currentRotVel, 0.5f);
        transform.position = Vector3.SmoothDamp(transform.position, targetPosition, ref currentVelocity, 0.5f);
    }
}

// little helper for a SmoothDamp equivalent for Quaternion
public static class QuaternionUtils
{
    public static Quaternion SmoothDamp(Quaternion from, Quaternion to, ref float currentAngularVelocity, float smoothTime)
    {
        var delta = Quaternion.Angle(from, to);
        if (delta &gt; 0f)
        {
            var t = Mathf.SmoothDampAngle(delta, 0.0f, ref currentAngularVelocity, smoothTime);
            t = 1.0f - t / delta;
            return Quaternion.Slerp(from, to, t);
        }

        return to;
    }
}

如何在Unity中使摄像机从球后面跟随滚动的球?

depends on your use case of cause, you can of course as well keep applying the input directly and get the direction that way instead basically mirroring the way you use and apply the user input to the player movement e.g.

var direction = player.transform.right * Input.GetAxis(&quot;Horizontal&quot;) + player.transform.forward * Input.GetAxis(&quot;Vertical&quot;);

答案2

得分: -1

看,这可以比现在简单得多。你可以将输入读取逻辑移动到一个单独的组件中(例如,PlayerInput),然后一个脚本,例如,CharacterMovement,将与这个输入一起工作。在CameraMovement组件中,你可以简单地取得玩家的位置,加上一定的偏移量,然后将得到的坐标设置为摄像机的位置。摄像机的旋转设置为玩家的旋转。代码将看起来像这样:

[SerializeField] private Transform _playerTransform;
[SerializeField] private Vector3 _offset;

private void LateUpdate()
{
    transform.position = _playerTransform.position + _offset;
    transform.rotation = _playerTransform.rotation;
}
英文:

Look, this can be done much easier than it is now. You can move the input reading logic into a separate component (for example, PlayerInput), and then a script, for example, CharacterMovement, will work with this input. In the CameraMovement component, you can simply take the player's position, add a certain offset to it, and set the resulting coordinate as the camera's position. Сamera rotation set to player rotation. The code will look something like this:

[SerializeField] private Transform _playerTransform;
[SerializeField] private Vector3 _offset;
    
private void LateUpdate()
{
    transform.position = _playerTransform.position + _offset;
    transform.rotation = _playerTransform.rotation;
}

huangapple
  • 本文由 发表于 2023年5月22日 23:04:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/76307527.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定