Unity引擎开发:VR控制器开发_(2).VR控制器硬件介绍与适配

VR控制器硬件介绍与适配

在虚拟现实(VR)游戏中,控制器是玩家与虚拟世界进行交互的主要工具。不同的VR平台(如Oculus、HTC Vive、Windows Mixed Reality等)使用不同的控制器硬件,因此在开发VR游戏时,适配多种控制器是一个重要的环节。本节将详细介绍如何在Unity引擎中适配不同类型的VR控制器,并提供具体的代码示例。

1. VR控制器硬件概述

1.1 主流VR控制器

目前市面上主流的VR控制器包括但不限于以下几种:

  • Oculus Touch:Oculus Rift和Quest系列头显的控制器。

  • HTC Vive Wands:HTC Vive系列头显的控制器。

  • Windows Mixed Reality Controllers:Windows Mixed Reality头显的控制器。

  • Valve Index Controllers:Valve Index头显的控制器。

  • PS VR Move:PlayStation VR头显的控制器。

1.2 控制器功能与特点

每种控制器都有其独特的功能和特点,例如:

  • Oculus Touch:具有触控板、扳机键、摇杆和按钮等多种输入方式,支持手势识别。

  • HTC Vive Wands:具有触控板、扳机键、按钮和轨迹球,支持手势识别。

  • Windows Mixed Reality Controllers:具有触控板、扳机键和按钮,支持手势识别。

  • Valve Index Controllers:具有高度灵敏的手指追踪、触控板和按钮,支持手势识别。

  • PS VR Move:具有触控板、扳机键、按钮和运动追踪,支持手势识别。

2. Unity中的VR控制器适配

2.1 VR输入系统概述

Unity引擎提供了多种方式来处理VR控制器的输入。从Unity 2019.3开始,推荐使用Input System包来处理输入,因为它更加灵活和强大。然而,对于旧版本的Unity,通常使用Legacy Input System

2.2 Legacy Input System

2.2.1 基本输入处理

Legacy Input System通过Input.GetAxisInput.GetButton等方法来处理控制器输入。以下是一些常用的输入轴和按钮:

  • Oculus Touch

    • Oculus_CV1_Left_Trigger

    • Oculus_CV1_Right_Trigger

    • Oculus_CV1_Left_Grip

    • Oculus_CV1_Right_Grip

    • Oculus_CV1_Left_Primary2DAxis

    • Oculus_CV1_Right_Primary2DAxis

  • HTC Vive Wands

    • SteamVR_Actions_Click

    • SteamVR_Actions_Touchpad

    • SteamVR_Actions_Trigger

    • SteamVR_Actions_Grip

  • Windows Mixed Reality Controllers

    • WindowsMR_LeftTrigger

    • WindowsMR_RightTrigger

    • WindowsMR_LeftThumbstick

    • WindowsMR_RightThumbstick

2.2.2 示例代码

以下是一个简单的示例,展示了如何使用Legacy Input System处理Oculus Touch控制器的扳机键输入,使虚拟手抓取物体:


using UnityEngine;



public class OculusTouchGrab : MonoBehaviour

{

    // 抓取距离

    public float grabDistance = 1.5f;

    // 抓取物体的标签

    public string grabTag = "Grabbable";



    // 左手控制器

    private OVRInput.Controller leftController = OVRInput.Controller.LTouch;

    // 右手控制器

    private OVRInput.Controller rightController = OVRInput.Controller.RTouch;



    // 当前抓取的物体

    private GameObject heldObject;



    void Update()

    {

        // 检查左手扳机键是否按下

        if (OVRInput.Get(OVRInput.Button.PrimaryIndexTrigger, leftController))

        {

            HandleGrab(leftController);

        }

        else if (heldObject != null && OVRInput.Get(OVRInput.Button.PrimaryIndexTrigger, leftController) == false)

        {

            HandleRelease(leftController);

        }



        // 检查右手扳机键是否按下

        if (OVRInput.Get(OVRInput.Button.PrimaryIndexTrigger, rightController))

        {

            HandleGrab(rightController);

        }

        else if (heldObject != null && OVRInput.Get(OVRInput.Button.PrimaryIndexTrigger, rightController) == false)

        {

            HandleRelease(rightController);

        }

    }



    void HandleGrab(OVRInput.Controller controller)

    {

        // 获取控制器位置

        Vector3 controllerPosition = OVRInput.GetLocalControllerPosition(controller);

        // 获取控制器方向

        Quaternion controllerRotation = OVRInput.GetLocalControllerRotation(controller);



        // 射线检测

        RaycastHit hit;

        if (Physics.Raycast(controllerPosition, controllerRotation * Vector3.forward, out hit, grabDistance))

        {

            // 检查击中的物体是否可抓取

            if (hit.collider.CompareTag(grabTag))

            {

                heldObject = hit.collider.gameObject;

                // 设置物体为子对象

                heldObject.transform.SetParent(this.transform);

                // 重置物体的位置和旋转

                heldObject.transform.localPosition = Vector3.zero;

                heldObject.transform.localRotation = Quaternion.identity;

            }

        }

    }



    void HandleRelease(OVRInput.Controller controller)

    {

        if (heldObject != null)

        {

            // 释放物体

            heldObject.transform.SetParent(null);

            heldObject = null;

        }

    }

}

2.3 Input System

2.3.1 安装Input System包
  1. 打开Unity Hub,选择您的项目。

  2. 点击“打开”按钮进入Unity编辑器。

  3. 转到Window > Package Manager

  4. 在搜索框中输入Input System

  5. 点击Install按钮安装Input System包。

2.3.2 配置Input System

安装完成后,需要在项目中启用Input System:

  1. 转到Edit > Project Settings > Player

  2. Other Settings中找到Active Input Handling

  3. 选择BothInput System (Preview)

2.3.3 基本输入处理

Input System通过InputAction来处理控制器输入。首先,需要创建一个输入动作(Input Action):

  1. 转到Window > Input System > Input Actions

  2. 点击New Input Action按钮。

  3. 命名输入动作,例如Grab

  4. Bindings中添加控制器输入,例如LeftHand/TriggerRightHand/Trigger

2.3.4 示例代码

以下是一个使用Input System处理Oculus Touch控制器扳机键输入的示例,使虚拟手抓取物体:


using UnityEngine;

using UnityEngine.InputSystem;



public class InputSystemGrab : MonoBehaviour

{

    // 抓取距离

    public float grabDistance = 1.5f;

    // 抓取物体的标签

    public string grabTag = "Grabbable";



    // 左手控制器输入

    private InputAction leftTrigger;

    // 右手控制器输入

    private InputAction rightTrigger;



    // 当前抓取的物体

    private GameObject heldObject;



    void Awake()

    {

        // 加载输入动作

        leftTrigger = new InputAction("LeftTrigger", binding: "<Oculus>/lefthand/trigger");

        rightTrigger = new InputAction("RightTrigger", binding: "<Oculus>/hand/trigger");

    }



    void OnEnable()

    {

        // 启用输入动作

        leftTrigger.Enable();

        rightTrigger.Enable();

    }



    void OnDisable()

    {

        // 禁用输入动作

        leftTrigger.Disable();

        rightTrigger.Disable();

    }



    void Update()

    {

        // 检查左手扳机键是否按下

        if (leftTrigger.ReadValue<float>() > 0.5f)

        {

            HandleGrab(leftTrigger);

        }

        else if (heldObject != null && leftTrigger.ReadValue<float>() <= 0.5f)

        {

            HandleRelease(leftTrigger);

        }



        // 检查右手扳机键是否按下

        if (rightTrigger.ReadValue<float>() > 0.5f)

        {

            HandleGrab(rightTrigger);

        }

        else if (heldObject != null && rightTrigger.ReadValue<float>() <= 0.5f)

        {

            HandleRelease(rightTrigger);

        }

    }



    void HandleGrab(InputAction trigger)

    {

        // 获取控制器位置

        Vector3 controllerPosition = trigger.bindings[0].effectiveDevice.currentControlScheme == "LeftHand" ? 

            OVRInput.GetLocalControllerPosition(OVRInput.Controller.LTouch) : 

            OVRInput.GetLocalControllerPosition(OVRInput.Controller.RTouch);



        // 获取控制器方向

        Quaternion controllerRotation = trigger.bindings[0].effectiveDevice.currentControlScheme == "LeftHand" ? 

            OVRInput.GetLocalControllerRotation(OVRInput.Controller.LTouch) : 

            OVRInput.GetLocalControllerRotation(OVRInput.Controller.RTouch);



        // 射线检测

        RaycastHit hit;

        if (Physics.Raycast(controllerPosition, controllerRotation * Vector3.forward, out hit, grabDistance))

        {

            // 检查击中的物体是否可抓取

            if (hit.collider.CompareTag(grabTag))

            {

                heldObject = hit.collider.gameObject;

                // 设置物体为子对象

                heldObject.transform.SetParent(this.transform);

                // 重置物体的位置和旋转

                heldObject.transform.localPosition = Vector3.zero;

                heldObject.transform.localRotation = Quaternion.identity;

            }

        }

    }



    void HandleRelease(InputAction trigger)

    {

        if (heldObject != null)

        {

            // 释放物体

            heldObject.transform.SetParent(null);

            heldObject = null;

        }

    }

}

3. 适配不同VR平台

3.1 适配Oculus平台

3.1.1 安装Oculus Integration包
  1. 打开Unity Hub,选择您的项目。

  2. 点击“打开”按钮进入Unity编辑器。

  3. 转到Window > Package Manager

  4. 在搜索框中输入Oculus Integration

  5. 点击Install按钮安装Oculus Integration包。

3.1.2 示例代码

以下是一个使用Oculus Integration包处理Oculus Touch控制器触控板输入的示例,使虚拟手进行交互:


using UnityEngine;

using UnityEngine.XR;

using UnityEngine.XR.Oculus;



public class OculusTouchInteraction : MonoBehaviour

{

    // 交互距离

    public float interactionDistance = 1.5f;

    // 交互物体的标签

    public string interactionTag = "Interactive";



    // 左手控制器

    private OVRInput.Controller leftController = OVRInput.Controller.LTouch;

    // 右手控制器

    private OVRInput.Controller rightController = OVRInput.Controller.RTouch;



    void Update()

    {

        // 检查左手触控板是否按下

        if (OVRInput.Get(OVRInput.Button.PrimaryThumbstick, leftController))

        {

            HandleInteraction(leftController);

        }



        // 检查右手触控板是否按下

        if (OVRInput.Get(OVRInput.Button.PrimaryThumbstick, rightController))

        {

            HandleInteraction(rightController);

        }

    }



    void HandleInteraction(OVRInput.Controller controller)

    {

        // 获取控制器位置

        Vector3 controllerPosition = OVRInput.GetLocalControllerPosition(controller);

        // 获取控制器方向

        Quaternion controllerRotation = OVRInput.GetLocalControllerRotation(controller);



        // 射线检测

        RaycastHit hit;

        if (Physics.Raycast(controllerPosition, controllerRotation * Vector3.forward, out hit, interactionDistance))

        {

            // 检查击中的物体是否可交互

            if (hit.collider.CompareTag(interactionTag))

            {

                // 调用交互对象的方法

                if (hit.collider.TryGetComponent(out InteractiveObject interactiveObject))

                {

                    interactiveObject.OnInteract();

                }

            }

        }

    }

}



// 交互对象的接口

public interface InteractiveObject

{

    void OnInteract();

}



// 交互对象的实现

public class InteractiveObjectExample : MonoBehaviour, InteractiveObject

{

    public void OnInteract()

    {

        Debug.Log("互动对象被交互了!");

        // 在这里添加具体的交互逻辑

    }

}

3.2 适配HTC Vive平台

3.2.1 安装SteamVR插件
  1. 打开Unity Hub,选择您的项目。

  2. 点击“打开”按钮进入Unity编辑器。

  3. 转到Window > Package Manager

  4. 在搜索框中输入SteamVR

  5. 点击Install按钮安装SteamVR插件。

3.2.2 示例代码

以下是一个使用SteamVR插件处理HTC Vive控制器扳机键输入的示例,使虚拟手抓取物体:


using UnityEngine;

using UnityEngine.XR;

using Valve.VR;



public class SteamVRGrab : MonoBehaviour

{

    // 抓取距离

    public float grabDistance = 1.5f;

    // 抓取物体的标签

    public string grabTag = "Grabbable";



    // 左手控制器

    private SteamVR_Action_Boolean grabAction = SteamVR_Input_GetAction<SteamVR_Action_Boolean>("Grab");

    // 右手控制器

    private SteamVR_Action_Boolean releaseAction = SteamVR_Input_GetAction<SteamVR_Action_Boolean>("Release");



    // 当前抓取的物体

    private GameObject heldObject;



    void Update()

    {

        // 检查左手扳机键是否按下

        if (grabAction.GetState(SteamVR_Input_Sources.LeftHand))

        {

            HandleGrab(SteamVR_Input_Sources.LeftHand);

        }

        else if (heldObject != null && !grabAction.GetState(SteamVR_Input_Sources.LeftHand))

        {

            HandleRelease(SteamVR_Input_Sources.LeftHand);

        }



        // 检查右手扳机键是否按下

        if (grabAction.GetState(SteamVR_Input_Sources.RightHand))

        {

            HandleGrab(SteamVR_Input_Sources.RightHand);

        }

        else if (heldObject != null && !grabAction.GetState(SteamVR_Input_Sources.RightHand))

        {

            HandleRelease(SteamVR_Input_Sources.RightHand);

        }

    }



    void HandleGrab(SteamVR_Input_Sources hand)

    {

        // 获取控制器位置

        Vector3 controllerPosition = SteamVR_Input_GetPosition(hand);

        // 获取控制器方向

        Quaternion controllerRotation = SteamVR_Input_GetRotation(hand);



        // 射线检测

        RaycastHit hit;

        if (Physics.Raycast(controllerPosition, controllerRotation * Vector3.forward, out hit, grabDistance))

        {

            // 检查击中的物体是否可抓取

            if (hit.collider.CompareTag(grabTag))

            {

                heldObject = hit.collider.gameObject;

                // 设置物体为子对象

                heldObject.transform.SetParent(this.transform);

                // 重置物体的位置和旋转

                heldObject.transform.localPosition = Vector3.zero;

                heldObject.transform.localRotation = Quaternion.identity;

            }

        }

    }



    void HandleRelease(SteamVR_Input_Sources hand)

    {

        if (heldObject != null)

        {

            // 释放物体

            heldObject.transform.SetParent(null);

            heldObject = null;

        }

    }



    // 获取控制器位置

    private Vector3 SteamVR_Input_GetPosition(SteamVR_Input_Sources hand)

    {

        return SteamVR_Input_GetHandPose(hand).headPose.pos;

    }



    // 获取控制器方向

    private Quaternion SteamVR_Input_GetRotation(SteamVR_Input_Sources hand)

    {

        return SteamVR_Input_GetHandPose(hand).headPose.rot;

    }

}

3.3 适配Windows Mixed Reality平台

3.3.1 安装Windows XR Plugin
  1. 打开Unity Hub,选择您的项目。

  2. 点击“打开”按钮进入Unity编辑器。

  3. 转到Window > Package Manager

  4. 在搜索框中输入Windows XR Plugin

  5. 点击Install按钮安装Windows XR Plugin。

3.3.2 示例代码

以下是一个使用Windows XR Plugin处理Windows Mixed Reality控制器扳机键输入的示例,使虚拟手抓取物体:


using UnityEngine;

using UnityEngine.XR;



public class WindowsMRGrab : MonoBehaviour

{

    // 抓取距离

    public float grabDistance = 1.5f;

    // 抓取物体的标签

    public string grabTag = "Grabbable";



    // 左手控制器

    private XRNode leftHand = XRNode.LeftHand;

    // 右手控制器

    private XRNode rightHand = XRNode.RightHand;



    // 当前抓取的物体

    private GameObject heldObject;



    void Update()

    {

        // 检查左手扳机键是否按下

        if (Input.GetAxis("WindowsMR_LeftTrigger") > 0.5f)

        {

            HandleGrab(leftHand);

        }

        else if (heldObject != null && Input.GetAxis("WindowsMR_LeftTrigger") <= 0.5f)

        {

            HandleRelease(leftHand);

        }



        // 检查右手扳机键是否按下

        if (Input.GetAxis("WindowsMR_RightTrigger") > 0.5f)

        {

            HandleGrab(rightHand);

        }

        else if (heldObject != null && Input.GetAxis("WindowsMR_RightTrigger") <= 0.5f)

        {

            HandleRelease(rightHand);

        }

    }



    void HandleGrab(XRNode hand)

    {

        // 获取控制器位置

        Vector3 controllerPosition = Vector3.zero;

        bool positionValid = InputTracking.GetNodeStates(new List<XRNodeState>()).Find(x => x.nodeType == hand).TryGetPosition(out controllerPosition);

        // 获取控制器方向

        Quaternion controllerRotation = Quaternion.identity;

        bool rotationValid = InputTracking.GetNodeStates(new List<XRNodeState>()).Find(x => x.nodeType == hand).TryGetRotation(out controllerRotation);



        if (positionValid && rotationValid)

        {

            // 射线检测

            RaycastHit hit;

            if (Physics.Raycast(controllerPosition, controllerRotation * Vector3.forward, out hit, grabDistance))

            {

                // 检查击中的物体是否可抓取

                if (hit.collider.CompareTag(grabTag))

                {

                    heldObject = hit.collider.gameObject;

                    // 设置物体为子对象

                    heldObject.transform.SetParent(this.transform);

                    // 重置物体的位置和旋转

                    heldObject.transform.localPosition = Vector3.zero;

                    heldObject.transform.localRotation = Quaternion.identity;

                }

            }

        }

    }



    void HandleRelease(XRNode hand)

    {

        if (heldObject != null)

        {

            // 释放物体

            heldObject.transform.SetParent(null);

            heldObject = null;

        }

    }

}

3.4 适配Valve Index平台

3.4.1 安装SteamVR插件
  1. 打开Unity Hub,选择您的项目。

  2. 点击“打开”按钮进入Unity编辑器。

  3. 转到Window > Package Manager

  4. 在搜索框中输入SteamVR

  5. 点击Install按钮安装SteamVR插件。

3.4.2 示例代码

以下是一个使用SteamVR插件处理Valve Index控制器扳机键输入的示例,使虚拟手抓取物体:


using UnityEngine;

using UnityEngine.XR;

using Valve.VR;



public class ValveIndexGrab : MonoBehaviour

{

    // 抓取距离

    public float grabDistance = 1.5f;

    // 抓取物体的标签

    public string grabTag = "Grabbable";



    // 左手控制器

    private SteamVR_Action_Boolean grabAction = SteamVR_Input_GetAction<SteamVR_Action_Boolean>("Grab");

    // 右手控制器

    private SteamVR_Action_Boolean releaseAction = SteamVR_Input_GetAction<SteamVR_Action_Boolean>("Release");



    // 当前抓取的物体

    private GameObject heldObject;



    void Update()

    {

        // 检查左手扳机键是否按下

        if (grabAction.GetState(SteamVR_Input_Sources.LeftHand))

        {

            HandleGrab(SteamVR_Input_Sources.LeftHand);

        }

        else if (heldObject != null && !grabAction.GetState(SteamVR_Input_Sources.LeftHand))

        {

            HandleRelease(SteamVR_Input_Sources.LeftHand);

        }



        // 检查右手扳机键是否按下

        if (grabAction.GetState(SteamVR_Input_Sources.RightHand))

        {

            HandleGrab(SteamVR_Input_Sources.RightHand);

        }

        else if (heldObject != null && !grabAction.GetState(SteamVR_Input_Sources.RightHand))

        {

            HandleRelease(SteamVR_Input_Sources.RightHand);

        }

    }



    void HandleGrab(SteamVR_Input_Sources hand)

    {

        // 获取控制器位置

        Vector3 controllerPosition = SteamVR_Input_GetPosition(hand);

        // 获取控制器方向

        Quaternion controllerRotation = SteamVR_Input_GetRotation(hand);



        // 射线检测

        RaycastHit hit;

        if (Physics.Raycast(controllerPosition, controllerRotation * Vector3.forward, out hit, grabDistance))

        {

            // 检查击中的物体是否可抓取

            if (hit.collider.CompareTag(grabTag))

            {

                heldObject = hit.collider.gameObject;

                // 设置物体为子对象

                heldObject.transform.SetParent(this.transform);

                // 重置物体的位置和旋转

                heldObject.transform.localPosition = Vector3.zero;

                heldObject.transform.localRotation = Quaternion.identity;

            }

        }

    }



    void HandleRelease(SteamVR_Input_Sources hand)

    {

        if (heldObject != null)

        {

            // 释放物体

            heldObject.transform.SetParent(null);

            heldObject = null;

        }

    }



    // 获取控制器位置

    private Vector3 SteamVR_Input_GetPosition(SteamVR_Input_Sources hand)

    {

        return SteamVR_Input_GetHandPose(hand).headPose.pos;

    }



    // 获取控制器方向

    private Quaternion SteamVR_Input_GetRotation(SteamVR_Input_Sources hand)

    {

        return SteamVR_Input_GetHandPose(hand).headPose.rot;

    }

}

3.5 适配PS VR平台

3.5.1 安装PS VR插件
  1. 打开Unity Hub,选择您的项目。

  2. 点击“打开”按钮进入Unity编辑器。

  3. 转到Window > Package Manager

  4. 在搜索框中输入PS VR

  5. 点击Install按钮安装PS VR插件。

3.5.2 示例代码

以下是一个使用PS VR插件处理PS VR Move控制器扳机键输入的示例,使虚拟手抓取物体:


using UnityEngine;

using UnityEngine.XR;



public class PSVRGrab : MonoBehaviour

{

    // 抓取距离

    public float grabDistance = 1.5f;

    // 抓取物体的标签

    public string grabTag = "Grabbable";



    // 左手控制器

    private XRNode leftHand = XRNode.LeftHand;

    // 右手控制器

    private XRNode rightHand = XRNode.RightHand;



    // 当前抓取的物体

    private GameObject heldObject;



    void Update()

    {

        // 检查左手扳机键是否按下

        if (Input.GetAxis("PSVR_LeftTrigger") > 0.5f)

        {

            HandleGrab(leftHand);

        }

        else if (heldObject != null && Input.GetAxis("PSVR_LeftTrigger") <= 0.5f)

        {

            HandleRelease(leftHand);

        }



        // 检查右手扳机键是否按下

        if (Input.GetAxis("PSVR_RightTrigger") > 0.5f)

        {

            HandleGrab(rightHand);

        }

        else if (heldObject != null && Input.GetAxis("PSVR_RightTrigger") <= 0.5f)

        {

            HandleRelease(rightHand);

        }

    }



    void HandleGrab(XRNode hand)

    {

        // 获取控制器位置

        Vector3 controllerPosition = Vector3.zero;

        bool positionValid = InputTracking.GetNodeStates(new List<XRNodeState>()).Find(x => x.nodeType == hand).TryGetPosition(out controllerPosition);

        // 获取控制器方向

        Quaternion controllerRotation = Quaternion.identity;

        bool rotationValid = InputTracking.GetNodeStates(new List<XRNodeState>()).Find(x => x.nodeType == hand).TryGetRotation(out controllerRotation);



        if (positionValid && rotationValid)

        {

            // 射线检测

            RaycastHit hit;

            if (Physics.Raycast(controllerPosition, controllerRotation * Vector3.forward, out hit, grabDistance))

            {

                // 检查击中的物体是否可抓取

                if (hit.collider.CompareTag(grabTag))

                {

                    heldObject = hit.collider.gameObject;

                    // 设置物体为子对象

                    heldObject.transform.SetParent(this.transform);

                    // 重置物体的位置和旋转

                    heldObject.transform.localPosition = Vector3.zero;

                    heldObject.transform.localRotation = Quaternion.identity;

                }

            }

        }

    }



    void HandleRelease(XRNode hand)

    {

        if (heldObject != null)

        {

            // 释放物体

            heldObject.transform.SetParent(null);

            heldObject = null;

        }

    }

}

4. 总结

在Unity引擎中适配不同类型的VR控制器是一个复杂但必要的过程。通过了解每种控制器的功能和特点,并使用适当的输入系统(Legacy Input System或Input System),开发者可以确保游戏在多个VR平台上都能提供一致的用户体验。以上示例代码展示了如何处理Oculus Touch、HTC Vive Wands、Windows Mixed Reality Controllers、Valve Index Controllers和PS VR Move控制器的输入,使虚拟手抓取和释放物体。希望这些示例能帮助您在开发VR游戏时更好地适配多种控制器。

如果您有任何疑问或需要进一步的帮助,请查阅Unity官方文档或相关VR平台的开发指南。祝您开发顺利!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值