[英]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.