说明和示意
可通过滑屏或键盘上的方向键控制角色在平面内上下左右移动。
![](https://img.haomeiwen.com/i10492731/acc87e1582c1f853.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;
}
}
网友评论