- 实现准备工作
将白色方形在蓝色方框内拖拽移动 - 实现过程
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
public class TestRocker : MonoBehaviour {
public delegate void RockerDragDelegate(Vector3 deviation);
public event RockerDragDelegate rockerDragDelegate;
public delegate void RockerUpDelegate();
public event RockerUpDelegate rockerUpDelegate;
private Transform IntenalRocker;//内部方框
private Vector3 startIntRocter;//内部方框的初识位置
private float RockerRadius=100f;
public static TestRocker Instance;
public static TestRocker instance
{
get
{
return Instance;
}
}
private void Awake()
{
IntenalRocker = transform.Find("IntenalRocker");
Instance = this;
}
// Use this for initialization
void Start () {
AddTriggerListener(IntenalRocker.gameObject, EventTriggerType.Drag,delegate { RockerDrag(); });//注册事件
AddTriggerListener(IntenalRocker.gameObject, EventTriggerType.PointerUp, delegate { RockerUp(); });
startIntRocter = IntenalRocker.position;//初识内部方框的位置
}
// Update is called once per frame
void Update () {
}
public void RockerDrag()
{
if (Vector3.Distance(Input.mousePosition, startIntRocter) < RockerRadius)
{
IntenalRocker.position = Input.mousePosition;
}
else
{
Vector3 dis = (Input.mousePosition - startIntRocter).normalized;//向量方向归一化
IntenalRocker.position = startIntRocter + dis * RockerRadius;//有大小和方向的向量
}
if (rockerDragDelegate != null)
{
if (Vector3.Distance(Input.mousePosition, startIntRocter) > 0.5f)//开始拖拽
{
Vector3 deviation = (Input.mousePosition - startIntRocter).normalized;//拖拽产生的偏移量
rockerDragDelegate(deviation);
}
}
}
public void RockerUp()
{
if (rockerUpDelegate!=null)
{
rockerUpDelegate();
}
IntenalRocker.position = startIntRocter;//当松开时回到初始位置
}
private void AddTriggerListener(GameObject obj,EventTriggerType eventID,UnityAction<BaseEventData>action)
{
EventTrigger trigger;
if (obj.GetComponent<EventTrigger>() != null)
{
trigger = obj.GetComponent<EventTrigger>();
}
else
{
trigger = obj.AddComponent<EventTrigger>();
}
if (trigger.triggers.Count==0)//如果当前事件为空
{
trigger.triggers = new List<EventTrigger.Entry>();
}
UnityAction<BaseEventData> callBack = new UnityAction<BaseEventData>(action);
EventTrigger.Entry entry = new EventTrigger.Entry();
entry.eventID = eventID;
entry.callback.AddListener(callBack);
trigger.triggers.Add(entry);
}
}
测试
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestRockerDemo : MonoBehaviour {
// Use this for initialization
void Start () {
TestRocker.Instance.rockerDragDelegate += OnDrag;
TestRocker.Instance.rockerUpDelegate += OnUp;
}
// Update is called once per frame
void Update () {
}
private void OnDrag(Vector3 deviation)
{
Debug.Log("Begin Drag");
}
private void OnUp()
{
Debug.Log("Begin Up");
}
}
- 实现结果
更好的实现方式:【上面那个方法在实现的时候有很多bug(例如不能持续触发)】
解决方法一:IDragHandler, IPointerUpHandler, IPointerDownHandler
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class LeftFingerDrag : MonoBehaviour, IDragHandler, IPointerUpHandler, IPointerDownHandler
{
public bool FixedPos = false;
[SerializeField] private Image _leftBac;
private Vector2 _LeftStartBac;
[SerializeField] private Image _leftInternal;
private Vector3[] _fourCornersArray = new Vector3[4];//四个锚点
private Vector3 _unNormalizedLeftInput;
private Vector3 _inputLeftVector;
public int _internalDistance = 4;
// Use this for initialization
void Start()
{
_leftBac.rectTransform.GetWorldCorners(_fourCornersArray);
_LeftStartBac = _fourCornersArray[3];
_leftBac.rectTransform.pivot = new Vector2(1, 0);
_leftBac.rectTransform.anchorMax = new Vector2(0, 0);
_leftBac.rectTransform.anchorMin = new Vector2(0, 0);
_leftBac.rectTransform.position = _LeftStartBac;
}
// Update is called once per frame
void Update()
{
}
public void OnDrag(PointerEventData eventData)
{
if (SecondSceneController.Instance.MoveMode== MoveType.None)
{
_leftInternal.rectTransform.anchoredPosition = Vector3.zero;
return;
}
//左手
if (SecondSceneController.Instance.MoveMode ==MoveType.Run)
{
Vector2 localLeftPoint = Vector2.zero;
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(_leftBac.rectTransform, eventData.position, eventData.pressEventCamera, out localLeftPoint))
{
localLeftPoint.x = 0;
localLeftPoint.y = (localLeftPoint.y) / _leftBac.rectTransform.sizeDelta.y;
_inputLeftVector = new Vector3(0, localLeftPoint.y * 2 - 1, 0);//范围
_unNormalizedLeftInput = _inputLeftVector;
_inputLeftVector = (_inputLeftVector.magnitude > 1.0f) ? _inputLeftVector.normalized : _inputLeftVector;
//移动
_leftInternal.rectTransform.anchoredPosition = new Vector3(0, _inputLeftVector.y * (_leftBac.rectTransform.sizeDelta.y / _internalDistance));
}
if (FixedPos == false)
{
if (_unNormalizedLeftInput.magnitude > _inputLeftVector.magnitude)
{
var currentPos = _leftBac.rectTransform.position;
currentPos.x = 0;
currentPos.y += eventData.delta.y;
_leftInternal.rectTransform.position = currentPos;
}
}
}
}
public void OnPointerDown(PointerEventData eventData)
{
OnDrag(eventData);
}
public void OnPointerUp(PointerEventData eventData)
{
_inputLeftVector = Vector3.zero;
_leftInternal.rectTransform.anchoredPosition = Vector2.zero;
}
public Vector3 GetLeftDirection()
{
return new Vector3(0, _inputLeftVector.y, 0);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class RightFingerDrag : MonoBehaviour, IDragHandler, IPointerUpHandler, IPointerDownHandler
{
public bool FixedPos = false;
[SerializeField] private Image _rightBac;
private Vector3 _rightStartBac;
[SerializeField] private Image _rightInternal;
private Vector3[] _fourCornersArray = new Vector3[4];//四个锚点
private Vector3 _unNormalizedRightInput;
private Vector3 _inputRightVector;
public int _internalDistance = 4;
// Use this for initialization
void Start()
{
_rightBac.rectTransform.GetWorldCorners(_fourCornersArray);
_rightStartBac = _fourCornersArray[3];
_rightBac.rectTransform.pivot = new Vector2(1, 0);
_rightBac.rectTransform.anchorMax = new Vector2(1, 0);
_rightBac.rectTransform.anchorMin = new Vector2(1, 0);
_rightBac.rectTransform.position = _rightStartBac;
}
// Update is called once per frame
void Update()
{
}
public void OnDrag(PointerEventData eventData)
{
if (SecondSceneController.Instance.MoveMode == MoveType.None)
{
_rightInternal.rectTransform.anchoredPosition = Vector3.zero;
return;
}
//右手
if (SecondSceneController.Instance.MoveMode == MoveType.Run)
{
Vector2 localRightPoint = Vector2.zero;
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(_rightBac.rectTransform, eventData.position, eventData.pressEventCamera, out localRightPoint))
{
localRightPoint.x = (localRightPoint.x) / _rightBac.rectTransform.sizeDelta.x;
localRightPoint.y = 0;
_inputRightVector = new Vector3(localRightPoint.x * 2 + 1.05f, 0, 0);
_unNormalizedRightInput = _inputRightVector;
_inputRightVector = (_inputRightVector.magnitude > 1.0f) ? _inputRightVector.normalized : _inputRightVector;
_rightInternal.rectTransform.anchoredPosition = new Vector3(_inputRightVector.x * (_rightBac.rectTransform.sizeDelta.x / _internalDistance), 0, 0);
}
if (FixedPos == false)
{
if (_unNormalizedRightInput.magnitude > _inputRightVector.magnitude)
{
var currentPos = _rightBac.rectTransform.position;
currentPos.x += eventData.delta.x;
currentPos.y = 0;
_rightInternal.rectTransform.position = currentPos;
}
}
}
}
public void OnPointerDown(PointerEventData eventData)
{
OnDrag(eventData);
}
public void OnPointerUp(PointerEventData eventData)
{
_inputRightVector = Vector3.zero;
_rightInternal.rectTransform.anchoredPosition = Vector2.zero;
}
public Vector3 GetRightDirection()
{
return new Vector3(_inputRightVector.x, 0, 0);
}
}
玩家自身:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;
public class JoystickPlayer : MonoBehaviour {
[SerializeField] private LeftFingerDrag _leftDrag;
[SerializeField] private RightFingerDrag _rightDrag;
[SerializeField] private float _moveSpeed = 4.0f;
[SerializeField] private float _rotationSpeed = 3.0f;
[SerializeField] private Animator _boyAni;
private Vector3 _leftInput;
private Vector3 _rightInput;
private void Awake()
{
}
private void Start()
{
}
private void FixedUpdate()
{
_leftInput = _leftDrag.GetLeftDirection();
_rightInput = _rightDrag.GetRightDirection();
Vector3 moveDirection =Vector3.forward * _leftInput.y;
float rotateDirection = _rightInput.x;
_boyAni.transform.Translate(moveDirection * _moveSpeed);
_boyAni.transform.Rotate(0f, _rotationSpeed * rotateDirection, 0f);
}
}
这个主要功能。左手控制前后移动,右手控制左右旋转,具体其他实现,可以修改代码
解决方法二、复杂的实现中,用插件吧,真的可以帮你减少很多bug