Unity实现的汽车方向盘转动效果[完整案例]

说明:

这是一个UI界面中操作方向盘的演示,源于一个游戏项目,仅供学习参考,其中:
1、方向盘可复原
2、Android测试能够正常操作,没有出现轴心偏离现象(测试机型Galaxy S8-分辨率:2960x1440)

注意:

如果你要使用这个脚本,应将Rect Transfrom设置成如下属性,当然,某些属性不是必须要这么设定,但至少这样做可以正常工作,作为一个案例,供参考!

1、Rect Transfrom相关属性设定
属性

2、其画布下的SteerWheel是Image类型的UI元素,图像设定为方向盘图片
方向盘
3、Game
Game属性
4、Inspector
面板

5、演示结果
测试效果

代码:

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using System.Collections;

/// <summary>
/// Steering wheel.
/// Defines the steerign wheel behaviour.
/// Original source:
/// http://forum.unity3d.com/threads/touchscreen-steering-wheel-rotation-example-mouse-supported.196741/
/// </summary>
public class SteeringWheel2D : MonoBehaviour
{
    [Tooltip("UI_Element通常它是一个Image类型的图像")]
    [Header("方向盘UI本体")]
    public Graphic UI_Element;
    [Header("方向盘最大旋转角度")]
    public float maximumSteeringAngle = 520f;
    [Header("方向盘旋转复原速度")]
    public float wheelReleasedSpeed = 700f;
    [Header("方向盘当前旋转角度")]
    public float wheelAngle = 0f;
    float wheelPrevAngle = 0f;
    bool wheelBeingHeld = false;
    RectTransform rectT;
    
    [Tooltip("centerPoint是方向盘旋转的中心,其中你应将设定UI_Element的Img图片")]
    [Header("方向盘旋转中心点")]
    public Vector2 centerPoint;

    /// <summary>
    /// Gets the clamped value.
    /// Returns a value in range [-1,1] similar to GetAxis("Horizontal")
    /// 返回旋转进度比
    /// </summary>
    /// <returns>The clamped value.</returns>
    public float GetClampedValue()
    {

        return wheelAngle / maximumSteeringAngle;
    }

    /// <summary>
    /// Gets the angle.
    /// returns the wheel angle itself without clamp operation
    /// 获取实际旋转角度(-520°~520°)
    /// </summary>
    /// <returns>The angle.</returns>
    public float GetAngle()
    {
        return wheelAngle;
    }

    /// <summary>
    /// Use this for initialization.
    /// </summary>
    void Start()
    {
        rectT = UI_Element.rectTransform;
        InitEventsSystem();
        UpdateRect();
    }

    /// <summary>
    /// Initializes the events system to catch
    /// the user movements.i.e. MouseDown/MouseDrag/MouseUp.
    /// </summary>
    void InitEventsSystem()
    {
        EventTrigger events = UI_Element.gameObject.GetComponent<EventTrigger>();

        if (events == null)
            events = UI_Element.gameObject.AddComponent<EventTrigger>();

        if (events.triggers == null)
            events.triggers = new System.Collections.Generic.List<EventTrigger.Entry>();

        EventTrigger.Entry entry = new EventTrigger.Entry();
        EventTrigger.TriggerEvent callback = new EventTrigger.TriggerEvent();
        UnityAction<BaseEventData> functionCall = new UnityAction<BaseEventData>(PressEvent);
        callback.AddListener(functionCall);
        entry.eventID = EventTriggerType.PointerDown;
        entry.callback = callback;

        events.triggers.Add(entry);

        entry = new EventTrigger.Entry();
        callback = new EventTrigger.TriggerEvent();
        functionCall = new UnityAction<BaseEventData>(DragEvent);
        callback.AddListener(functionCall);
        entry.eventID = EventTriggerType.Drag;
        entry.callback = callback;

        events.triggers.Add(entry);

        entry = new EventTrigger.Entry();
        callback = new EventTrigger.TriggerEvent();
        functionCall = new UnityAction<BaseEventData>(ReleaseEvent);
        callback.AddListener(functionCall);
        entry.eventID = EventTriggerType.PointerUp;
        entry.callback = callback;

        events.triggers.Add(entry);
    }

    /// <summary>
    /// Initializes the center point of seetring wheel transform
    /// rectangle.
    /// 初始化方向盘变换矩形的旋转中心点。
    /// </summary>
    void UpdateRect()
    {
        Vector3[] corners = new Vector3[4];
        rectT.GetWorldCorners(corners);
        for (int i = 0; i < 4; i++)
        {
            corners[i] = RectTransformUtility.WorldToScreenPoint(null, corners[i]);
        }
        Vector3 bottomLeft = corners[0];
        Vector3 topRight = corners[2];
        float width = topRight.x - bottomLeft.x;
        float height = topRight.y - bottomLeft.y;
        Rect _rect = new Rect(bottomLeft.x, topRight.y, width, height);
        centerPoint = new Vector2(_rect.x + _rect.width * 0.5f, _rect.y - _rect.height * 0.5f);
    }

    /// <summary>
    /// Update is called once per frame.
    /// Update the wheel status. If the 
    /// wheel is released, reset the rotation
    /// to initial (zero) rotation by 
    /// wheelReleasedSpeed degrees per second
    /// </summary>
    void Update()
    {
        if (!wheelBeingHeld && !Mathf.Approximately(0f, wheelAngle))
        {
            float deltaAngle = wheelReleasedSpeed * Time.deltaTime;
            if (Mathf.Abs(deltaAngle) > Mathf.Abs(wheelAngle))
                wheelAngle = 0f;
            else if (wheelAngle > 0f)
                wheelAngle -= deltaAngle;
            else
                wheelAngle += deltaAngle;
        }
        rectT.localEulerAngles = Vector3.back * wheelAngle;
    }

    /// <summary>
    /// Presses the event.
    /// Executed when mouse/finger starts touching the steering wheel.
    /// </summary>
    /// <param name="eventData">Event data.</param>
    public void PressEvent(BaseEventData eventData)
    {
        Vector2 pointerPos = ((PointerEventData)eventData).position;
        wheelBeingHeld = true;
        wheelPrevAngle = Vector2.Angle(Vector2.up, pointerPos - centerPoint);
    }

    /// <summary>
    /// Drags the event.
    /// Executed when mouse/finger is dragged over the steering wheel.
    /// Do nothing if the pointer is too close to the center of the wheel.
    /// Make sure wheel angle never exceeds maximumSteeringAngle.
    /// </summary>
    /// <param name="eventData">Event data.</param>
    public void DragEvent(BaseEventData eventData)
    {

        Vector2 pointerPos = ((PointerEventData)eventData).position;

        float wheelNewAngle = Vector2.Angle(Vector2.up, pointerPos - centerPoint);

        if (Vector2.Distance(pointerPos, centerPoint) > 20f)
        {
            if (pointerPos.x > centerPoint.x)
                wheelAngle += wheelNewAngle - wheelPrevAngle;
            else
                wheelAngle -= wheelNewAngle - wheelPrevAngle;
        }

        wheelAngle = Mathf.Clamp(wheelAngle, -maximumSteeringAngle, maximumSteeringAngle);
        wheelPrevAngle = wheelNewAngle;
    }

    /// <summary>
    /// Executed when mouse/finger stops touching the steering wheel
    /// Performs one last DragEvent, just in case
    /// </summary>
    /// <param name="eventData">Event data.</param>
    public void ReleaseEvent(BaseEventData eventData)
    {
        DragEvent(eventData);
        wheelBeingHeld = false;
    }
}

—END—

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
实现Unity VR中使用手柄控制车辆移动与转弯,可以按照以下步骤进行: 1. 在Unity中创建一个车辆模型,并将其放置在场景中。 2. 添加一个Rigidbody组件,以便车辆可以受到物理引擎的影响。 3. 添加一个WheelCollider组件,以便车辆的轮子可以与地面发生交互。 4. 创建一个新的脚本并将其附加到车辆上。在此脚本中,您可以编写一些代码来处理手柄输入,并控制车辆的移动和转弯。 5. 使用Input.GetAxis()函数获取手柄输入,然后将其映射到车辆的移动和转弯。 以下是一个示例脚本,可用于控制车辆的移动和转弯: ``` using UnityEngine; using System.Collections; public class CarController : MonoBehaviour { public float speed = 10.0f; public float turnSpeed = 50.0f; void Update () { // Get input from left joystick float moveHorizontal = Input.GetAxis("Horizontal"); float moveVertical = Input.GetAxis("Vertical"); // Move the car forward and backward transform.Translate(Vector3.forward * speed * moveVertical * Time.deltaTime); // Rotate the car left and right transform.Rotate(Vector3.up, turnSpeed * moveHorizontal * Time.deltaTime); } } ``` 在以上代码中,我们通过手柄的左摇杆来控制车辆的移动与转弯。您可以根据需要修改速度和转向速度的值。 最后,将此脚本附加到车辆上,并确保手柄已连接到VR设备上。现在,您应该可以使用手柄控制车辆在Unity VR中移动和转弯了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值