美文网首页
Unity2D中,控制角色移动

Unity2D中,控制角色移动

作者: 全新的饭 | 来源:发表于2023-10-31 10:51 被阅读0次

说明和示意

可通过滑屏或键盘上的方向键控制角色在平面内上下左右移动。


2D角色移动示意.gif

思路

TouchScreenSys:在开始触屏、滑屏、停止触屏时发出相应事件。
PlayerMove:通过设置刚体的速度来控制角色移动。
PlayerMoveCtr:通过滑屏或键盘方向键来控制PlayerMove
CamFollowCtr:相机跟随玩家角色移动
Test:实现简单的游戏流程,测试玩家移动功能

具体实现

TouchScreenSys.cs

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;

public class TouchScreenSys : MonoBehaviour, IPointerDownHandler, IDragHandler, IPointerUpHandler
{
    private int _curId;
    private const int DefaultId = -100;

    public event Action<Vector2> BeginDragEvent;
    public event Action<Vector2> DragEvent;
    public event Action<Vector2> EndDragEvent;

    public void Init()
    {
        ResetId();
    }
    public void MyDestroy()
    {

    }

    public void OnPointerDown(PointerEventData eventData)
    {
        if (_curId == DefaultId)
        {
            _curId = eventData.pointerId;
            BeginDragEvent?.Invoke(eventData.position);
            // Debug.Log("按下:" + eventData.position);
        }
    }

    public void OnDrag(PointerEventData eventData)
    {
        if (_curId != DefaultId)
        {
            DragEvent?.Invoke(eventData.position);
            // Debug.Log("滑动:" + eventData.position);
        }
    }

    public void OnPointerUp(PointerEventData eventData)
    {
        if (_curId != DefaultId)
        {
            EndDragEvent?.Invoke(eventData.position);
            ResetId();
            // Debug.Log("抬起:" + eventData.position);
        }
    }

    private void ResetId()
    {
        _curId = DefaultId;
    }
}

PlayerMove.cs

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// 通过设置刚体的速度来控制角色移动
public class PlayerMove : MonoBehaviour
{
    // 是角色的子节点,其right方向始终与移动方向同向
    [SerializeField]
    private Transform _dirTrans;
    [SerializeField]
    private Rigidbody2D _rb;

    [SerializeField]
    private float _moveSpeed = 5f;

    public event Action StartMoveEvent;
    public event Action StopMoveEvent;

    public bool IsInMove => _rb.velocity != Vector2.zero;
    public Vector2 Pos { get { return _rb.position; } }

    public void Init()
    {

    }

    public void MyDestroy()
    {

    }
    public void Move(Vector2 dir)
    {
        if (!IsInMove)
        {
            StartMoveEvent?.Invoke();
        }

        _rb.velocity = dir * _moveSpeed;
        _dirTrans.right = dir;
    }
    public void StopMove()
    {
        if (IsInMove)
        {
            _rb.velocity = Vector2.zero;
            StopMoveEvent?.Invoke();
        }

    }
}

PlayerMoveCtr.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// 通过滑屏或键盘方向键来控制角色移动
public class PlayerMoveCtr
{
    private TouchScreenSys _touchScreenSys;
    private PlayerMove _playerMove;

    public bool UseKeyboard { get; set; } = false;

    public PlayerMoveCtr(TouchScreenSys touchScreenSys, PlayerMove playerMove)
    {
        _touchScreenSys = touchScreenSys;
        _touchScreenSys.BeginDragEvent += OnPointerDown;
        _touchScreenSys.DragEvent += OnPointerDrag;
        _touchScreenSys.EndDragEvent += OnPointerUp;

        _playerMove = playerMove;
    }

    public void MyDestroy()
    {
        _playerMove = null;
        if (_touchScreenSys != null)
        {
            _touchScreenSys.BeginDragEvent -= OnPointerDown;
            _touchScreenSys.DragEvent -= OnPointerDrag;
            _touchScreenSys.EndDragEvent -= OnPointerUp;
            _touchScreenSys = null;
        }
    }

    #region 触屏控制
    private Vector2 _curCenterPos;
    private void OnPointerDown(Vector2 pos)
    {
        _curCenterPos = pos;
    }

    private void OnPointerDrag(Vector2 pos)
    {
        var curDir = (pos - _curCenterPos).normalized;
        Move(curDir);
    }
    private void OnPointerUp(Vector2 pos)
    {
        _playerMove.StopMove();
    }
    private void Move(Vector2 dir)
    {
        if (dir == Vector2.zero)
        {
            if (_playerMove.IsInMove)
            {
                _playerMove.StopMove();
            }
        }
        else
        {
            _playerMove.Move(dir);
        }
    }
    #endregion

    #region 键盘方向键控制
    public void MyUpdate()
    {
        if (UseKeyboard)
        {
            var curDir = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical")).normalized;
            Move(curDir);
        }
    }
    #endregion
}

CamFollowCtr.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CamFollowCtr
{
    private Transform _camTrans;
    private Transform _target;
    private Vector3 _offset;

    private float _moveSpeed = 10;
    private Vector3 TargetPos { get { return _target.position - _offset; } }

    public CamFollowCtr(Transform camTrans, Transform target)
    {
        _camTrans = camTrans;
        _target = target;
        _offset = _target.position - _camTrans.position;
    }
    public void MyDestroy()
    {
        _camTrans = null;
        _target = null;
    }

    // 如果在Update中调用,则factor是Time.deltaTime;如果在FixedUpdate中调用,则factor是Time.fixedDeltaTime
    public void Follow(float factor)
    {
        _camTrans.position = Vector3.Lerp(_camTrans.position, TargetPos, _moveSpeed * factor);
    }
}

Test.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;


// 实现简单的游戏流程,测试玩家移动功能
public class Test : MonoBehaviour
{
    // 根据该开关的值来决定是否使用键盘控制
    [SerializeField]
    private Toggle _toggle;

    private TouchScreenSys _touchScreenSys;
    private PlayerMove _playerMove;
    private PlayerMoveCtr _playerMoveCtr;
    private CamFollowCtr _camFollowCtr;

    private void Start()
    {
        Init();
    }

    private void Update()
    {
        MyUpdate();
    }

    private void FixedUpdate()
    {
        MyFixedUpdate();
    }

    private void OnDestroy()
    {
        MyDestroy();
    }

    private void Init()
    {
        _touchScreenSys = FindObjectOfType<TouchScreenSys>();
        _touchScreenSys.Init();
        _playerMove = FindObjectOfType<PlayerMove>();
        _playerMove.Init();
        _playerMoveCtr = new PlayerMoveCtr(_touchScreenSys, _playerMove)
        {
            UseKeyboard = _toggle.isOn
        };
        _camFollowCtr = new CamFollowCtr(Camera.main.transform, _playerMove.transform);

        _toggle.onValueChanged.AddListener(OnToggleValueChanged);
    }

    private void MyUpdate()
    {
        _playerMoveCtr.MyUpdate();

    }

    private void MyFixedUpdate()
    {
        _camFollowCtr.Follow(Time.fixedDeltaTime);
    }

    private void MyDestroy()
    {
        _toggle.onValueChanged.RemoveListener(OnToggleValueChanged);

        _camFollowCtr.MyDestroy();
        _camFollowCtr = null;
        _playerMoveCtr.MyDestroy();
        _playerMoveCtr = null;
        _playerMove?.MyDestroy();
        _playerMove = null;
        _touchScreenSys?.MyDestroy();
        _touchScreenSys = null;
    }

    private void OnToggleValueChanged(bool isOn)
    {
        _playerMoveCtr.UseKeyboard = isOn;
    }
}

相关文章

网友评论

      本文标题:Unity2D中,控制角色移动

      本文链接:https://www.haomeiwen.com/subject/afbiidtx.html