C# 如何在不移动 X 的情况下在 unity3d 中平滑跳跃,朝向最近的对象 [英] C# How to make a smooth jump in unity3d without moving the X, towards the nearest object
问题描述
我想平稳地跳向最近的立方体.我已经有一个脚本来检测最近的立方体.我希望X轴被锁定,所以跳跃时只有Y轴和Z轴发生变化.我想在跳跃时使用跳跃动画.我已经尝试过使用 Vector3MoveTowards,但效果不佳,可能是我没有正确使用它.
I would like to make a smooth jump towards the nearest cube. I already have a script to detect the closest cube. I want that the X-axis is locked, so only the Y-axis and the Z-axis change when jumping. I would like to use a Jump animation when jumping. I already tried to use Vector3MoveTowards, but that didn't really work well, maybe I didn't use it properly.
检测玩家应该跳到的最近立方体(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).我该怎么做?
The tricky part is that at some cubes you have to jump up (y+1), with some cubes you jump towards the same Y (y+0) and with some cubes you jump down (y-1). How do I do this?
外观图片:
我现在有这个代码:
----------------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() 不起作用.我该如何解决?
I calculated the difference in Y-axis between the cube where the player is standing on and the closestCube. But the Jump() doesn't work. How do I fix that?
推荐答案
好的,我为你的游戏设置了一个快速版本并得到了你想要的东西,这不是一个快速的解决方案,因为你所做的并没有内置了除使用动画以外的功能.
Okay I set up a quick version of your game and got what you wanted to work, it is not exactly a quick solution, because what your doing doesn't have built in functionality for other than using animations.
这是字符脚本,其中包含您需要的所有代码并进行了彻底的注释,因此它应该自我解释.
Here is the character script that has all the code you need and commented thoroughly so it should explain itself.
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;
}
}
这是我的多维数据集脚本,其中包含一些您需要添加的内容
And here is my cube script which has some things you will need to add
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;
}
}
}
上一个答案
我会说你需要计算未来物体的感知位置.
I would say you need to calculate the perceived position of the object in the future.
Vector3 futurePos = cubePos + (cubeMoveDirection * cubeMoveSpeed);
一旦你有了未来的位置,即使它不准确,你也应该将你的动画瞄准那个位置.为此,我将让动画更改速度矢量而不是实际变换位置,这样我们就可以在保持块方向的同时沿您想要的任何方向旋转该速度矢量.否则,您必须旋转整个块以指向您想要的方向.如果这是你想要的,那么把你的方块放在一个空的游戏对象下,旋转空的游戏对象指向你想要的位置,然后只进行速度计算.
Once you have the future position, even if it is not exact, you should aim your animation towards that position. To do this I would have the animation change a speed vector instead of an actual transforms position that way we can rotate this speed vector in any direction you want while keeping the orientation of the block. Otherwise you have to rotate the entire block to point towards the direction you want. If this is what you want then put your block under a empty gameobject, rotate the empty gameobject to point to where you want and do the speed calculations only.
接下来你的动画应该有一个净移动向量,它应该被预先计算并缩小或放大以满足到未来位置的距离.它看起来像这样(注意这没有经过测试)
Next your animation should have a net move vector which should be pre-calculated and scaled down or up to meet the distance to the future position. It will look something like this(note this is not tested)
//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;
希望这样做,就像我说的那样,我根本没有测试过它,因此您可能需要根据您的特定情况进行一些调整,因为这本质上是伪代码.
Hopefully this does it, like I said I haven't tested it at all so you may have to do some tweaking based on your particular case as this is essentially psuedo-code.
祝你好运!我要睡觉了,等我醒来再来看看.
Good luck! I'm off to bed I'll check back when I wake up.
这篇关于C# 如何在不移动 X 的情况下在 unity3d 中平滑跳跃,朝向最近的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!