问题描述
我正在用Unity制作2D平台游戏,距离我决定使用新的输入系统提供游戏手柄支持和键盘已经3个星期了,但我仍在努力。另外,我正在使用Player Input组件并调用统一事件行为。实际上,我从GitHub下载了一个Player Controller代码以用作指导,然后将其复制并粘贴到我的实际Player Controller中,但问题是它使用的是旧的Input System,我不知道如何编写无效更新中的等效代码,而不是“(Input.GetAxisRaw(“ Horizontal”))“,而不是我想知道的代码中是否还有其他问题?我已经尝试解决这些问题很长时间了,如果您能指导我,并且代码很长,我将不胜感激。
这是我的播放器控制器代码。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerController : MonoBehavIoUr
{
private PlayerInputActions controls;
private Rigidbody2D rb;
private Animator anim;
private bool facingRight = true;
private float moveInput;
public Transform feetPos;
public float jumpInput;
public float speed;
[Serializefield] float JumpVeLocity = 5;
float JumppressedRemember = 0;
[Serializefield] float JumppressedRememberTime = 0.2f;
float GroundedRemember = 0;
[Serializefield] float GroundedRememberTime = 0.25f;
[Serializefield] float Horizontalacceleration = 1;
[Serializefield] [Range(0,1)] float HorizontaldampingBasic = 0.5f;
[Serializefield] [Range(0,1)] float HorizontaldampingWhenStopping = 0.5f;
[Serializefield] [Range(0,1)] float HorizontaldampingWhenTurning = 0.5f;
[Serializefield] [Range(0,1)] float JumpHeight = 0.5f;
private void Awake()
{
controls = new PlayerInputActions();
}
void Start()
{
rb = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
}
public void OnMove(InputAction.CallbackContext context)
{
moveInput = context.ReadValue<float>();
}
public void OnJump(InputAction.CallbackContext context)
{
JumpVeLocity = context.ReadValue<float>();
}
void FixedUpdate()
{
rb.veLocity = new Vector2(moveInput * speed,rb.veLocity.y);
if (facingRight == false && moveInput > 0)
{
Flip();
}
else if (facingRight == true && moveInput < 0)
{
Flip();
}
}
void Flip()
{
facingRight = !facingRight;
Vector3 Scaler = transform.localScale;
Scaler.x *= -1;
transform.localScale = Scaler;
}
void Update()
{
Vector2 GroundedBoxCheckPosition = (Vector2)transform.position + new Vector2(0,-0.01f);
Vector2 GroundedBoxCheckScale = (Vector2)transform.localScale + new Vector2(-0.02f,0);
bool Grounded = Physics2D.OverlapBox(GroundedBoxCheckPosition,transform.localScale,0);
GroundedRemember -= Time.deltaTime;
if (Grounded)
{
GroundedRemember = GroundedRememberTime;
}
JumppressedRemember -= Time.deltaTime;
if (controls.Player.Jump.triggered)
{
JumppressedRemember = JumppressedRememberTime;
}
if (controls.Player.Jump.triggered)
{
if (rb.veLocity.y > 0)
{
rb.veLocity = new Vector2(rb.veLocity.x,rb.veLocity.y * JumpHeight);
}
}
if ((JumppressedRemember > 0) && (GroundedRemember > 0))
{
JumppressedRemember = 0;
GroundedRemember = 0;
rb.veLocity = new Vector2(rb.veLocity.x,JumpVeLocity);
}
float HorizontalVeLocity = rb.veLocity.x;
HorizontalVeLocity += Input.GetAxisRaw("Horizontal");
if (Mathf.Abs(Input.GetAxisRaw("Horizontal")) < 0.01f)
HorizontalVeLocity *= Mathf.Pow(1f - HorizontaldampingWhenStopping,Time.deltaTime * 10f);
else if (Mathf.Sign(Input.GetAxisRaw("Horizontal")) != Mathf.Sign(HorizontalVeLocity))
HorizontalVeLocity *= Mathf.Pow(1f - HorizontaldampingWhenTurning,Time.deltaTime * 10f);
else
HorizontalVeLocity *= Mathf.Pow(1f - HorizontaldampingBasic,Time.deltaTime * 10f);
rb.veLocity = new Vector2(HorizontalVeLocity,rb.veLocity.y);
}
}
这是我从GitHub下载的代码。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehavIoUr
{
[Serializefield]
LayerMask lmWalls;
[Serializefield]
float fJumpVeLocity = 5;
Rigidbody2D rigid;
float fJumppressedRemember = 0;
[Serializefield]
float fJumppressedRememberTime = 0.2f;
float fGroundedRemember = 0;
[Serializefield]
float fGroundedRememberTime = 0.25f;
[Serializefield]
float fHorizontalacceleration = 1;
[Serializefield]
[Range(0,1)]
float fHorizontaldampingBasic = 0.5f;
[Serializefield]
[Range(0,1)]
float fHorizontaldampingWhenStopping = 0.5f;
[Serializefield]
[Range(0,1)]
float fHorizontaldampingWhenTurning = 0.5f;
[Serializefield]
[Range(0,1)]
float fCutJumpHeight = 0.5f;
void Start ()
{
rigid = GetComponent<Rigidbody2D>();
}
void Update ()
{
Vector2 v2GroundedBoxCheckPosition = (Vector2)transform.position + new Vector2(0,-0.01f);
Vector2 v2GroundedBoxCheckScale = (Vector2)transform.localScale + new Vector2(-0.02f,0);
bool bGrounded = Physics2D.OverlapBox(v2GroundedBoxCheckPosition,v2GroundedBoxCheckScale,lmWalls);
fGroundedRemember -= Time.deltaTime;
if (bGrounded)
{
fGroundedRemember = fGroundedRememberTime;
}
fJumppressedRemember -= Time.deltaTime;
if (Input.GetButtonDown("Jump"))
{
fJumppressedRemember = fJumppressedRememberTime;
}
if (Input.GetButtonUp("Jump"))
{
if (rigid.veLocity.y > 0)
{
rigid.veLocity = new Vector2(rigid.veLocity.x,rigid.veLocity.y * fCutJumpHeight);
}
}
if ((fJumppressedRemember > 0) && (fGroundedRemember > 0))
{
fJumppressedRemember = 0;
fGroundedRemember = 0;
rigid.veLocity = new Vector2(rigid.veLocity.x,fJumpVeLocity);
}
float fHorizontalVeLocity = rigid.veLocity.x;
fHorizontalVeLocity += Input.GetAxisRaw("Horizontal");
if (Mathf.Abs(Input.GetAxisRaw("Horizontal")) < 0.01f)
fHorizontalVeLocity *= Mathf.Pow(1f - fHorizontaldampingWhenStopping,Time.deltaTime * 10f);
else if (Mathf.Sign(Input.GetAxisRaw("Horizontal")) != Mathf.Sign(fHorizontalVeLocity))
fHorizontalVeLocity *= Mathf.Pow(1f - fHorizontaldampingWhenTurning,Time.deltaTime * 10f);
else
fHorizontalVeLocity *= Mathf.Pow(1f - fHorizontaldampingBasic,Time.deltaTime * 10f);
rigid.veLocity = new Vector2(fHorizontalVeLocity,rigid.veLocity.y);
}
}
解决方法
从unity文档和我对unity的一点了解来看,似乎您使用的是正确的,但是在示例中它们运行float speed = Input.GetAxisRaw("Horizontal") * Time.deltaTime;
,因此,如果您遇到问题,请尝试使用该行,看看有什么变化。如果您在键映射方面苦苦挣扎,它还说您可以在“编辑”->“设置”->“输入”中对其进行编辑。
文档:https://docs.unity3d.com/ScriptReference/Input.GetAxisRaw.html
,我想尝试一下,因为我还没有在自己的游戏中实现跳跃,而且我想看看使用新输入系统可以多么简单。我宁愿喜欢它,关于基于事件的输入最酷的部分之一就是您不必将所有内容都放在一个方法中!
请注意,我是在3D模式下完成的-我还没有设置2D游戏。我认为您可能需要调整施加力的轴,并使用RigidBody2D和2D碰撞器。
对于设置,您需要在地形上使用对撞机,在角色上需要对撞机和RigidBody。 (我假设您已经设置好了,但这是给其他找到答案的人使用的。)需要在地面上使用对撞机,以使玩家不会掉落在地面上。播放器上的对撞机是出于相同的原因。 RigidBody允许围绕重力和质量等进行物理和计算。(此示例必须启用重力!)
因此,此示例将允许我们在向上的方向上向玩家施加力,然后重力会将角色带回地形。
首先,请注意,当您创建控件并自动生成C#类时,您需要让您的类继承该类。您的控件类称为PlayerInputActions
。我没有看到“动作图”名称,因此我将使用我的名称。在GUI中,我的称为“ AvatarDefault”。该动作称为“跳转”。如果检查自动生成的C#类,则会找到名称空间,接口和方法。我的动作图在生成时成为接口,并被命名为IAvatarDefaultActions
。由于您没有列出您的ActionMap名称,因此我将使用我的名称。在代码中将其替换为您的代码。
如有必要,导入您的名称空间,并在播放器输入类上继承接口。
为简洁起见,删除了一些代码!
public class PlayerController : MonoBehaviour,PlayerInputActions.IAvatarDefaultActions {
// allow changing the force applied when jumping in the editor.
// note that for a mass of 1 on my character,I had to use a value of about 300
[SerializeField]
private float jumpForce;
// track our instance of controls
private PlayerInputActions controls;
// in awake,we need to create a new instance of controls
// and bind the action events.
private void Awake()
{
controls = new PlayerInputActions();
// the auto-generated class takes care of all the event registration we need to do!
// without this,we won't get event notifications.
controls.AvatarDefault.SetCallbacks(this);
}
// I chose to explicitly implement the interface for clarity (since I'm still newish)
void PlayerInputActions.IAvatarDefaultActions.OnJump(InputAction.CallbackContext context)
{
// there are several phases,but the only one we should care about is whether
// the action was performed or not. (You can use an if statement,if you want)
switch (context.phase)
{
case InputActionPhase.Performed:
// to separate event handlers from actual code,I've been putting the
// actual logic in a separate method
this.Jump();
break;
}
}
public void Jump()
{
// you can play around with the ForceMode here,and probably need
// to use a Vector2 since you're working with 2D.
// in this example,though,it's applying the jump force on the y axis.
// a positive value will make the character thrust upward.
rb.AddForce(transform.up * this.jumpForce,ForceMode.Force);
}
// You should also have these two methods
public void OnEnable()
{
controls.Enable();
}
public void OnDisable()
{
controls.Disable();
}
}
让我知道这是否有帮助。如果没有,我可以尝试设置2D环境。看来唯一会改变2D的是使用ForceMode2D.Force
。
作为参考,这是我的输入设置的样子。我将“跳转”设置为“按钮”操作类型,因为我只关心是否按下它。
运动修复程序更新
对于movement
的问题,输入系统旨在轻松传递Vector2,以进行操纵杆和D-pad的移动。因此传入的值将分别具有movement.x
和movement.y
来获取水平和垂直输入。
这就是将Up
控件映射到W
键的方式。 (其他类似,但映射到适当的键。)
这是我设置移动变量的代码。
private Vector2 moveInput;
void PlayerInputActions.IAvatarDefaultActions.OnMove(InputAction.CallbackContext context)
{
moveInput= context.ReadValue<Vector2>();
}
现在您只需在更新代码中使用moveInput.x
作为水平值即可!