我是一名学习视频游戏编程的二年级学生,我已经在这个问题上挣扎了一段时间,我想知道你们是否可以就如何解决这个问题提供最好的建议。
我有一个 3D 角色,可以行走、奔跑、跳跃、二段跳和旋转以面对光标。然而,我注意到一种错误,我的角色能够控制其在半空中的移动。
例如,如果你按住左Shift + W然后跳跃,你就可以停止向前移动,然后开始在半空中向左扫射.
这是我的代码:
void Update ()
{
// Turns off all animations while in the air
if (isInAir)
{
animator.SetBool("Running", false);
animator.SetBool("Walking", false);
}
if (Input.GetKey(KeyCode.W))
{
// If the character is not in the air then turn on the walk animation
if (!isInAir)
{
animator.SetBool("Walking", true);
}
transform.Translate(Vector3.forward * movementSpeed * Time.deltaTime);
}
else if (Input.GetKey(KeyCode.S))
{
// If the character is not in the air then turn on the walk animation
if (!isInAir)
{
animator.SetBool("Walking", true);
}
transform.Translate(Vector3.back * movementSpeed * Time.deltaTime);
}
if (Input.GetKey(KeyCode.A))
{
// If the character is not in the air then turn on the walk animation
if (!isInAir)
{
animator.SetBool("Walking", true);
}
transform.Translate(Vector3.left * movementSpeed * Time.deltaTime);
}
else if (Input.GetKey(KeyCode.D))
{
// If the character is not in the air then turn on the walk animation
if (!isInAir)
{
animator.SetBool("Walking", true);
}
transform.Translate(Vector3.right * movementSpeed * Time.deltaTime);
}
if (Input.GetKey(KeyCode.LeftShift))
{
// If the character is not in the air then turn on the run animation
// and change the character's movementSpeed
if (!isInAir)
{
movementSpeed = runSpeed;
animator.SetBool("Running", true);
}
}
else
{
// If the character is not in the air then reset their movement speed
// and turn off the run animation.
if (!isInAir)
{
movementSpeed = walkSpeed;
animator.SetBool("Running", false);
}
}
// When a key is released, turn off the movement animations
// This does not cause an issue since each movement if statement turns the animation back on
if (Input.GetKeyUp(KeyCode.W) || Input.GetKeyUp(KeyCode.S) || Input.GetKeyUp(KeyCode.A) || Input.GetKeyUp(KeyCode.D))
{
animator.SetBool("Walking", false);
animator.SetBool("Running", false);
}
#endregion
// Jumping
if (Input.GetButtonDown("Jump") && jumpCounter != 2)
{
jumpCounter++;
isInAir = true;
myRigidbody.AddForce(new Vector3(0, jumpForce));
if (jumpCounter == 1)
{
firstJumpStamp = Time.time;
}
}
if(Physics.Raycast(groundCheckRay, groundCheckRayDistance) && Time.time > firstJumpStamp + 0.5f)
{
jumpCounter = 0;
isInAir = false;
}
}
我删除了所有与角色移动无关的代码。
有人可以给我一个关于我可以用来完成这项工作的方法的建议吗?
我不是要求提供代码来解决此问题,只是一个建议...
我觉得我需要自己学习这个,我只需要有人给我指明正确的方向。
如果您不理解部分代码,请随时询问我,我很乐意向您展示我正在尝试用它做什么。 :) 例如,也许您知道编写某些行的更好方法。
(我确实尽量避免使用 Input.GetAxis
,因为我发现当我无法 100% 控制它时,很难进行移动)
最佳答案
我可以建议您重新评估您的要求并将其与您所写的内容进行比较。您所描述的内容与您在代码中所做的内容之间存在细微差别。首先,您希望该角色能够向左或向右移动,而不是同时移动这两个移动,前进和后退也是如此。
为了解决此问题,您可以使用 Input.GetAxis
而不是您现在使用的 Input.GetKey
。
我可以建议的第二件事是使用本地 Vector3
来计算力,然后将其应用于您的角色。然后,您可以根据 Vector3
值设置动画变量。
您的主要问题在于所使用的运动技术。由于您决定使用 Transform.Translate
而不是使用 Rigidbody
来移动角色,因此您必须计算帧上的位置增量。
假设您的角色将从位置 [ x:1.00f, y: 0.00f, z: 1.00f ]
开始,并朝 [ x: 0.30f, y: 0.00f, z: 0.70f ]
在帧 1
上,它决定跳跃。那么你要做的就是抢到之前的位置
(帧更改之前的那个)将是 [ x:1.00f, y: 0.00f, z: 1.00f ]
并从当前位置中减去它,即 [ x:1.30f ,y:0.00f,z:1.70f]
。这将返回一个等于先前位置增量的向量 ([ x: 0.30f, y: 0.00f, z: 0.70f ]
)。现在只需将此位置添加到当前位置,它应该保持相同的航向(方向)。
这不包括摩擦力,因此您的角色在半空中时将始终以相同的速度朝相同的方向移动。
即使您没有要求提供代码,但在其中描述它比用简单的英语描述要容易得多(至少对我来说是这样:))所以,这里有一个示例代码:
// value indicating what was the position before change
Vector3 previousPosition;
void Update ()
{
// get user input as a vector
Vector3 horizontal = Vector3.right * Input.GetAxis("horizontal");
Vector3 vertical = Vector3.forward * Input.GetAxis("vertical");
bool isRunning = Input.GetKey(KeyCode.LeftShift);
float speedModifier = isRunning ? runSpeed : walkSpeed;
// add these inputs together
Vector3 currentVelocity = (horizontal + vertical);
// check if player is in mid air
if (IsInAir)
{
// if it is, get the previous and current positions
// add calculate the distance between frames
// and normalize it to get the movement direction
Vector3 currentPosition = transfor.position;
Vector3 direction = (currentPosition - previousPosition).Normalize();
// apply movement direction to the "currentVelocity"
currentVelocity = direction * speedModifier * Time.deltaTime;
}
else
{
// user is not in mid air so you can just calculate
// the position change
currentVelocity = currentVelocity.Normalize() * speedModifier * Time.deltaTime;
if ( currentVelocity != Vector3.zero )
{
animator.SetBool("walking", !isRunning);
animator.SetBool("running", isRunning);
}
}
// current position ( before changes )
// should be copied to a previous position
// to calculate it in the next frame update
previousPosition = currentPosition;
// do the translation
transform.Translate(currentVelocity);
}
附加信息: 我仍然强烈建议您从 Transform.Translate 切换到 Rigidbody,并在角色处于半空中时“重新使用”它的速度。这不需要您计算每帧的位置增量,从而使其更易于使用。
关于c# - Unity3D - 防止3D角色在空中改变方向,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46171538/