简体   繁体   中英

How do I jump a fix distance in Unity 3d?

I have a Controller which moves my object diagonally. The left arrow should move the player forward and to the left 45 degrees, and the right arrow the same to the right. I would like to move the player relatively to its current position. Right now it moves relatively to the point(0,0,0).

My code:

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;
        }
    }
}

How can resolve this? Any ideas? Thanks a lot!

The short answer is: you hard-coded two locations you want to jump to: points (1, 1) and (-1, 1). You should create new Vector each time you start jumping. Replace each

direction = new Vector2(1.0f, 1.0f);

with this line:

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

and it should work.

While I'm on it, there are some other things I want to point:

  • There is a lot of floating point error after each jump. Notice that in your code v3T will never be equal to v3Dest (you never actually reach your destination), because you switch the moving flag earlier. You should explicitly set your position to v3Dest when the jump is over.
  • You are checking jump timers etc. every frame. A more elegent solution is to start a coroutine .
  • You use a sinusoid as your jump curve, which looks ok, but using a parabola would be conceptually more correct.
  • Right now it is possible to start next jump mid-air (I'm not sure whether it is intended or not)

Here is some code you may use that avoids those problems:

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;
}

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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