我如何在Unity 3d中跳跃固定距离

本文关键字:跳跃 距离 3d Unity | 更新日期: 2023-09-27 18:18:09

我有一个控制器,它移动我的对象对角线。左箭头应该使玩家向前和向左移动45度,右箭头也应该向右移动45度。我想让玩家相对于当前位置移动。现在它相对于点(0,0,0)移动。

我代码:

public class JollyJumper : MonoBehaviour {
protected CharacterController control;
    public float fTime = 1.5f;      // Hop time
    public float fRange = 5.0f;     // Max dist from origin
    public float fHopHeight = 2.0f; // Height of hop
    private Vector3 v3Dest;
    private Vector3 v3Last;
    private float fTimer = 0.0f;
    private bool moving = false;
    private int number= 0;
    private Vector2 direction;
    public virtual void Start () {
        control = GetComponent<CharacterController>();
        if(!control){
            Debug.LogError("No Character Controller");
            enabled=false;
        }
    }

    void Update () {
       if (fTimer >= fTime&& moving) {
        var playerObject = GameObject.Find("Player");
        v3Last = playerObject.transform.position;
        Debug.Log(v3Last);
        v3Dest = direction *fRange;
        //v3Dest = newVector* fRange + v3Last;
         v3Dest.z = v3Dest.y;
         v3Dest.y = 0.0f;
         fTimer = 0.0f;
        moving = false;
       }
        if(Input.GetKeyDown(KeyCode.LeftArrow)){
            moving = true;
            direction = new Vector2(1.0f, 1.0f);
            number++;
        }
        if(Input.GetKeyDown(KeyCode.RightArrow)){
            moving = true;
            direction = new Vector2(-1.0f, 1.0f);
            number++;
        }
        if(moving){
       Vector3 v3T = Vector3.Lerp (v3Last, v3Dest, fTimer / fTime);
       v3T.y = Mathf.Sin (fTimer/fTime * Mathf.PI) * fHopHeight;
       control.transform.position = v3T;
       fTimer += Time.deltaTime;
        }
    }
}

如何解决这个问题?什么好主意吗?非常感谢!

我如何在Unity 3d中跳跃固定距离

简短的回答是:你硬编码了两个你想要跳跃的位置:点(1,1)和(- 1,1)。你应该在每次开始跳跃时创建新的Vector。替换每个

direction = new Vector2(1.0f, 1.0f);
v3Dest = transform.position + new Vector3(1.0f, 0, 1) * fRange;

,它应该工作。

当我在上面的时候,还有一些事情我想指出:

  • 每次跳转后都有很多浮点误差。注意,在您的代码中,v3T 永远不会等于v3Dest(实际上您从未到达目的地),因为您较早地切换了moving标志。当跳跃结束时,您应该显式地将您的位置设置为v3Dest
  • 你正在检查每帧跳跃计时器等。一个更优雅的解决方案是启动协程。
  • 你使用正弦波作为跳跃曲线,这看起来不错,但使用抛物线在概念上更正确。
  • 现在可以在半空中开始下一个跳跃(我不确定这是否是有意的)
下面是一些可以避免这些问题的代码:
using System.Collections;
using UnityEngine;
public class Jumper : MonoBehaviour
{
#region Set in editor;
public float jumpDuration = 0.5f;
public float jumpDistance = 3;
#endregion Set in editor;
private bool jumping = false;
private float jumpStartVelocityY;
private void Start()
{
    // For a given distance and jump duration
    // there is only one possible movement curve.
    // We are executing Y axis movement separately,
    // so we need to know a starting velocity.
    jumpStartVelocityY = -jumpDuration * Physics.gravity.y / 2;
}
private void Update()
{
    if (jumping)
    {
        return;
    }
    else if (Input.GetKeyDown(KeyCode.LeftArrow))
    {
        // Warning: this will actually move jumpDistance forward
        // and jumpDistance to the side.
        // If you want to move jumpDistance diagonally, use:
        // Vector3 forwardAndLeft = (transform.forward - transform.right).normalized * jumpDistance;
        Vector3 forwardAndLeft = (transform.forward - transform.right) * jumpDistance;
        StartCoroutine(Jump(forwardAndLeft));
    }
    else if (Input.GetKeyDown(KeyCode.RightArrow))
    {
        Vector3 forwardAndRight = (transform.forward + transform.right) * jumpDistance;
        StartCoroutine(Jump(forwardAndRight));
    }
}
private IEnumerator Jump(Vector3 direction)
{
    jumping = true;
    Vector3 startPoint = transform.position;
    Vector3 targetPoint = startPoint + direction;
    float time = 0;
    float jumpProgress = 0;
    float velocityY = jumpStartVelocityY;
    float height = startPoint.y;
    while (jumping)
    {
        jumpProgress = time / jumpDuration;
        if (jumpProgress > 1)
        {
            jumping = false;
            jumpProgress = 1;
        }
        Vector3 currentPos = Vector3.Lerp(startPoint, targetPoint, jumpProgress);
        currentPos.y = height;
        transform.position = currentPos;
        //Wait until next frame.
        yield return null;
        height += velocityY * Time.deltaTime;
        velocityY += Time.deltaTime * Physics.gravity.y;
        time += Time.deltaTime;
    }
    transform.position = targetPoint;
    yield break;
}

}