Unity 中移动的命令模式实现

问题描述 投票:0回答:1

我正在 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
脚本附加到该系统上。感觉就像我很接近,但我不知道如何将它们联系在一起。

c# unity-game-engine game-development
1个回答
0
投票

EventSystem 仅用于 UI。另外,当您添加组件时,不会使用构造函数。我在您的代码设置 UserInput.character 中没有看到任何地方。如果您的 Run/JumpCommand 中出现某种无提示故障,您将 null 对象传递给它们,而它们什么都不做,您将不会收到任何错误。

© www.soinside.com 2019 - 2024. All rights reserved.