繁体   English   中英

C#如何在unity3d中平滑跳跃而不将X移向最近的对象

[英]C# How to make a smooth jump in unity3d without moving the X, towards the nearest object

我想顺利地跳到最近的立方体。 我已经有一个脚本来检测最接近的多维数据集。 我希望X轴被锁定,所以跳跃时只有Y轴和Z轴会改变。 我想在跳跃时使用跳跃动画。 我已经尝试过使用Vector3MoveTowards,但这并不是很好,也许我没有正确使用它。

检测玩家应跳至(C#)的最近立方体

 void Update() { FindClosestCube (); GameObject closestCube = FindClosestCube (); Debug.Log (closestCube); } GameObject FindClosestCube() { GameObject[] gos; gos = GameObject.FindGameObjectsWithTag("cube"); GameObject closest = null; float distance = Mathf.Infinity; float position = transform.position.z; foreach (GameObject go in gos) { float diff = go.transform.position.z - position; float curDistance = diff; if (curDistance < distance) { closest = go; distance = curDistance; } } return closest; } 

棘手的部分是,在某些多维数据集上,您必须向上跳(y + 1),在某些多维数据集上,您向同一Y(y + 0)跳,而在某些多维数据集上,您跳下(y-1)。 我该怎么做呢?

外观如下图:

在此处输入图片说明

编辑:我现在有此代码:

  ----------------C#----------------- Rigidbody rb; public int clicks = 0; Vector3 target; public Animation jumpAnimation; bool jump = false; float cubeDiffY; bool movePlayer; public float smoothTime = 0.3f; public float yVelocity = 0.0f; void Start() { rb = GetComponent<Rigidbody> (); } void Update () { FindClosestCube (); GameObject closestCube = FindClosestCube (); Debug.Log ("Closestcube = " + closestCube); target = closestCube.transform.position + new Vector3 (0f, 0.7f, 0f); cubeDiffY = target.y - transform.position.y; movePlayer = true; Debug.Log("Cube Difference Y-axis = " + Mathf.Round(cubeDiffY)); if (Input.GetMouseButtonDown (0)) { clicks += 1; jump = true; jumpAnimation = gameObject.GetComponent<Animation>(); //jumpAnimation.Play (); } if (jump == true) { Jump (); } } void Jump() { float newPosition = Mathf.SmoothDamp (transform.position.y, target.y, ref yVelocity, smoothTime); transform.position = new Vector3 (0, newPosition, transform.position.z); } 

我计算了玩家站立的立方体和最近的立方体之间在Y轴上的差异。 但是Jump()不起作用。 我该如何解决?

好吧,我为您的游戏设置了一个快速版本,并获得了您想要的功能,但这并不是一个快速的解决方案,因为您所做的工作并没有内置功能,只能使用动画。

这是字符脚本,其中包含您需要的所有代码并进行了彻底注释,因此应自行解释。

using UnityEngine;

public class Character : MonoBehaviour
{
    //the collider for the player
    private new BoxCollider collider;

    //the jump box collider on a empty game object that is a child to the player object
    public BoxCollider JumpBox;

    //the offset of the cube so it doesn't stop inside of it
    public Vector3 cubeOffset;

    //how high the jump will be
    public float JumpHeight;

    //how fast the jump will be
    public float JumpSpeed;

    //holds the change in position the jump will produce
    private Vector3 jumpDelta;

    //holds the destination cube the jump is attempting to hit
    private Cube destinationCube;

    //true if a jumping animation is currently playing
    private bool jumping = false;

    //used to swap the jump direction from up to down
    private bool jumpDirection = true;

    //used to hold the position of the jump so it knows when to stop
    private float jumpPosition = 0;

    // Use this for initialization
    void Start()
    {
        collider = GetComponent<BoxCollider>();
    }

    // Update is called once per frame
    void Update()
    {
        if(jumping)
        {
            //move straight towards the cube
            transform.position = transform.position + (JumpSpeed * jumpDelta);

            //move up and down to simulate a jump
            //check the current move direction
            if (jumpDirection)
            {
                //add to the jump position twice product of the JumpHeight the JumpSpeed so that it will 
                //rise and fall the same amount of time it takes to move to the destination
                jumpPosition += JumpHeight * JumpSpeed * 2;
                //if it has passed the jump height reverse the jump direction
                if (jumpPosition >= JumpHeight)
                    jumpDirection = !jumpDirection;
                transform.position += transform.up * JumpHeight * JumpSpeed * 2;
            }
            //the jump direction is going down
            else
            {
                jumpPosition -= JumpHeight * JumpSpeed * 2;
                transform.position -= transform.up * JumpHeight * JumpSpeed * 2;
            }
            //check if the character collider intersects witht he cubes collider
            //if it has then stop jumping and set the final position as the destination position
            if (collider.bounds.Intersects(destinationCube.BoxCollider.bounds))
            {
                jumping = false;
                transform.position = destinationCube.transform.position + cubeOffset;
            }
        }
        //detect a jump
        if (Input.GetKeyDown(KeyCode.Space))
        {
            //detect all hits on the jump box
            Collider[] hits = Physics.OverlapBox(JumpBox.center, JumpBox.size * 0.5f);
            //get the closest collider with the right tag
            Collider result = GetClosestColliderWithTag(hits, "Cube");

            //if we have a result then begin the jumping animation
            if(result != null)
            {
                //gets the destination cubes cube component(the custom class you have on your cubes)
                destinationCube = result.gameObject.GetComponent<Cube>();

                //calculate the jump delta
                jumpDelta = (result.transform.position + cubeOffset) - transform.position;

                //remove the left and right components so the jumping doesnt move to the left or right of the player
                Vector3 component = Vector3.Project(jumpDelta, -transform.right);
                jumpDelta -= component;
                component = Vector3.Project(jumpDelta, transform.right);
                jumpDelta -= component;

                //setup the jump animation control fields to the initial values
                jumpPosition = 0;
                jumpDirection = true;
                jumping = true;
            }
        }
    }
    private Collider GetClosestColliderWithTag(Collider[] colliders, string tag)
    {
        //just gets the closest collider
        float distance = float.MaxValue;
        int result = -1;
        for (int i = 0; i < colliders.Length; i++)
        {
            if (colliders[i].tag == tag)
            {
                float distanceTemp = Vector3.Distance(transform.position, colliders[i].transform.position);
                if (distanceTemp < distance)
                {
                    distance = distanceTemp;
                    result = i;
                }
            }
        }
        if (result != -1)
            return colliders[result];
        else return null;
    }
}

这是我的多维数据集脚本,其中包含一些您需要添加的内容

using UnityEngine;

public class Cube : MonoBehaviour {
    //these arent important just fields I used to set up a quick version of your game
    public GameObject StartPoint;
    public GameObject EndPoint;
    public float Speed;
    private Vector3 directionVector;
    private bool direction;

    //YOU WILL NEED THIS!!
    [HideInInspector]
    public BoxCollider BoxCollider;


    // Use this for initialization
    void Start() {
        //not important
        directionVector = EndPoint.transform.position - StartPoint.transform.position;
        directionVector.Normalize();

        //DONT FORGET TO SET YOUR BOX COLLIDER
        BoxCollider = GetComponent<BoxCollider>();
    }

    // Update is called once per frame
    void Update()
    {
        float distance = 0;
        if (direction)
        {
            distance = Vector3.Distance(EndPoint.transform.position, transform.position);
            transform.position += directionVector * Speed;
            if (distance < Vector3.Distance(EndPoint.transform.position, transform.position))
                direction = !direction;
        }
        else
        {
            distance = Vector3.Distance(StartPoint.transform.position, transform.position);
            transform.position -= directionVector * Speed;
            if (distance < Vector3.Distance(StartPoint.transform.position, transform.position))
                direction = !direction;
        }
    }
}

上一个答案

我要说的是,您需要计算将来对象的感知位置。

Vector3 futurePos = cubePos + (cubeMoveDirection * cubeMoveSpeed);

一旦有了将来的位置,即使位置不准确,也应该将动画对准该位置。 为此,我将让动画更改速度矢量而不是实际的变换位置,这样我们就可以在保持块方向的同时,沿所需的任何方向旋转该速度矢量。 否则,您必须旋转整个块以指向所需的方向。 如果这是您想要的,则将您的积木放在一个空的游戏对象下,旋转该空的游戏对象以指向您想要的位置,然后仅进行速度计算。

接下来,您的动画应具有净移动矢量,该矢量应预先计算并按比例缩小或放大,以适应到未来位置的距离。 它看起来像这样(注意这未经测试)

//class fields
Vector3 AnimatedSpeed;

Vector3 AnimationDelta;

//basic calculation

//get the direction vector from the players current position to the future 
block position

Vector3 dirVector = futurePos - transform.position;
//find the rotation from the current orientation to the direction vector
Quaternion rotation = Quaternion.FromToRotation(transform.forward, dirVector);

//calculate the distance from you to the cube and scale it with the magnitude of the AnimationDelta
float result = Vector3.Distance(transform.position, futurePos);

result = result / animationDelta.magnitude;

//finally rotate the forward vector by the rotation and multiply it by the 
//animation speed and the result to get the step by step movement as
//the animation plays. NOTE: The animation should be based on forward direction

transform.position += (AnimationSpeed * rotation) * result * Time.deltaTime;

希望可以做到这一点,就像我说过我还没有测试过那样,所以您可能必须根据您的特定情况进行一些调整,因为这本质上是伪代码。

祝好运! 我上床睡觉,醒来后会再检查一次。

暂无
暂无

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

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