如何使用 CharacterController 跳转到一个点?

Aim*_* Z. 4 c# unity-game-engine

我有一个要跳转的脚本,但它的跳转取决于 JumpFactor 常量的值。我希望使用 JumpToPositionX(浮动目标)方法进行跳转。我想我需要根据 JumpToPositionX 方法中目标的值以某种方式计算 JumpFactor。我在维基百科上找到了一篇文章,但我什至不知道从哪里开始。我还没有找到有关如何使用 CharacterController 执行此操作的示例。

public class ExampleClass : MonoBehaviour
{
    const float Speed = 6f;
    const float JumpFactor = 14f;
    const float Gravity = 20f;
    
    private Vector3 moveDirection = Vector3.zero;

    CharacterController controller;

    void Start()
    {
        controller = GetComponent<CharacterController>();
    }

    void Update()
    {
        if (controller.isGrounded)
        {
            moveDirection = new Vector3(1f, 0f, 0f); // Move X Direction
            moveDirection *= Speed;
            if (Input.GetButton("Jump"))
                moveDirection.y = JumpFactor;

        }
        moveDirection.y -= Gravity * Time.deltaTime;
        controller.Move(moveDirection * Time.deltaTime);
    }

    // Method for jump, calling from other script.
    void JumpToPositionX(float target)
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

D.B*_*D.B 7

理论

我假设您想使用弹道物理学。

让我们看看我们可以使用什么公式

速度公式

位置公式

在哪里 :

  • V : 速度
  • 一:加速
  • P : 位置
  • t : 自开始以来的时间
  • 0 : 初始

已知它是(0f,-9.81f)(0f, Gravity)在您的情况下。

也是已知的,它是你跳跃前的初始位置。

是最终目标位置。

解析度

你必须找到结束时间 和初始速度 . 所以这是位置方程:

我们可以通过只查找 x 轴来简化这个过程,因为没有加速度。

简化为:

让我们隔离 从 x 位置公式:

现在你有了跳跃的总时间 . 你只需要找到初始 y 速度 通过使用 y 位置公式:

隔离 Vyo :

所以现在你有了计算跳跃的所有信息:初始和结束位置、总时间、初始速度和加速度。

执行

这是您可以创建的 MonoBehaviour 示例:

public class JumpBehaviour : MonoBehaviour
{

    public CharacterController CharacterController;

    public Transform TargetPosition;

    private bool jumpStarted = false;
    private float totalTime = 0f;
    private float t = 0f;
    private Vector2 V0;

    private Vector2 initialPosition;

    private bool jumpKeyDown;

    private const float xSpeed = 6f;
    private const float gravity = -9.81f;

    void Update()
    {
        jumpKeyDown = Input.GetKeyDown(KeyCode.Space);
    }

    void FixedUpdate()
    {
        if (jumpStarted)
        {
            UpdateJumpPosition(Time.fixedDeltaTime);
        }
        else if (jumpKeyDown )
        {
            StartJump();
        }
    }

    private void UpdateJumpPosition(float deltaTime)
    {
        t += deltaTime;

        if(t > totalTime)
        {
            //End of jump
            transform.position = TargetPosition.position;
            jumpStarted = false;
            return;
        }

        Vector2 newPosition = new Vector2(0f, gravity) * t * t + V0 * t + initialPosition;

        CharacterController.Move(newPosition);
    }

    private void StartJump()
    {
        jumpStarted = true;

        initialPosition = transform.position;

        // Absolute because xSpeed could be positive or negative. We dont want negative time
        float delta = TargetPosition.position.x - transform.position.x;
        totalTime = Mathf.Abs(delta / xSpeed);
        t = 0f;

        float yInitialSpeed = (TargetPosition.position.y - transform.position.y - gravity * totalTime * totalTime) / totalTime;

        // Using Sign to set the direction of horizontal movement
        V0 = new Vector2(xSpeed * Mathf.Sign(delta), yInitialSpeed);
    }
}
Run Code Online (Sandbox Code Playgroud)

这就是结果 统一结果

结论

这只是一个简单的例子,用于说明如何计算 2D 中跳跃和移动的初始值。正如 derHugo 在评论中所说,您不应该对 Physic 使用transform.position直接归因。

对于 3D,这是相同的想法,但您应该根据目标方向和速度大小计算速度 x,z。

Vector3 delta = TargetPosition - transform.position;
delta.y = 0f;
float direction = delta.normalized;
Vector3 initialSpeed = direction * movementSpeed;
Run Code Online (Sandbox Code Playgroud)