前言
最近制作类似汽车方向盘操作方式的游戏,简单分享一下实现思路,类似于操作汽车方向盘,旋转开关阀等,均可借鉴此思路。
实现思路
利用上一帧(pre)和当前帧(cur)的从中心点到移动位置求得的单位向量计算偏移的角度差,再利用叉乘求旋转的方向(顺时针(z > 0)、逆时针(z < 0))。
实现效果
实现了一个简单的拖拽和方向盘修正。
代码实现
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class Demo : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
public Image steeringWheel;
public TMP_Text _angleTxt;
private Vector2 _centerPosition;
private Vector2 _prePosition;
private Vector2 _curPosition;
private float _curAngle;
private bool _autoFix;
private const int Speed = 400;
private void Start()
{
_centerPosition = RectTransformUtility.WorldToScreenPoint(Camera.main, steeringWheel.transform.position);
}
public void OnBeginDrag(PointerEventData eventData)
{
_autoFix = false;
_prePosition = eventData.position;
}
public void OnDrag(PointerEventData eventData)
{
_curPosition = eventData.position;
var curToCenter = _curPosition - _centerPosition;
var preToCenter = _prePosition - _centerPosition;
curToCenter.Normalize();
preToCenter.Normalize();
if (_prePosition != _curPosition)
{
var newAngle = Vector2.Angle(preToCenter, curToCenter);
var crossValue = Vector3.Cross(curToCenter, preToCenter);
var isClockWise = crossValue.z > 0;
_curAngle += isClockWise ? newAngle : -newAngle;
_curAngle = Mathf.Clamp(_curAngle, -540, 540);
}
_prePosition = _curPosition;
steeringWheel.GetComponent<RectTransform>().localRotation = Quaternion.Euler(new Vector3(0, 0, -_curAngle));
_angleTxt.text = $"Rotation angle:{_curAngle}";
}
public void OnEndDrag(PointerEventData eventData)
{
_autoFix = true;
}
private void Update()
{
if (!_autoFix) return;
if(_curAngle > 0) _curAngle -= Time.deltaTime * Speed;
if(_curAngle < 0) _curAngle += Time.deltaTime * Speed;
if(_curAngle is > -1 and < 1) _curAngle = 0;
steeringWheel.GetComponent<RectTransform>().localRotation = Quaternion.Euler(new Vector3(0, 0, -_curAngle));
_angleTxt.text = $"Rotation angle:{_curAngle}";
}
}