unity手柄事件(VRTK_ControllerEvents)參數(shù)

Controller Events 腳本用于統(tǒng)一處理Vive手柄發(fā)送的事件.

Controller Events 腳本掛載在[CameraRig] 預(yù)置件下的Controller 子對(duì)象上抓半,為手柄上每個(gè)按鈕的觸發(fā)提供事件監(jiān)聽(tīng) (包括menu按鈕).
  當(dāng)手柄上某個(gè)按鈕被按下, 腳本會(huì)發(fā)送一個(gè)事件负蚊, 通知其他腳本這個(gè)點(diǎn)擊事件眨层,而具體的點(diǎn)擊邏輯并不需要寫在Controller Events腳本里面. 當(dāng)一個(gè)按鈕被釋放, 腳本同樣會(huì)發(fā)送一個(gè)事件通知其他腳本這個(gè)按鈕被釋放了.
  這個(gè)腳本也有各個(gè)按鈕相應(yīng)的public boolean屬性以便其他腳本獲取到所需按鈕的當(dāng)前狀態(tài),例如是否釋放,是否點(diǎn)擊等.

Inspector可見(jiàn)參數(shù)

unity手柄事件(VRTK_ControllerEvents)前鹅,在unity中与涡,可以通過(guò)下拉列表,指定這些行為的對(duì)應(yīng)按鈕是什么魏蔗?

· Pointer Toggle Button: 這個(gè)按鈕用于控制一束激光指示線開(kāi)/關(guān).
· Pointer Set Button: 這個(gè)按鈕用于設(shè)置指示線的目標(biāo)標(biāo)記.
· Grab Toggle Button: 這個(gè)按鈕用于控制抓取游戲中的物體.
· Use Toggle Button: 這個(gè)按鈕用于使用游戲中的物體.
· UI Click Button: 這個(gè)按鈕用于點(diǎn)擊UI元素.
· Menu Toggle Button:這個(gè)按鈕用于點(diǎn)擊彈出游戲內(nèi)置按鈕.
· Axis Fidelity: 坐標(biāo)變化的精度, 默認(rèn)為1. 大于2的數(shù)字將會(huì)導(dǎo)致過(guò)于靈敏的結(jié)果.

變量

· public bool triggerPressed - 當(dāng)trigger被扣下一半左右時(shí)為真.
· public bool triggerTouched - 當(dāng)trigger被扣下一點(diǎn)點(diǎn)時(shí)為真.
· public bool triggerHairlinePressed - 當(dāng)trigger比任何之前扣下的程度多時(shí)為真.
· public bool triggerClicked - 當(dāng)trigger完全扣下時(shí)為真.
· public bool triggerAxisChanged - 當(dāng)trigger位置改變時(shí)為真.
· public bool applicationMenuPressed - 當(dāng)application menu被按下時(shí)為真.
· public bool touchpadPressed - 當(dāng)touchpad被按下時(shí)為真.
· public bool touchpadTouched - 當(dāng)touchpad被觸碰時(shí)為真.
· public bool touchpadAxisChanged - 當(dāng)touchpad觸碰位置改變時(shí)為真.
· public bool gripPressed - 當(dāng)grip被按下時(shí)為真.
· public bool pointerPressed - 當(dāng)別名為pointer的按鈕被按下時(shí)為真.
· public bool grabPressed - 當(dāng)別名為grab的按鈕被按下時(shí)為真.
· public bool usePressed - 當(dāng)別名為use的按鈕被按下時(shí)為真.
· public bool uiClickPressed - 當(dāng)別名為UI click的按鈕被按下時(shí)為真.
· public bool menuPressed - 當(dāng)別名為menu的按鈕被按下時(shí)為真.

事件

· TriggerPressed - 當(dāng)trigger被扣下一半左右時(shí)發(fā)送事件.
· TriggerReleased - 當(dāng)Trigger從扣下一半的狀態(tài)釋放后發(fā)送事件.
· TriggerTouchStart - 當(dāng)trigger被扣下一點(diǎn)點(diǎn)時(shí)發(fā)送事件.
· TriggerTouchEnd - 當(dāng)trigger完全沒(méi)有被扣下時(shí)發(fā)送事件.
· TriggerHairlineStart - 當(dāng)trigger扣下的程度超過(guò)了當(dāng)前的hairline閾值時(shí)發(fā)送事件.
· TriggerHairlineEnd - 當(dāng)tringger釋放程度超過(guò)了當(dāng)前的hairline閾值時(shí)發(fā)送事件.
· TriggerClicked - 當(dāng)trigger在clicked之前扣下的過(guò)程中發(fā)送事件.
· TriggerUnclicked - 當(dāng)trigger不再一直處于clicked狀態(tài)時(shí)發(fā)送事件.
· TriggerAxisChanged - 當(dāng)trigger扣下的量發(fā)生變化時(shí)發(fā)送事件.
· ApplicationMenuPressed - 當(dāng)application menu被按下時(shí)發(fā)送事件.
· ApplicationMenuReleased - 當(dāng)application menu被釋放時(shí)發(fā)送事件.
· GripPressed - 當(dāng)grip被按下時(shí)發(fā)送事件.
· GripReleased - 當(dāng)grip被釋放時(shí)發(fā)送事件.
· TouchpadPressed - 當(dāng)touchpad被按下的時(shí)候發(fā)送事件(比觸摸的按壓程度大).
· TouchpadReleased - 當(dāng)touchpad從被按下(非觸碰)的狀態(tài)下釋放時(shí)發(fā)送事件.
· TouchpadTouchStart - 當(dāng)touchpad被觸摸時(shí)發(fā)送事件 (不是點(diǎn)擊或者摁下).
· TouchpadTouchEnd - 當(dāng)touchpad不再被觸摸時(shí)發(fā)送事件.
· TouchpadAxisChanged - 當(dāng)touchpad被觸摸的點(diǎn)改變時(shí)發(fā)送事件.
· AliasPointerOn - 當(dāng)pointer toggle(別名)被按下的時(shí)候發(fā)送事件.
· AliasPointerOff - 當(dāng)pointer toggle(別名)被釋放的時(shí)候發(fā)送事件.
· AliasPointerSet - 當(dāng)pointer set(別名)被釋放時(shí)發(fā)送事件.
· AliasGrabOn - 當(dāng)grab toggle(別名)被按下的時(shí)候發(fā)送事件.
· AliasGrabOff - 當(dāng)grab toggle(別名)被釋放的時(shí)候發(fā)送事件.
· AliasUseOn - 當(dāng)use toggle(別名)被按下的時(shí)候發(fā)送事件.
· AliasUseOff - 當(dāng)use toggle(別名)被釋放時(shí)發(fā)送事件.
· AliasMenuOn - 當(dāng)menu toggle(別名)被按下時(shí)發(fā)送事件.
· AliasMenuOff - 當(dāng)menu toggle(別名)被釋放時(shí)發(fā)送事件.
· AliasUIClickOn - 當(dāng)UI click(別名)被按下時(shí)發(fā)送事件.

· AliasUIClickOff - 當(dāng)UI click(別名)被釋放時(shí)發(fā)送事件.

事件和bool狀態(tài)變量有著對(duì)應(yīng)的關(guān)系砍的,通常一個(gè)bool狀態(tài)變量會(huì)對(duì)應(yīng)至少兩個(gè)按鈕事件

事件裝載參數(shù)

public struct ControllerInteractionEventArgs
{
    public uint controllerIndex;
    public float buttonPressure;
    public Vector2 touchpadAxis;
    public float touchpadAngle;
}

· uint controllerIndex - 當(dāng)前使用設(shè)備的索引.
· float buttonPressure - 按鈕的按壓數(shù)值. 0f 到 1f.
· Vector2 touchpadAxis - touchpad被觸摸的坐標(biāo). (0,0) 到 (1,1).
· float touchpadAngle - touchpad觸摸時(shí)滑動(dòng)的角度, top為0, bottom為180,以此類推其他 . 0f 到 360f.

委托類型

public delegate void ControllerInteractionEventHandler(object sender, ControllerInteractionEventArgs e);

聲明一個(gè)委托類型莺治,參數(shù)為object和ControllerInteractionEventArgs,綁定事件時(shí)一定要傳入這兩個(gè)參數(shù)廓鞠,按鈕被按下時(shí)會(huì)通過(guò)SetButtonEvent()方法來(lái)給ControllerInteractionEventArgs e分配值.
按鈕別名

public enum ButtonAlias
 {
     Trigger_Hairline,
     Trigger_Touch,
     Trigger_Press,
     Trigger_Click,
     Grip,
     Touchpad_Touch,
     Touchpad_Press,
     Application_Menu,
     Undefined
 }

這個(gè)工具類給Vive手柄一些常用的操作取一些別名,和實(shí)際的按鈕建立映射谣旁,例如:

public ButtonAlias menuToggleButton = ButtonAlias.Application_Menu;

  這個(gè)menuToggleButton與SteamVR中的

SteamVR_Controller.ButtonMask.ApplicationMenu

對(duì)應(yīng)床佳,當(dāng)這個(gè)按鈕被按下時(shí),別名按鈕對(duì)應(yīng)的事件(如果有綁定)也會(huì)發(fā)送
和SteamVR相關(guān)的全局變量

private uint controllerIndex;
private SteamVR_TrackedObject trackedController;
private SteamVR_Controller.Device device;
private Vector2 touchpadAxis = Vector2.zero;
private Vector2 triggerAxis = Vector2.zero;
private float hairTriggerDelta;
private Vector3 controllerVelocity = Vector3.zero;
private Vector3 controllerAngularVelocity = Vector3.zero;

· controllerIndex - 手柄的索引值榄审,通過(guò)trackedController.index獲取
· trackedController - gameobject綁定的SteamVR_TrackedObject腳本
· device - 設(shè)備類砌们,通過(guò)此類獲取實(shí)際中手柄的各種數(shù)據(jù)
· touchpadAxis - 全局變量,touchpad的坐標(biāo)
· triggerAxis - 全局變量瘟判,trigger的坐標(biāo)
· hairTriggerDelta -
· controllerVelocity - 手柄運(yùn)動(dòng)的速度
· controllerAngularVelocity - 手柄旋轉(zhuǎn)的角速度
事件發(fā)送方法
  以O(shè)nTriggerPressed方法為例怨绣,其他都和這個(gè)差不多

public virtual void OnTriggerPressed(ControllerInteractionEventArgs e)
{
    if (TriggerPressed != null)
    {
        TriggerPressed(this, e);//發(fā)送事件,通知綁定此事件的腳本拷获,執(zhí)行具體的邏輯篮撑,但是此處是真正最后調(diào)用的地方
    }
}

裝載參數(shù)

private ControllerInteractionEventArgs SetButtonEvent(ref bool buttonBool, bool value, float buttonPressure)
{
    buttonBool = value;
    ControllerInteractionEventArgs e;
    e.controllerIndex = controllerIndex;
    e.buttonPressure = buttonPressure;
    e.touchpadAxis = device.GetAxis();//調(diào)用SteamVR API獲取當(dāng)前的touchpad二維坐標(biāo)
    e.touchpadAngle = CalculateTouchpadAxisAngle(e.touchpadAxis);//計(jì)算二維坐標(biāo)在圓形表盤上對(duì)應(yīng)的角度
    return e;
}

通過(guò)傳入ref bool buttonBool,可以在對(duì)ControllerInteractionEventArgs進(jìn)行裝填的同時(shí)匆瓜,把事件對(duì)應(yīng)的按鈕bool狀態(tài)進(jìn)行更新赢笨,
  例如TriggerPressed和TriggerReleased事件對(duì)應(yīng)的按鈕bool狀態(tài)是triggerPressed,當(dāng)發(fā)送TriggerPressed事件時(shí)要同時(shí)更新triggerPressed為true驮吱;發(fā)送TriggerReleased事件時(shí)要同時(shí)更新triggerPressed為false
初始化

private void Awake()
{
    trackedController = GetComponent();
    gameObject.layer = LayerMask.NameToLayer("Ignore Raycast");
}
private void Start()
{
    //獲取當(dāng)前腳本attach的Controller的index
    controllerIndex = (uint)trackedController.index;
    if (controllerIndex < uint.MaxValue)
    {
        //獲取設(shè)備
        device = SteamVR_Controller.Input((int)controllerIndex);
    }
}

一般頭顯對(duì)應(yīng)的index為0茧妒,兩個(gè)手柄分別為0和1
別名按鈕事件發(fā)送

private void EmitAlias(ButtonAlias type, bool touchDown, float buttonPressure, ref bool buttonBool)
…
        if (pointerToggleButton == type)
        {
            if (touchDown)
            {
                pointerPressed = true;
                OnAliasPointerOn(SetButtonEvent(ref buttonBool, true, buttonPressure));
            }
            else
            {
                pointerPressed = false;
                OnAliasPointerOff(SetButtonEvent(ref buttonBool, false, buttonPressure));
            }
        }
…

根據(jù)type判斷是哪個(gè)別名按鈕,最后一個(gè)參數(shù)buttonBool對(duì)應(yīng)的是非別名的按鈕bool狀態(tài)左冬,例如這個(gè)pointerToggleButton桐筏,發(fā)送事件時(shí)要把touchpadPressed狀態(tài)更新,而更新為true還是false要根據(jù)touchDown的值來(lái)判斷拇砰,上面的OnAliasPointerOn等方法和OnTriggerPressed
  值得注意的是梅忌,不同的別名對(duì)應(yīng)的可能是相同的按鈕狰腌,例如pointerToggleButton和pointerSetButton都是ButtonAlias.Touchpad_Press.
禁用事件

private void OnDisable()
{
    //在0.1s內(nèi)調(diào)用DisableEvents(),禁用所有事件發(fā)送
    Invoke("DisableEvents", 0.1f);
}
///
/// 禁用牧氮,還原琼腔,但是保存touchpad和trigger的坐標(biāo)等
///
private void DisableEvents()
{
    if (triggerPressed)
    {
        OnTriggerReleased(SetButtonEvent(ref triggerPressed, false, 0f));
        EmitAlias(ButtonAlias.Trigger_Press, false, 0f, ref triggerPressed);
    }
    ...
    triggerAxisChanged = false;
    touchpadAxisChanged = false;
    controllerIndex = (uint)trackedController.index;
    if (controllerIndex < uint.MaxValue)
    {
        device = SteamVR_Controller.Input((int)controllerIndex);
        Vector2 currentTriggerAxis = device.GetAxis(Valve.VR.EVRButtonId.k_EButton_SteamVR_Trigger);
        Vector2 currentTouchpadAxis = device.GetAxis();
        // 保存當(dāng)前的touchpad和trigger的設(shè)置.
        touchpadAxis = new Vector2(currentTouchpadAxis.x, currentTouchpadAxis.y);
        triggerAxis = new Vector2(currentTriggerAxis.x, currentTriggerAxis.y);
        hairTriggerDelta = device.hairTriggerDelta;
    }
}

這個(gè)方法應(yīng)該就是將所有事件對(duì)應(yīng)的按鈕bool狀態(tài)置為false,同時(shí)保存touchpad和trigger上的坐標(biāo)信息踱葛,但是為什么要重新獲取一次device呢丹莲?
Update()方法

private void Update()
{
    controllerIndex = (uint)trackedController.index;
    //Only continue if the controller index has been set to a sensible number
    //SteamVR 在未找到Controller時(shí)會(huì)把index置為uint最大的值
    if (controllerIndex >= uint.MaxValue)
    {
        return;
    }
    device = SteamVR_Controller.Input((int)controllerIndex);
    Vector2 currentTriggerAxis = device.GetAxis(Valve.VR.EVRButtonId.k_EButton_SteamVR_Trigger);
    Vector2 currentTouchpadAxis = device.GetAxis();
    //Trigger Pressed
    if (device.GetPressDown(SteamVR_Controller.ButtonMask.Trigger))
    {
        //發(fā)送事件,設(shè)triggerPressed為true,同時(shí)發(fā)送Trigger_Press對(duì)應(yīng)的別名按鈕事件
        OnTriggerPressed(SetButtonEvent(ref triggerPressed, true, currentTriggerAxis.x));
        EmitAlias(ButtonAlias.Trigger_Press, true, currentTriggerAxis.x, ref triggerPressed);
    }
    else if (device.GetPressUp(SteamVR_Controller.ButtonMask.Trigger))
    {
        OnTriggerReleased(SetButtonEvent(ref triggerPressed, false, 0f));
        EmitAlias(ButtonAlias.Trigger_Press, false, 0f, ref triggerPressed);
    }
    ...
    // 保存當(dāng)前trigger和touchpad狀態(tài).
    touchpadAxis = new Vector2(currentTouchpadAxis.x, currentTouchpadAxis.y);
    triggerAxis = new Vector2(currentTriggerAxis.x, currentTriggerAxis.y);
    hairTriggerDelta = device.hairTriggerDelta;
}

使用實(shí)例
  例如在VRTK_ControllerEvents_ListenerExample中


GetComponent().TriggerPressed += new ControllerInteractionEventHandler(DoTriggerPressed);
private void DoTriggerPressed(object sender, ControllerInteractionEventArgs e)
{
    DebugLogger(e.controllerIndex, "TRIGGER", "pressed", e);
}

獲取到當(dāng)前Controller綁定的VRTK_ControllerEvents腳本尸诽,為它的TriggerPressed綁定DoTriggerPressed方法甥材,在VRTK_ControllerEvents腳本中,每一幀會(huì)檢測(cè)trigger是否被按下逊谋,如果按下擂达,則發(fā)送事件

OnTriggerPressed(SetButtonEvent(ref triggerPressed, true, currentTriggerAxis.x));

然后在OnTriggerPressed方法里執(zhí)行TriggerPressed(this, e);
  此時(shí)DoTriggerPressed(this,e)被真正調(diào)用,而example腳本中無(wú)需在update中寫代碼胶滋,只需要在初始化的時(shí)候綁定事件就可以了.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末板鬓,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子究恤,更是在濱河造成了極大的恐慌俭令,老刑警劉巖,帶你破解...
    沈念sama閱讀 223,207評(píng)論 6 521
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件部宿,死亡現(xiàn)場(chǎng)離奇詭異抄腔,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)理张,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,455評(píng)論 3 400
  • 文/潘曉璐 我一進(jìn)店門赫蛇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人雾叭,你說(shuō)我怎么就攤上這事悟耘。” “怎么了织狐?”我有些...
    開(kāi)封第一講書人閱讀 170,031評(píng)論 0 366
  • 文/不壞的土叔 我叫張陵暂幼,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我移迫,道長(zhǎng)旺嬉,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 60,334評(píng)論 1 300
  • 正文 為了忘掉前任厨埋,我火速辦了婚禮邪媳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己悲酷,他們只是感情好套菜,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,322評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著设易,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蛹头。 梳的紋絲不亂的頭發(fā)上顿肺,一...
    開(kāi)封第一講書人閱讀 52,895評(píng)論 1 314
  • 那天,我揣著相機(jī)與錄音渣蜗,去河邊找鬼屠尊。 笑死,一個(gè)胖子當(dāng)著我的面吹牛耕拷,可吹牛的內(nèi)容都是我干的讼昆。 我是一名探鬼主播,決...
    沈念sama閱讀 41,300評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼骚烧,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼浸赫!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起赃绊,我...
    開(kāi)封第一講書人閱讀 40,264評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤既峡,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后碧查,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體运敢,經(jīng)...
    沈念sama閱讀 46,784評(píng)論 1 321
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,870評(píng)論 3 343
  • 正文 我和宋清朗相戀三年忠售,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了传惠。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,989評(píng)論 1 354
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡稻扬,死狀恐怖卦方,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情腐螟,我是刑警寧澤愿汰,帶...
    沈念sama閱讀 36,649評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站乐纸,受9級(jí)特大地震影響衬廷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜汽绢,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,331評(píng)論 3 336
  • 文/蒙蒙 一吗跋、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦跌宛、人聲如沸酗宋。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,814評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)蜕猫。三九已至,卻和暖如春哎迄,著一層夾襖步出監(jiān)牢的瞬間回右,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,940評(píng)論 1 275
  • 我被黑心中介騙來(lái)泰國(guó)打工漱挚, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留翔烁,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,452評(píng)論 3 379
  • 正文 我出身青樓旨涝,卻偏偏與公主長(zhǎng)得像蹬屹,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子白华,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,995評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • VRTK是由一些大神對(duì)SteamVR進(jìn)行一定的優(yōu)化后封裝出來(lái)的便捷快速VR開(kāi)發(fā)工具慨默,下面一步一步來(lái)了解這個(gè)神插件。...
    砍了那只鴨閱讀 7,289評(píng)論 3 15
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理衬鱼,服務(wù)發(fā)現(xiàn)业筏,斷路器,智...
    卡卡羅2017閱讀 134,722評(píng)論 18 139
  • OVERVIEW 控制器腳本是處理游戲控制器發(fā)出的事件的鸟赫∷馀郑控制器腳本是附在[camerarig]預(yù)制件上并為控制器...
    slyfy27閱讀 5,254評(píng)論 1 4
  • 1. 準(zhǔn)備場(chǎng)景 下載并導(dǎo)入官方Space Shooter教程的范例素材包,我們僅使用其中的模型抛蚤、材質(zhì)台谢、貼圖、Pre...
    shimmery閱讀 6,422評(píng)論 0 16
  • ¥開(kāi)啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開(kāi)一個(gè)線程岁经,因...
    小菜c閱讀 6,453評(píng)論 0 17