我正在使用 Unity 制作 2D 平台游戏,自从我决定使用新的输入系统来支持游戏手柄和键盘以来,已经过去 3 周了,但我仍然在努力解决这个问题。另外,我正在使用玩家输入组件并调用统一事件行为。事实上,我从 GitHub 下载了一个玩家控制器代码以将其用作指南,并将其复制并粘贴到我的实际玩家控制器中,但问题是它使用的是旧的输入系统。所以我需要稍微改变一下代码,但我不知道如何在 void update 而不是
(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, 0, 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);
}
}
我想尝试一下,因为我还没有在自己的游戏中实现跳跃,我想看看新输入系统有多么简单。我很喜欢这个,基于事件的输入最酷的部分之一是您不必将所有内容都放入一个方法中!
请注意,我是在 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以进行摇杆和方向键移动。因此,通过的值将具有 movement.x
和 movement.y
分别获得水平和垂直输入。
这就是我将
Up
控件映射到 W
键的方式。 (其他类似,但映射到适当的键。)
这是我设置运动变量的代码。
private Vector2 moveInput;
void PlayerInputActions.IAvatarDefaultActions.OnMove(InputAction.CallbackContext context)
{
moveInput= context.ReadValue<Vector2>();
}
现在您只需在更新代码中使用
moveInput.x
来获取水平值!
从统一文档和我对统一的小知识来看,您似乎正在正确使用它,但是在他们运行的示例中
float speed = Input.GetAxisRaw("Horizontal") * Time.deltaTime;
所以也许如果您遇到问题,请尝试使用该行并看看有什么变化。如果您在按键映射方面遇到困难,它还表示您可以在“编辑”->“设置”->“输入”中对其进行编辑。
文档:https://docs.unity3d.com/ScriptReference/Input.GetAxisRaw.html