我正在 Unity 中开发一款游戏,并尝试清理一些代码并提高可重用性。我有一个基本的玩家移动脚本,如下所示:
using System;
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.Animations;
using UnityEngine.TextCore.Text;
//TODO - refactor this as a design pattern -- in progress
// Implementing command pattern for userInput
public class Movement : MonoBehaviour
{
private Rigidbody2D body;
private Animator anim;
[SerializeField] private readonly float speed = 5;
private bool grounded;
private void Awake()
{
// Grab references for rigidbody and animator from object
body = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
anim.SetBool("grounded", true);
}
private void Update()
{
float horizontalInput = Input.GetAxis("Horizontal");
CharacterFacing(horizontalInput);
CharacterRun(horizontalInput);
Jump();
// TODO - add jumpBuffer implementation. Should use Time.Delta value.
}
private void Jump()
{
anim.SetFloat("jumpAsc", body.velocity.y);
if (Input.GetKey(KeyCode.Space) && grounded)
{
body.velocity = new Vector2(body.velocity.x, speed);
body.inertia = 30;
grounded = false;
}
if (Input.GetKeyUp(KeyCode.Space) && body.velocity.y > 0)
{
body.velocity = new Vector2(body.velocity.x, 0);
body.AddForce(5.0f * body.mass * Physics.gravity);
}
}
private void CharacterFacing(float horizontalInput)
{
// flip character left/right
if (horizontalInput > 0.01f)
transform.localScale = Vector3.one;
else if (horizontalInput < -0.01f)
transform.localScale = new Vector3(-1, 1, 1);
}
private void CharacterRun(float horizontalInput)
{
body.velocity = new Vector2(horizontalInput * speed, body.velocity.y);
anim.SetFloat("run", Math.Abs(body.velocity.x));
}
private void OnCollisionEnter2D()
{
grounded = true;
body.inertia = 10;
anim.SetBool("grounded", grounded);
}
}
我正在尝试将其重构为命令模式。我已将所有逻辑移至名为
Character
的类中,该类将用作 Player
和 Enemies
子类的父类。就是这样,基本没有变化:
using UnityEngine;
using System;
public class Character : MonoBehaviour
{
private Rigidbody2D _body;
private Animator _anim;
private int _HP;
private float _speed = 5;
private float _jumpForce;
private int _level;
private bool _grounded;
public Character()
{
_body = GetComponent<Rigidbody2D>();
_anim = GetComponent<Animator>();
_anim.SetBool("grounded", true);
}
public void Jump()
{
_anim.SetFloat("jumpAsc", _body.velocity.y);
if (Input.GetKey(KeyCode.Space) && _grounded)
{
_body.velocity = new Vector2(_body.velocity.x, _speed);
_body.inertia = 30;
_grounded = false;
}
if (Input.GetKeyUp(KeyCode.Space) && _body.velocity.y > 0)
{
_body.velocity = new Vector2(_body.velocity.x, 0);
_body.AddForce(5.0f * _body.mass * Physics.gravity);
}
}
private void CharacterFacing(float horizontalInput)
{
// flip character left/right
if (horizontalInput > 0.01f)
transform.localScale = Vector3.one;
else if (horizontalInput < -0.01f)
transform.localScale = new Vector3(-1, 1, 1);
}
public void Run()
{
float horizontalInput = Input.GetAxis("Horizontal");
_body.velocity = new Vector2(horizontalInput * _speed, _body.velocity.y);
_anim.SetFloat("run", Math.Abs(_body.velocity.x));
}
}
所以现在我的
Player
子类已清理完毕:
class Player : Character
{
Character _player;
UserInput _userInput;
public Player(UserInput userInput)
{
_player = gameObject.AddComponent<Character>();
_userInput = gameObject.AddComponent<UserInput>();
}
}
用户输入被分开:
using UnityEngine;
public class UserInput : MonoBehaviour
{
public Character _character;
public UserInput(Character character)
{
_character = character;
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
ICommand storedCommand = new JumpCommand(_character);
storedCommand.Execute();
}
if(Input.GetAxis("Horizontal") != 0)
{
ICommand storedCommand = new RunCommand(_character);
storedCommand.Execute();
}
}
}
但是现在我的玩家角色不动了。角色所做的就是掉到地上(这告诉我我的
Rigidbody2D
至少初始化正确)。我不知道如何将这一切结合在一起来监听用户输入。
我尝试在
UserInput
类中创建一个 Player
对象,希望它能够使用那里的 Update()
函数来捕获用户输入。我还尝试在 Unity 中创建一个事件系统并将我的 UserInput
脚本附加到该系统上。感觉就像我很接近,但我不知道如何将它们联系在一起。
EventSystem 仅用于 UI。另外,当您添加组件时,不会使用构造函数。我在您的代码设置 UserInput.character 中没有看到任何地方。如果您的 Run/JumpCommand 中出现某种无提示故障,您将 null 对象传递给它们,而它们什么都不做,您将不会收到任何错误。