我是一名学习视频游戏编程的二年级学生,我一直在努力解决这个问题,我想知道你们是否可以就如何解决这个问题提供最好的建议。
我有一个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%控制它时,我发现更难移动)
答案 0 :(得分:4)
我建议您重新评估您的要求,并将其与您撰写的内容进行比较。您所描述的内容与您在代码中所做的事情之间存在细微差别。首先,你希望这个角色能够向左或向右移动,而不是同时移动这两个角色,与向前和向后相同。
要获得此帮助,您可以使用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 ]
。这将返回一个等于前一个位置delta([ 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
,然后重新使用"角色在半空中时的速度。这不需要您计算每帧的位置增量,使其更容易使用。
答案 1 :(得分:1)
我认为您需要的是将transform
移到if
。因为现在你正在以任何方式移动物体,只是不更新布尔
例如:
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); //<-- New line
}
//transform.Translate(Vector3.forward * movementSpeed * Time.deltaTime); //<-- Removed line
}
您需要为所有动作if
s