《SteamVR实战之PMCore》(Yanlz+Unity+XR+SteamVR+VR+AR+MR+Valve+Oculus+立钻哥哥+==)

《SteamVR实战之PMCore》

《SteamVR实战之PMCore》

版本

作者

参与者

完成日期

备注

SteamVRPro_PMCore_V01_1.0

严立钻

 

2019.04.22

 

 

 

 

 

 

##《SteamVR实战之PMCore》发布说明:

++++“SteamVR实战之PMCore”:是对“SteamVR实战之PMCore”的梳理总结;(2019年度的重点技术突破点确立为:“SteamVR”)(前面已经有了一个“V2.0”和“V2.2.0”开发指南了:https://blog.csdn.net/VRunSoftYanlz/article/details/86618187https://blog.csdn.net/VRunSoftYanlz/article/details/88784527;快速入门:https://blog.csdn.net/VRunSoftYanlz/article/details/88833579;交互系统:https://blog.csdn.net/VRunSoftYanlz/article/details/89199778;官方教程:https://blog.csdn.net/VRunSoftYanlz/article/details/89324067;传送机制:https://blog.csdn.net/VRunSoftYanlz/article/details/89390866这里重点说明一下:实战是关键,所以官方教程是重中之重,后期还会基于熟悉官方示例的基础上拓展应用到现实应用中,敬请期待!(现在实战来了,以“PMCore”为内容,那这个“PMCore”是什么东西??)

++++“SteamVR实战之PMCore”:定位在熟悉SteamVR框架和基于SteamVR实战

 

++++SteamVR2.2.0开发指南:https://blog.csdn.net/VRunSoftYanlz/article/details/88784527

++++SteamVR2.2.0快速入门:https://blog.csdn.net/VRunSoftYanlz/article/details/88833579

++++SteamVR2.2.0交互系统:https://blog.csdn.net/VRunSoftYanlz/article/details/89199778

 

 

##特别提示:此篇可作为“VR框架”来理解阅读,是一个比较好的VR实战案例参考

++++框架分类链接:https://blog.csdn.net/vrunsoftyanlz/article/category/7570175

 

 

 

##《SteamVR实战之PMCore》目录

#第一篇:PMCore目录结构

#第二篇:PMCore代码剖析

#第三篇:PMCore功能模块分析

#第四篇:PMCore的机制探索

#第五篇:立钻哥哥对PMCore的拓展

推广:【XR游戏开发QQ群:784477094

 

 

 

#第一篇:PMCore目录结构

#第一篇:PMCore目录结构

#第一篇:PMCore目录结构

++++立钻哥哥:PMCore”是立钻哥哥手中的一套基于SteamVR的源码,嗯,不是最终版本,但是基本有点脉络了,所以在“SteamVR实战”前期,以这份源码为剖析,看一下效果吧;后期会为大家奉上一个比较经典的框架源码,敬请期待

++++PMCore目录结构”当然是对这份源码的目录结构的了解;通过目录结构的熟悉,基本可以知道这份源码的层次了(不管是知识层次,还是框架意识层面的认知:到目前为止立钻哥哥也不知道其代码质量如何,那就跟着立钻哥哥来探究一下吧!)

++++A.01、Art/

++++A.02、E1/

++++A.03、E2/

++++A.04、Element/

++++A.05、Scenes/

++++A.06、StreamingAssets/

++++A.07、TextMeshPro/

++++A.08、ThirdPartyPlugins/

++++A.09、UIElement/

##A.01、Art/

##A.01、Art/

++A.01、Art/

++++立钻哥哥:Art/”这个目录下应该都是“美术”相关资源,包括:模型、特效、动画、测试场景等内容;这个目录基本是“美术团队”在维护,这样做的目的是为了提交资源不会与程序开发冲突

++++A.01.01、E1/

++++A.01.02、E2/

++++A.01.03、Effect/

++++A.01.04、Font/

++++A.01.05、Models/

++++A.01.06、Scenes/

++++A.01.07、SKY/

++++A.01.08、UI/

++++A.01.09、立钻哥哥对“Art/”的拓展

###A.01.01、E1/

###A.01.01、E1/

++A.01.01、E1/

++++立钻哥哥:E1/(\Assets\Art\E1)文件夹是“E1(实验一)”的所有资源汇总,也是有完整的目录结构的:Effect/、Materials/、Modules/、Prefabs/、Scenes/、SKY/、Textures/、UI/等

++Effect/(\Assets\Art\E1\Effect\)

++++立钻哥哥:这里应该是几个特效

++Materials/(\Assets\Art\E1\Materials\)

++++立钻哥哥:这里存放的是一些材质贴图等

++Models/(\Assets\Art\E1\Models\)

++++立钻哥哥:这里存放的是一些模型

++Prefabs/(\Assets\Art\E1\Prefabs\)

++++立钻哥哥:这里放了一些预制体,里面貌似有一个球?这个估计是用来调整环境用的

++Scenes/(\Assets\Art\E1\Scenes\)

++++立钻哥哥:这里有几个场景,应该是美术用来测试或展示效果用的

++++Assets/Art/E1/Scenes/shiyanchangjing1.unity

----\Assets\E1\Scripts\Rsk\Dismantle\DismantleLoadAndCreate.cs

//\Assets\E1\Scripts\Rsk\Dismantle\DismantleLoadAndCreate.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

 

//立钻哥哥:负责生成学习模型(模型的命名为当前实验的ID)

public class DismantleLoadAndCreate : MonoSingleton<DismantleLoadAndCreate>{

    public GameObject prefab;

 

    private void Start(){

        string path = string.Format(Exprement/DismantlePrefabs/{0}, CurrentInfo.currentExp.exp_id);

        Debug.Log(立钻哥哥:打印路径  + path);

 

        prefab = GameObject.Instantiate(Resources.Load<GameObject>(path));

        prefab.name = CurrentInfo.currentExp.exp_id;

    }

 

    public void Fun(){

    }

 

}    //立钻哥哥:public class DismantleLoadAndCreate:MonoSingleton<>{}

----\Assets\E1\Scripts\LearnProcess.cs

//\Assets\E1\Scripts\LearnProcess.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

 

public class LearnProcess : MonoBehaviour{

    void Start(){

        ProcessManager.instance.ShowButtonForLearn();

    }    //立钻哥哥:void Start(){}

}    //立钻哥哥:public class LearnProcess:MonoBehaviour{}

++++Assets/Art/E1/Scenes/wujian.unity

++SKY/(\Assets\Art\E1\SKY\)

++++立钻哥哥:这里应该是为自定义天空盒预留的

++Textures/(\Assets\Art\E1\Textures\)

++++立钻哥哥:这里存放的是一些纹理贴图

++UI(\Assets\Art\E1\UI\)

++++立钻哥哥:这里面存放一些UI元素,比如背包中物品展示切图、布局图、效果图等

###A.01.02、E2/

###A.01.02、E2/

++A.01.02、E2/(\Assets\Art\E2\)

++++立钻哥哥:E2/”和“E1/”一样是存放实验二的美术资源的

###A.01.03、Effect/

###A.01.03、Effect/

++A.01.03、Effect/

++++立钻哥哥:这里存放一些特效相关内容

++++\Assets\Art\Effect\Eri_TexMaterials\:这里存放了一些相关纹理贴图:

++++\Assets\Art\Effect\Materials\:这里存放了一些材质(球):

++++-\Assets\Art\Effect\Mesh\:这里存放了一个地面的Mesh

++++\Assets\Art\Effect\Prefabs\:这里存放了一些预制体:

++++\Assets\Art\Effect\Textures\:这里存放了一些纹理贴图:

###A.01.04、Font/

###A.01.04、Font/

++A.01.04、Font/

++++立钻哥哥:这里存放的是一些字体

###A.01.05、Models/

###A.01.05、Models/

++A.01.05、Models/

++++立钻哥哥:这里存放了一些模型

###A.01.06、Scenes/

###A.01.06、Scenes/

++A.01.06、Scenes/

++++立钻哥哥:这里是存放的是一些测试场景,主要是美术提供的

++主场景的测试效果

++++立钻哥哥:这里我们来欣赏这个场景的一些功能效果吧

++TestScript.cs(在场景中打开登录界面)

++++立钻哥哥:\Assets\E1\Scripts\Rsk\TestScript.cs

using MCS.WebApi.Models;

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using Valve.Newtonsoft.Json;

 

public class TestScript : MonoBehaviour{

    void Start(){

        UI_Manager.Instance.OpenPanel(PanelType.LogOnPanel);

    }

}    //立钻哥哥:public class TestScript:MonoBehaviour{}

 

 

 

###A.01.07、SKY/

###A.01.07、SKY/

++A.01.07、SKY/

++++立钻哥哥:这里是一个“宇宙星空”的天空盒材质和贴图

###A.01.08、UI/

###A.01.08、UI/

++A.01.08、UI/

++++立钻哥哥:这里是一些UI元素,包括:按钮、背包元素、登录面板、计时器、考核面板、确认面板、提示框、专业选择面板等

++按钮UI

++++立钻哥哥:这里有一些常用按钮的UI

++帮助面板

++++立钻哥哥:这里是一些帮助面板相关UI

++背包系统

++++立钻哥哥:这里是一些和背包系统有关的UI

++登录面板

++++立钻哥哥:这里是一些和“登录系统”相关的UI

 

++常用图标

++++立钻哥哥:这里有一些常用的通用图标UI

++计时器界面

++++立钻哥哥:这里有一个计时器界面设计UI参考

++任务考核面板

++++立钻哥哥:这里是一些任务面板和考核面板的UI设计参考

++结算面板

++++立钻哥哥:这里有一个结算面板的UI设计参考

++确认面板

++++立钻哥哥:这里有一个“确认提示框”的UI面板参考

++提示面板

++++立钻哥哥:这里有一个“提示框”的UI面板参考

++主菜单

++++立钻哥哥:这里有一个比较有趣的主菜单UI设计

++工具栏

++++立钻哥哥:这里有一个工具栏相关的UI设计

++游戏选择界面

++++立钻哥哥:这里有一个专业选择界面的UI界面参考

++辅助面板

++++立钻哥哥:这里有一个面板缩放拉近等操作的辅助UI面板设计

@@@@设计原型可查阅以下博文:

++++实验四:存储器扩展实验https://blog.csdn.net/VRunSoftYanlz/article/details/87834434

++++钻哥带您了解产品原型https://blog.csdn.net/VRunSoftYanlz/article/details/87303828

++++计算机组成原理(教材篇)https://blog.csdn.net/VRunSoftYanlz/article/details/82719129

##A.02、E1/

##A.02、E1/

++A.02、E1/(\Assets\E1\)

++++立钻哥哥:从这里“\Assets\E1\”开始就进入游戏1的代码结构了

++++A.02.01、Prefabs/

++++A.02.02、Scripts/

###A.02.01、Prefabs/

###A.02.01、Prefabs/

++A.02.01、Prefabs/

++++A.02.01.01、Resources/

++++A.02.01.02、Rsk/

++++A.02.01.03、Player_VR.prefab

++A.02.01.03、Player_VR.prefab

++++立钻哥哥:“Player_VR.prefab”是玩家预制体

++++\Assets\ThirdPartyPlugins\SteamVR\Player_VR.cs

using UnityEngine;

using UnityEngine.SceneManagement;

using UnityEngine.VR;

using System;

using DG.Tweening;

 

namespace Valve.VR.InteractionSystem{

    //立钻哥哥改写的[Player_VR]

    public class Player_VR : MonoBehaviour{

        public static Player_VR Instance;

 

        public Transform head;

        public Camera Main;

 

        [SerializeField]

        public Transform camRig;

 

        float renderScale;

 

        public GameObject leftHand;    //左手模型

        public GameObject rightHand;    //右手模型

 

        public Transform root;

 

        private void Awake(){

            Instance = this;

        }

 

        public void ReSetCamRig(){

            camRig.SetParent(root);

            camRig.transform.localEulerAngles = Vector3.zero;

            camRig.transform.localPosition = Vector3.zero;

            camRig.transform.localScale = Vector3.one;

        }

 

        public void CamRigGoto(){

            camRig.position = desPosition;

        }

 

        public void CamRigGoRoat(Vector3 roat){

            camRig.eulerAngles = roat;

        }

 

        //立钻哥哥:以头为基准移动

        //[headPositon]: 想要让头去的位置(世界坐标)

        public void HeadGoTo(Vector3 headPosition){

            if(head){

               camRig.position = headPosition - (head.position - camRig.position);

            }

        }

 

        public void HeadGoTo(Vector3 headPosition, float time, TweenCallback ac=null){

            if(head){

                Vector3 pos = headPosition - (head.positon - camRig.position);

                camRig.DOMove(pos, time).OnComplete(ac);

            }

        }

 

        //以头为基准旋转

        //[headRotation]: 头将要去的旋转(世界旋转)

        public void HeadRotate(){

            if(head){

                Vector3 deltaAngleY = new Vector3(0, (camRig.eulerAngles - head.eulerAngles).y, 0);

                camRig.rotation = headRotation * Quaternion.Euler(deltaAngleY);

            }

        }

 

        //把头移动到指定地点并且旋转到指定方向

        //[headPosition]: 想要让头去的位置;

        //[headRotation]: 头将要去到的旋转;

        //[isImmediately]: 是否瞬移(默认为否);

        //[time]: 如果不瞬移,time代表缓慢移动到目标点的时间

        public void HeadGoToAndRotate(Vector3 headPosition, Quaternion headRotation, bool isImmediately=false, float time=1f){

            HeadRotate(headRotation);

            if(isImmediately){

                HeadGoTo(headPosition);

            }else{

                HeadGoTo(headPosition, time);

            }

        }

 

    }    //立钻哥哥:public class Player_VR:MonoBehaviour{}

}    //立钻哥哥:namespace Valve.VR.InteractionSystem{}

 

++知识点01:HeadGoTo(以头为基准移动)

++++立钻哥哥:public void HeadGoTo(Vector3 headPosition){}

++++HeadGoTo(headPosition);

 

++知识点02:HeadGoTo(以头为基准移动)

++++立钻哥哥:public void HeadGoTo(Vector3 headPosition, float time, TweenCallback ac=null){}

++++HeadGoTo(headPosition, time);

 

++知识点03:HeadRotate(以头为基准旋转)

++++立钻哥哥:public void HeadRotate(Quaternion headRotation){}

++++HeadRotate(headRotation);

 

 

++“Player_VR”所有引用

++++立钻哥哥:我们来查看一下“Player_VR”这个单例都被谁使用了吧!

++++\Assets\E1\Scripts\Rsk\Dismantle\Dismantle.cs

//立钻哥哥:拆解脚本

[RequireComponent(typeof(InteractableObject))]

public class Dismantle : BaseDisintegrateAction{}

++++Player_VR playerInstance;

++++playerInstance = Player_VR.Instance;

++++\Assets\UIElment\Inventory\Scripts\InventoryContentItemBorder.cs

//立钻哥哥:背包系统

public class InventoryContentItemBorder : MonoBehaviour{}

++++InteractGrab temp = Player_VR.Instance.rightHand.GetComponentInChildren<InteractGrab>();

++++\Assets\E1\Scripts\Rsk\Dismantle\Scaling.cs

//立钻哥哥:缩放脚本:获取两手距离,用于计算当前物体的缩放程度

[RequireComponent(typeof(InteractableObject))]

public class Scaling : BaseDisintegrateAction{}

++++Player_VR playerInstance;

++++playerInstance = Player_VR.Instance;

++++\Assets\UIElment\MainMenu\Scripts\MainMenuController.cs

//立钻哥哥:主菜单控制器

public class MainMenuController : MonoSingleton<MainMenuController>{}

++++mainMenuFollowPoint.transform.position = Player_VR.Instance.transform.position;

++++mainMenuFollowPoint.transform.rotation = Player_VR.Instance.transform.rotation;

++++mainMenuFollowPoint.transform.SetParent(Player_VR.Instance.transform);

++++\Assets\ThirdPartyPlugins\OVRUI\OVRRaycaster.cs

//Extension of GraphicRaycaster to support ray casting with world space rays instead of just screen-space pointer positions.(立钻哥哥:GraphicRaycaster的扩展,支持使用世界空间射线进行光线投射,而不仅仅是屏幕空间指针的位置

[RequireComponent(typeof(Canvas))]

public class OVRRaycaster : GraphicRaycaster, IPointerEnterHandler{}

++++canvas.worldCamera = Valve.VR.InteractionSystem.Player_VR.Instance.head.GetComponent<Camera>();

OVRCameraRig rig = FindObjectOfType<OVRCameraRig>();

canvas.worldCamera = rig.centerEyeAnchor.gameObject.GetComponent<Camera>();

++++private void Raycast(PointerEventData eventData, List<RaycastResult> resultAppendList, Ray ray, bool checkForBlocking){}

++++\Assets\ThirdPartyPlugins\SteamVR\InteractionSystem\Core\Scripts\RenderModel.cs

//立钻哥哥:namespace Valve.VR.InteractionSystem{}

public class RenderModel : MonoBehaviour{}

++++handSkeleton.origin = Player_VR.Instance.root;

 

++BodyCollider.cs[Player_VR/SteamVRObjects/BodyCollider](玩家碰撞体)

++++立钻哥哥:[Purpose: Collider dangling from the players head]:(目的:碰撞器悬挂在球员的头);

++++\Assets\ThirdPartyPlugins\SteamVR\InteractionSystem\Core\Scripts\BodyCollider.cs

//Purpose: Collider dangling from the players head.(立钻哥哥:目的:碰撞器悬挂在玩家的头部.

using UnityEngine;

using System.Collections;

 

namespace Valve.VR.InteractionSystem{

    [RequireComponent(typeof(CapsuleCollider))]

    public class BodyCollider : MonoBehaviour{

        public Transform head;

        private CapsuleCollider capsuleCollider;

 

        void Awake(){

            capsuleCollider = GetComponent<CapsuleCollider>();

        }

 

        void FixedUpdate(){

            float distanceFromFloor = Vector3.Dot(head.localPosition, Vector3.up);

            capsuleCollider.height = Mathf.Max(capsuleCollider.radius, distanceFromFloor);

            transform.localPosition = head.localPosition - 0.5f * distanceFromFloor * Vector3.up;

        }

 

    }    //立钻哥哥:public class BodyCollider:MonoBehaviour{}

}    //立钻哥哥:namesapce Valve.VR.InteractionSystem{}

 

++LeftHand([Player_VR/SteamVRObjects/LeftHand])左手

++++立钻哥哥:左手(LeftHand)上挂载了很多组件,包括:SteamVR_Behaviour_Pose.csInteractDisintegrate.csInteractGrab.csInteractTouch.csInteractRaycaster.csHandController.csUITouch.cs

++++\Assets\ThirdPartyPlugins\SteamVR\Input\SteamVR_Behaviour_Pose.cs

using System;

using System.Threading;

using UnityEngine;

using UnityEngine.Events;

using Valve.VR;

 

namespace Valve.VR{

    //This component simplifies the use of Pose actions. Adding it to a gameobject will auto set that transforms position and rotation every update to match the pose. Advanced velocity estimation is handled through a buffer of the last 30 updates.(立钻哥哥:这个组件简化了姿态动作的使用。将其添加到gameobject将自动设置转换位置并在每次更新时旋转以匹配该姿态。高级速度估计是通过最近30次更新的缓冲区来处理的.

    public class SteamVR_Behaviour_Pose : MonoBehaviour{}

}    //立钻哥哥:namespace Valve.VR{}

++++\Assets\ThirdPartyPlugins\LeiJia.VR\InteractSystem\InteractDisintegrate.cs

//立钻哥哥:提供分解操作

using UnityEngine;

using Valve.VR;

namesapce YanlzXR.VR.InteractSystem{

    public class InteractDisintegrate : MonoBehaviour{}

}    //立钻哥哥:namesapace YanlzXR.VR.InteractSystem{}

++++\Assets\ThirdPartyPlugins\LeiJia.VR\InteractSystem\InteractGrab.cs

//立钻哥哥:抓握交互

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using Valve.VR;

using Valve.VR.InteractionSystem;

 

namespace YanlzXR.VR.InteractionSystem{

    public class InteractGrab : MonoBehaviour{}

}    //立钻哥哥:namespace YanlzXR.VR.InteractionSystem{}

++++\Assets\ThirdPartyPlugins\LeiJia.VR\InteractSystem\InteractTouch.cs

//立钻哥哥:触摸交互

using System.Collection;

using System.Collections.Generic;

using UnityEngine;

 

namesapce YanlzXR.VR.InteractSystem{

    public class InteractTouch : MonoBehaviour{}

}    //立钻哥哥:namespace YanlzXR.VR.InteractSystem{}

++++\Assets\ThirdPartyPlugins\LeiJia.VR\InteractSystem\InteractRaycaster.cs

//立钻哥哥:射线交互类

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

 

namespace YanlzXR.VR.InteractSystem{

    public class InteractRaycaster : MonoBehaviour{

        //立钻哥哥:射线打到的所有物体

        [HideInInspector]

        public RaycastHit[] raycastResult;

 

        //立钻哥哥:射线忽略层

        public LayerMask rayCastLayerMask = ~(1 << 0);

 

        private OVRRayTransform uiRayTransform;

 

        protected virtual void Awake(){

            uiRayTransform = GetComponent<OVRRayTransform>();

        }

 

        public virtual void GetRaycastResult(){

            raycastResult = Physics.RaycastAll(transform.position, transform.forward, 100, rayCastLayerMask);

        }

 

        private void Update(){

            if(uiRayTransform == null){

                GetRaycastReult();

            }

       }

 

    }    //立钻哥哥:public class InteractRaycaster:MonoBehaviour{}

}    //立钻哥哥:namespace YanlzXR.VR.InteractSystem{}

++++\Assets\ThirdPartyPlugins\LeiJia.VR\InteractSystem\HandController.cs

//立钻哥哥:手控制器

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using Valve.VR;

 

namespace YanlzXR.VR.InteractSystem{

    public class HandController : MonoBehaviour{

        public SteamVR_Input_Sources input_Sources;

        public GameObject renderModelPrefab;

 

        private void Start(){

            InitController();

        }

 

        private void InitController(){

            GameObject renderModelInstance = GameObject.Instantiate(renderModelPrefab);

            renderModelInstance.layer = gameObject.layer;

            renderModelInstance.tag = gameObject.tag;

            renderModelInstance.transform.parent = this.transform;

            renderModelInstance.transform.localPosition = Vector3.zero;

            renderModelInstance.transform.localRotation = Quaternion.indentity;

            renderModelInstance.transform.localScale = renderModelPrefab.transform.localScale;

 

            renderModelInstance.GetComponent<Valve.VR.InteractionSystem.RenderModel>().Show();

        }

 

    }    //立钻哥哥:public class HandController:MonoBehaviour{}

}    //立钻哥哥:namespace YanlzXR.VR.InteractSystem{}

++++\Assets\UIElment\MainMenu\Scripts\UITouch.cs

using YanlzXR.VR.InteractSystem;

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using Valve.VR;

 

public class UITouch : MonoBehaviour{

    //立钻哥哥:当前被Touch的物体

    public MainMenuInteractable currentTouchObject;

 

    public HandController handController;

    private InteractRaycaster raycaster;

 

    [HideInInspector]

    public readonly List<MainMenuInteractable> interactableObjs = new List<MainMenuInteractable>();

    public SteamVR_Action_Boolean grabAction = SteamVR_Input.GetAction<SteamVR_Action_Boolean>(InteractUI);

 

    private void Awake(){}

    private void Update(){}

    private void OnEnable(){}

    private void OnDisable(){}

 

    //立钻哥哥:处理射线打到的物体

    private void ProcessInteractObjects(){}

 

    //立钻哥哥:射线投射获取InteractObject

    protected virtual void RayCastGetInteractObject(){}

 

    protected virtual void TouchedObject(){}

    protected virtual void UnTouchObject(){}

    protected virtual void InteractDown(SteamVR_Action_Boolean fromAction, SteamVR_Input_Sources fromSource){}

    protected virtual void InteractUp(SteamVR_Action_Boolean fromAction, SteamVR_Input_Sources fromSource){}

 

}    //立钻哥哥:public class UITouch:MonoBehaviour{}

 

++ControllerHoverHighlight([Player_VR/SteamVRObjects/LeftHand/ControllerHoverHighlight])

++++立钻哥哥:[Purpose: Highlights the controller when hovering over interactables.]:用途:悬停在interactables上时突出显示控制器

++++\Assets\ThirdPartyPlugins\SteamVR\InteractionSystem\Core\Scripts\ControllerHoverHighlight.cs

//Purpose: Highlights the controller when hovering over interactables.(立钻哥哥:用途:悬停在interactables上时突出显示控制器.

using UnityEngine;

using System.Collections;

 

namespace Valve.VR.InteractionSystem{

    public class ControllerHoverHightlight : MonoBehaviour{

        public Material highLightMaterial;

        public bool fireHapticsOnHightlight = true;

        protected Hand hand;

        protected RenderModel renderModel;

        protected SteamVR_Events.Action renderModelLoadedAction;

 

        protected void Awake(){}

        protected void OnHandInitialized(int deviceIndex){}

        private void RenderModel_onControllerLoaded(){}

        protected void OnParentHandHoverBegin(Interactable other){}

        private void OnParentHandHoverEnd(Interactable other){}

        private void OnParentHandInputFocusAcquired(){}

        private void OnParentHandInputFocusLost(){}

        public void ShowHighlight(){}

        public void HideHighlight(){}

 

    }    //立钻哥哥:public class ControllerHoverHightlight:MonoBehaviour{}

}    //立钻哥哥:namespace Valve.VR.InteractionSystem{}

 

++ControllerButtonHints([Player_VR/SteamVRObjects/LeftHand/ControllerButtonHints])

++++立钻哥哥:[Purpose: Displays text and button hints on the controllers.]:用途:在控制器上显示文本和按钮提示

++++\Assets\ThirdPartyPlugins\SteamVR\InteractionSystem\Hints\Scripts\ControllerButtonHints.cs

//Purpose: Displays text and button hints on the controllers.(立钻哥哥:用途:在控制器上显示文本和按钮提示

using UnityEngine;

using System.Collections;

using System.Collections.Generic;

using UnityEngine.UI;

using System.Text;

 

namespace Valve.VR.InteractionSystem{

    public class ControllerButtonHints : MonoBehaviour{

        public Material controllerMaterial;

        public Color flashColor = new Color(1.0f, 0.557f, 0.0f);

        public GameObject textHintPrefab;

        public SteamVR_Action_Vibration hapticFlash = SteamVR_Input.GetAction<SteamVR_Action_Vibration>(Haptic);

 

        //Info for each of the buttons.(立钻哥哥:每个按钮的信息.

        private class ActionHintInfo{}

 

        private Dictionary<ISteamVR_Action_In_Source, ActionHintInfo> actionHintInfos;

        SteamVR_Events.Action renderModelLoadedAction;

        protected SteamVR_Input_Sources inputSource;

 

        void Awake(){}

        void Start(){}

        private void HintDebugLog(string msg){}

        void OnEnable(){}

        void OnDisable(){}

        private void OnParentHandInputFocusLost(){}

        public virtual void SetInputSource(SteamVR_Input_Sources newInputSource){}

 

        //Gets called when the hand has been initialized and a render model has been set.(立钻哥哥:在初始化手并设置呈现模型时调用.

        private void OnHandInitialized(int deviceIndex){}

 

        void OnRenderModelLoaded(SteamVR_RenderModel renderModel, bool succeess){}

        private IEnumerator DoInitialize(SteamVR_RenderModel renderModel){}

        private void CreateAndAddButtonInfo(ISteamVR_Action_In action, SteamVR_Input_Sources inputSource){}

        private void ComputeTextEndTransforms(){}

        private void ShowButtonHint(params ISteamVR_Action_In_Source[] actions){}

        private void HideAllButtonHints(){}

        private void HideButtonHint(params ISteamVR_Action_In_Source[] actions){}

        private bool IsButtonHintActive(ISteamVR_Action_In_Source action){}

        private IEnumerator TestButtonHints(){}

        private IEnumerator TestTextHints(){}

 

        void Update(){}

 

        private void UpdateTextHint(ActionHintInfo hintInfo){}

        private void Clear(){}

        private void ShowText(ISteamVR_Action_In_Source action, string text, bool highlightButton=true){}

        private void HideText(ISteamVR_Action_In_Source action){}

        private void HideAllText(){}

        private string GetActiveHintText(ISteamVR_Action_In_Source action){}

 

        private static ControllerButtonHints GetControllerButtonHints(Hand hand){}

        public static void ShowButtonHint(Hand hand, params ISteamVR_Action_In_Source[] actions){}

        public static void HideButtonHint(Hand hand, params ISteamVR_Action_In_Source[] actions){}

        public static void HideAllButtonHints(Hand hand){}

        pubic static bool IsButtonHintActive(Hand hand, ISteamVR_Action_In_Source action){}

        public static void ShowTextHint(Hand hand, ISteamVR_Action_In_Source action, string text, bool highlightButton=true){}

        public static void HideTextHint(Hand hand, ISteamVR_Action_In_Source action){}

        public static void HideAllTextHints(Hand hand){}

        public static string GetActiveHintText(Hand hand, ISteamVR_Action_In_Source action){}

 

    }    //立钻哥哥:public class ControllerButtonHints:MonoBehaviour{}

}    //立钻哥哥:namespace Valve.VR.InteractionSystem{}

 

++RayController([Player_VR/SteamVRObjects/LeftHand/RayController])

++++立钻哥哥:手柄上的射线控制

++++\Assets\E1\Scripts\RayController.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using YanlzXR.VR.InteractionSystem;

using UnityEngine.EventSystems;

 

public class RayController : MonoBehaviour{

    protected LineRenderer lineRenderer;

    public float lineWidth = 0.01f;

 

    public Color nonObject_Color = Color.blue;

    public Color interactable_Color = Color.green;

    public Color unInteractable_Color = Color.red;

 

    protected InteractRaycaster interactRaycaster;

    protected InteractGrab interactGrab;

    private OVRRayTransform uiRay;

 

    private void Awake(){

        GetLineRenderer();

        interactRaycaster = GetComponentInParent<InteractRaycaster>();

        uiRay = GetComponentInParent<OVRRayTransform>();

        interactGrab = GetComponentInParent<InteractGrab>();

    }

 

    void Start(){

        InitLineRender();

    }

 

    protected virtual void GetLineRenderer(){

        lineRenderer = GetComponent<LineRenderer>();

        if(lineRenderer == null){

            lineRenderer = gameObject.AddComponent<LineRenderer>();

        }

    }

 

    protected virtual void InitLineRender(){

        lineRenderer.useWorldSpace = false;

        lineRenderer.positionCount = 2;

        lineRenderer.startWidth = lineWidth;

        lineRenderer.endWithth = lineWidth;

    }

 

    private void Update(){

        UpdateLinePosition();

        UpdateLineColor();

    }

 

    protected virtual void UpdateLinePosition(){

        lineRenderer.SetPosition(0, Vector3.zero);

 

        if(OVRInputModule.currentRayCastResult.gameObject != null && uiRay && !interactGrab.GetGrabbedObject){

            lineRenderer.SetPosition(1, Vector3.forward * OVRInputModule.currentRayCastResult.distance);

        }else if(interactGrab.GetGrabbedObject()){

            lineRenderer.SetPosition(1, Vector3.forward * interactGrab.GetGrabbedObject().hitDistance);

        }else if(interactRaycaster.raycastResult != null  && interactRaycaster.raycastResult.Length > 0 && interactRaycaster.raycastResult.Length > 0){

            lineRenderer.SetPosition(1, Vector3.forward * interactRaycaster.raycastResult[0].distance);

        }else{

            lineRenderer.SetPosition(1, Vector3.forward * 1);

        }

    }    //立钻哥哥:protected virtual void UpdateLinePosition(){}

 

    protected virtual void UpdateLineColor(){

        if(OVRInputModule.currentRayCastResult.gameObject != null && uiRay){

            SetColor(interactable_Color);

            return;

        }

 

        if((interactGrab.GetGrabbedObject())){

            SetColor(interactable_Color);

            return;

        }

 

        if(interactRaycaster.raycastResult == null || interactRaycaster.raycastResult.Length == 0){

            SetColor(nonObject_Color);

            return;

        }

 

        InteractableObject obj = interactRaycaster.raycastResult[0].transform.GetComponent<InteractableObject>();

        if(obj != null && obj.isInteractable){

            SetColor(interactable_Color);

        }else{

            SetColor(unInteractable_Color);

        }

 

    }    //立钻哥哥:protected virtual void UpdateLineColor(){}

 

    public virtual void SetColor(Color color){

        lineRenderer.material.SetColor(_TintColor, color);

    }

 

}    //立钻哥哥:public class RayController:MonoBehaivour{}

 

++RightHand([Player_VR/SteamVRObjects/RightHand])右手

++++立钻哥哥:右手和左手还是有点区别的,除了共同拥有的脚本:SteamVR_Behaviour_Pose.csInteractGrab.csInteractTouch.csInteractRaycaster.csHandController.csInteractDisintegrate.csUITouch.cs外,还有个特殊的脚本:OVRRayTransform.cs

++++\Assets\ThirdPartyPlugins\OVRUI\OVRRayTransform.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

 

public class OVRRayTransform : MonoBehaviour{

    public static OVRRayTransform Instance;

    public void Awake(){

        if(Instance == null){

            Instance = this;

        }

    }

 

    public Vector3 Dir{

        get{  return transform.forward;  }

    }

 

}    //立钻哥哥:public class OVRRayTransform:MonoBehaviour{}

++++OVRRayTransform”引用:那我们来看一下这个“OVRRayTransform”这个单例都被谁使用了吧!

----\Assets\ThirdPartyPlugins\OVRUI\OVRInputModule.cs

//VR extension of PointerInputModule which supports gaze and controller pointing.(立钻哥哥:支持凝视和控制器指向的PointerInputModule的VR扩展

public class OVRInputModule : PointerInputModule{}

++++leftData.worldSpaceRay = new Ray(OVRRayTransform.Instance.transform.position, OVRRayTransform.Instance.Dir);

++++if(OVRRayTransform.Instance){}

++++YanlzXR.VR.InteractSystem.InteractRaycaster interactRaycaster = OVRRayTransform.Instance.GetComponent<YanlzXR.VR.InteractSystem.InteractRaycaster>();

++++float uiDistance = (raycast.gameObject.transform.position - OVRRayTransform.Instance.transform.position).sqrMagnitude;

++++float objectDistance = (interactRaycaster.raycastResult[0].point - OVRRayTransform.Instance.transform.position).sqrMagnitude;

++++\Assets\ThirdPartyPlugins\LeiJia.VR\InteractSystem\InteractRaycaster.cs

//立钻哥哥:射线交互

public class InteractRaycaster : MonoBehaviour{}

++++private OVRRayTransform uiRayTransform;

++++uiRayTransform = GetComponent<OVRRayTransform>();

++++\Assets\E1\Scripts\RayController.cs

//立钻哥哥:射线控制

public class RayController : MonoBehaviour{}

++++private OVRRayTransform uiRay;

++++uiRay = GetComponentInParent<OVRRayTransform>();

++++立钻哥哥:这个“OVRUI/”是什么呢?这个是从“OculusSDK”中提炼出来的好用脚本,其中主要包括“射线操作UI相关功能

----\Assets\ThirdPartyPlugins\OVRUI\OVRInputModule.cs

using System;

using System.Collections.Generic;

using Valve.VR;

 

namespace UnityEngine.EventSystems{

    //VR extension of PointerInputModule which supports gaze and controller pointing.(立钻哥哥:支持凝视和控制器指向的PointerInputModule的VR扩展.

    public class OVRInputModule : PointerInputModule{

        public Valve.VR.SteamVR_Action_Boolean confirmAction = SteamVR_Input.GetAction<SteamVR_Action_Boolean>(InteractUI, Confirm);

        public SteamVR_Input_Sources inputSource = SteamVR_Input_Sources.RightHand;

        public SteamVR_ActionSet ui_InputAction = SteamVR_Input.GetActionSet(InteractUI);

 

        protected override void Start(){}

 

        //Convenience function for cloning PointerEventData.(立钻哥哥:方便的功能克隆PointerEventData.

        protected void CopyFromTo(OVRPointerEventData @from, OVRPointerEventData @to){}

        protected new void CopyFromTo(PointerEventData @from, PointerEventData @to){}

 

        //For RectTransform, calculate its normal in world space.(立钻哥哥:对于RectTransform,计算它在世界空间中的法线.

        static Vector3 GetRectTransformNormal(RectTransform rectTransform){}

 

        //State for a pointer controlled by a world space ray. E.g. gaze pointer.(立钻哥哥:由世界空间射线控制的指针的状态。如目光指针.

        virtual protected MouseState GetGazePointerData(){}

 

        //Get state for pointer which is a pointer moving in world space across the surface of a world space canvas.(立钻哥哥:获取指针的状态,该指针在世界空间中移动,穿过世界空间画布的表面.

        protected MouseState GetCanvasPointerData(){}

 

        //New version of ShouldStartDrag implemented first in PointerInputModule. This version differs in that for ray based pointers it makes a decision about whether a drag should start based on the angular change to pointer has made so far, as seen from the camera. This also works when the world space ray is translated rather than rotated, since the beginning and end of the movement are considered as angle from the same point.(立钻哥哥:新版本的“ShouldStartDrag”首先在“PointerInputModule”中实现。这个版本的不同之处在于,对于基于光线的指针,它根据到目前为止指针的角度变化来决定是否应该开始拖动,就像从摄像机中看到的那样。当世界空间射线被平移而不是旋转时也是如此,因为运动的开始和结束被认为是从同一点出发的角度.

        private bool ShouldStartDrag(PointerEventData pointerEvent){}

 

        //The purpose of this function is to allow us to switch between using the standard IsPointerMoving method for mouse driven pointers, but to always return true when its a ray based pointer. All real-world ray-based input devices are always moving so for simplicity we just return true for them. (If PointerEventData.IsPointerMoving was virtual we could just override that in OVRRayPointerEventData.)(立钻哥哥:这个函数的目的是允许我们在使用鼠标驱动指针的标准“IsPointerMoving”方法之间进行切换,但是当它是基于光线的指针时,总是返回true。所有实际的基于ray的输入设备总是在移动,为了简单起见,我们只返回true。(如果PointerEventData.IsPointerMoving是virtual虚函数的,我们可以在“OVRRayPointerEventData”中重写它。)

        static bool IsPointerMoving(PointerEventData pointerEvent){}

 

        protected Vector2 SwipeAdjustedPosition(Vector2 originalPosition, PointerEventData pointerEvent){}

 

        //Exactly the same as the code from PointerInputModule, except that we call our own IsPointerMoving. (This would also not be necessary if PointerEventData.IsPointerMoving was virtual.)(立钻哥哥:与“PointerInputModule”中的代码完全相同,只是我们将自己的代码称为“IsPointerMoving”。(如果“PointerEventData.IsPointerMoving是virtual虚函数,也不需要这样做)

        protected override void ProcessDrag(PointerEventData pointerEvent){}

 

        //Get state of button corresponding to gaze pointer.(立钻哥哥:获取与凝视指针对应的按钮状态.

        virtual protected PointerEventData.FramePressState GetGazeButtonState(){}

 

        //Get extra scroll delta from gamepad.(立钻哥哥:从gamepad获得额外的滚动增量.

        protected Vector2 GetExtraScrollDelta(){}

 

    }    //立钻哥哥:public class OVRInputModule:PointerInputModule{}

}    //立钻哥哥:namespace UnityEngine.EventSystems{}

----\Assets\ThirdPartyPlugins\OVRUI\OVRPointerEventData.cs

using System;

using System.Text;

using UnityEngine;

using UnityEngine.Assertions;

 

namespace UnityEngine.EventSystems{

    //Extension of Unitys PointerEventData to support ray based pointing and also touchpad swiping.(立钻哥哥:Unity的“PointerEventData”的扩展,支持基于光线的指向和触摸板的滑动.

    public class OVRPointerEventData : PointerEventData{

        public OVRPointerEventData(EventSystem eventSystem) : base(eventSystem){}

 

        public Ray worldSpaceRay;

        public Vector2 swipeStart;

 

        public override string ToString(){}

 

    }    //立钻哥哥:public class OVRPointerEventData:PointerEventData{}

 

    //Static helper for OVRPointerEventData.(立钻哥哥:用于“OVRPointerEventData”的静态助手.

    public static class PointerEventDataExtension{

        public static bool IsVRPointer(this PointerEventData pointerEventData){

            return (pointerEventData is OVRPointerEventData);

        }

 

        public static Ray GetRay(this PointerEventData pointerEventData){

            OVRPointerEventData vrPointerEventData = pointerEventData as OVRPointerEventData;

            Assert.IsNotNull(vrPointerEventData);

 

            return vrPointerEventData.worldSpaceRay;

        }

 

        public static Vector2 GetSwipeStart(this PointerEventData pointerEventData){

            OVRPointerEventData vrPointerEventData = pointerEventData as OVRPointerEventData;

            Assert.IsNotNull(vrPointerEventData);

    

            return vrPointerEventData.swipeStart;

        }

 

        public static void SetSwipeStart(this PointerEventData pointerEventData, Vector2 start){

            OVRPointerEventData vrPointerEventData = pointerEventData as OVRPointerEventData;

            Assert.IsNotNull(vrPointerEventData);

 

            vrPointerEventData.swipeStart = start;

        }

 

    }    //立钻哥哥:public static class PointerEventDataExtension{}

 

}    //立钻哥哥:namespace UnityEngine.EventSystems{}

----\Assets\ThirdPartyPlugins\OVRUI\OVRRaycaster.cs

using System;

using System.Collections;

using System.Collections.Generic;

using System.Text;

using UnityEngine;

using UnityEngine.UI;

using UnityEngine.EventSystem;

using UnityEngine.Serialization;

 

//Extension of GraphicRaycaster to support ray casting with world space rays instead of just screen-space pointer positions.(立钻哥哥:扩展GraphicRaycaster来支持世界空间射线的光线投射,而不仅仅是屏幕空间指针的位置.

[RequireComponent(typeof(Canvas))]

public class OVRRaycaster : GraphicRaycaster, IPointerEnterHandler{

    [Tooltip(A world space pointer for this canvas.(立钻哥哥:这个画布的一个世界空间指针)]

    public GameObject pointer;

 

    public int sortOrder = 0;

 

    protected OVRRaycaster(){}

 

    [NonSerialized]

    private Canvas m_Canvas;

    private Canvas canvas{}

 

    public override Camera eventCamera{}

    public override int sortOrderPriority{}

    protected override void Start(){}

 

    //For the given ray, find graphics on this canvas which it intersects and are not blocked by other world objects.(立钻哥哥:对于给定的光线,在画布上找到它与之相交且不被其他世界对象阻塞的图形.

    [NonSerialized]

    private List<RaycastHit> m_RaycastResults = new List<RaycastHit>();

    private void Raycast(PointerEventData eventData, List<RaycastResult> resultAppendList, Ray ray, bool checkForBlocking){}

 

    //Performs a raycast using eventData.worldSpaceRay.(立钻哥哥:使用eventData.worldSpaceRay执行光线转换.

    public override void Raycast(PointerEventData eventData, List<RaycastResult> resultAppendList){}

 

    //Performs a raycast using the pointer object attached to this OVRRaycaster.(立钻哥哥:使用附加到此“OVRRaycaster”的指针对象执行光线转换.

    public void RaycastPointer(PointerEventData eventData, List<RaycastResult> resultAppendList){}

 

    //Perform a raycast into the screen and collect all graphics underneath it.(立钻哥哥:将光线投射到屏幕上,并收集屏幕下面的所有图形.

    [NonSerialized]

    static readonly List<RaycastHit> s_SortedGraphics = new List<RaycastHit>();

    private void GraphicRaycast(Canvas canvas, Ray ray, List<RaycastHit> results){}

 

    //Get screen position of worldPosition contained in this RaycastResult.(立钻哥哥:获取包含在这个RaycastResult中的worldPosition的屏幕位置.

    public Vector2 GetScreenPosition(RaycastResult raycastResult){}

 

    //Detects whether a ray intersects a RectTransform and if it does also returns the world position of the intersection.(立钻哥哥:检测射线是否与RectTransform相交,如果相交,则返回相交点的世界位置.

    static bool RayIntersectsRectTransform(RectTransform rectTransform, Ray ray, out Vector3 worldPos){}

 

    struct RaycastHit{

        public Graphic graphic;

        public Vector3 worldPos;

        public bool fromMouse;

    }

 

    //Is this the currently focussed Raycaster according to the InputModule.(立钻哥哥:根据InputModule,这是当前聚焦的光线吗?

    public bool IsFocussed(){}

 

    public void OnPointerEnter(PointerEventData e){

        if(e.IsVRPointer){

            //Gaze has entered this canvas. Well make it the active one so that canvas-mouse pointer can be used.(立钻哥哥:凝视进入了这幅画布。我们将它设置为活动的,这样就可以使用canvas-mouse指针了.

            OVRInputModule inputModule = EventSystem.current.currentInputModule as OVRInputModule;

            if(inputModule != null){

                inputModule.activeGraphicRaycaster = this;

            }

        }

    }    //立钻哥哥:public void OnPointerEnter(PointerEventData e){}

 

}    //立钻哥哥:public class OVRRaycaster:GraphicRaycaster,IPointerEnterHandler{}

----\Assets\ThirdPartyPlugins\OVRUI\OVRRayTransform.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

 

public class OVRRayTransform : MonoBehaviour{

    public static OVRRayTransform Instance;

    public void Awake(){

        if(Instance == null){

            Instance = this;

        }

    }

 

    public Vector3 Dir{

        get{  return transform.forward;  }

    }

 

}    //立钻哥哥:public class OVRRayTransform:MonoBehaviour{}

 

++VRCamera([Player_VR/SteamVRObjects/VRCamera])(VR摄像机)

++++立钻哥哥:VRCamera”就是VR头盔视角摄像机了呗,也就是VR的主摄像机

++++\Assets\ThirdPartyPlugins\SteamVR\Scripts\SteamVR_Fade.cs

//Purpose: CameraFade script adapted to work with SteamVR.(立钻哥哥:用途:适用于SteamVR的摄像脚本

//Usage: Add to your top level SteamVR_Camera(the one with ApplyDistoration checked) and drag a reference to this component into SteamVR_Camera RenderComponent list. Then call the static helper function SteamVR_Fade. Start with the desired color and duration. Use a duration of zero to set the start color.(立钻哥哥:用法:将“SteamVR_Camera”添加到顶层(已检查了ApplyDistoration),并将对该组件的引用拖放到“SteamVR_Camera RenderComponent”列表中。然后调用静态助手函数“SteamVR_Fade”。从想要的颜色和持续时间开始。使用持续时间为零来设置开始颜色.

//Example: Fade down from black over one second.(立钻哥哥:例子:淡出黑色超过一秒钟.

//[SteamVR_Fade.Start(Color.black, 0);]

//[SteamVR_Fade.Start(Color.clear, 1)]

//Note: This component is provided to fade out a single camera layers scene view. If instead you want to fade the entire view, use: SteamVR_Fade.View(Color.black, 1);(立钻哥哥:注意:此组件用于淡出单个相机层的场景视图。如果你想让整个视图褪色,使用:“SteamVR_Fade.View(Color)”。黑色,1);

//(Does not affect the game view, however.(立钻哥哥:不过,这并不影响游戏视图))

using UnityEngine;

using Valve.VR;

 

namespace Valve.VR{

    public class SteamVR_Fade : MonoBehaviour{

        //default starting color: black and fully transparent.(立钻哥哥:默认启动颜色:黑色和完全透明

        private Color currentColor = new Color(0, 0, 0, 0);

 

        //default target color: black and fully transparent.(立钻哥哥:默认目标颜色:黑色和完全透明

        private Color targetColor = new Color(0, 0, 0, 0);

 

        //the delta-color is basically the speed/second at which the current color should change.(立钻哥哥:delta-color基本上是当前颜色应该改变的“速度/秒”

        private Color deltaColor = new Color(0, 0, 0, 0);

 

        static public void Start(Color newColor, float duration, bool fadeOverlay=false){

            SteamVR_Events.Fade.Send(newColor, duration, fadeOverlay);

        }

 

        static public void View(Color newColor, float duration){

            var compositor = OpenVR.Compositor;

            if(compositor != null){

                compositor.FadeToColor(duration, newColor.r, newColor.g, newColor.b, newColor.a, false);

            }

        }

 

        #if TEST_FADE_VIEW

            void Update(){

                if(Input.GetKeyDown(KeyCode.Space)){

                    SteamVR_Fade.View(Color.black, 0);

                    SteamVR_Fade.View(Color.clear, 1);

                }

            }

            @@@立钻哥哥:这个已验证,效果就是“按空格键后视野黑一下”,但是在Game视图是看不见的,因为当时想截个动图给大家看一下,PC上没有显示效果,只能在头盔中体验了,还是一个比较好的功能点设计呢:类似眨眼睛,或者UI蒙版效果都可以借鉴这种设计!

        #endif

 

        public void OnStartFade(Color newColor, float duration, bool fadeOverlay){

            if(duration > 0.0f){

                targetColor = newColor;

                deltaColor = (targetColor - currentColor) / duration;

            }else{

                currentColor = newColor;

            }

        }

 

        static Material fadeMaterial = null;

        static int fadeMaterialColorID = -1;

 

        void OnEnable(){

            if(fadeMaterial == null){

                fadeMaterial = new Material(Shader.Find(Custom/SteamVR_Fade));

                fadeMaterialColorID = Shader.PropertyToID(fadeColor);

            }

 

            SteamVR_Events.Fade.Listen(OnStartFade);

            SteamVR_Events.FadeReady.Send();

        }

 

        void OnDisable(){

            SteamVR_Events.Fade.Remove(OnStartFade);

        }

 

        void OnPostRender(){

            if(currentColor != targetColor){

                //if the difference between the current alpha and the desired alpha is smaller than delta-alpha*deltaTime, then weve pretty much done fading.(立钻哥哥:如果当前alpha值和期望alpha值之间的差小于“delta-alpha*deltaTime”,那么我们基本上已经完成了衰减.

                if(Mathf.Abs(currentColor.a - targetColor.a) < Mathf.Abs(deltaColor.a) * Time.deltaTime){

                    currentColor = targetColor;

                    deltaColor = new Color(0, 0, 0, 0);

                }else{

                    currentColor += deltaColor * Time.deltaTime;

                }

 

                if(fadeOverlay){

                    var overlay = SteamVR_Overlay.instance;

                    if(overlay != null){

                        overlay.alpha = 1.0f - currentColor.a;

                    }

                }

            }    //立钻哥哥:if(currentColor != targetColor){}

 

            if(currentColor.a > 0 && fadeMaterial){

                fadeMaterial.SetColor(fadeMaterialColorID, currentColor);

                fadeMaterial.SetPass(0);

                GL.Begin(GL, QUADS);

 

                GL.Vertex3(-1, -1, 0);

                GL.Vertex3(1, -1, 0);

                GL.Vertex3(1, 1, 0);

                GL.Vertex3(-1, 1, 0);

                GL.End();

            }    //立钻哥哥:if(currentColor.a > 0 && fadeMaterial){}

 

        }    //立钻哥哥:void OnPostRender(){}

 

    }    //立钻哥哥:public class SteamVR_Fade:MonoBehaviour{}

}    //立钻哥哥:namespace Valve.VR{}

 

++Overlay([Player_VR/SteamVRObjects/Overlay])蒙版

++++立钻哥哥:Overlay”这个怎么理解呢?暂且当“蒙版”理解吧

++++\Assets\ThirdPartyPlugins\SteamVR\Scripts\SteamVR_Overlay.cs

//Purpose: Displays 2d content on a large virtual screen.(立钻哥哥:用途:在大型虚拟屏幕上显示2d内容

using UnityEngine;

using System.Collections;

using Valve.VR;

 

namespace Valve.VR{

    public class SteamVR_Overlay : MonoBehaviour{

        public Texture texture;

        public bool curved = true;

        public bool antialias = true;

        public bool highquality = true;

 

        public float scale = 3.0f;

        public float distance = 1.25f;

        public float alpha = 1.0f;

 

        public Vector4 uvOffset = new Vector4(0, 0, 1, 1);

        public Vector2 mouseScale = new Vector2(1, 1);

        public Vector2 curvedRange = new Vector3(1, 2);

 

        public VROverlayInputMethod inputMethod = VROverlayInputMethod.None;

    

        static public SteamVR_Overlay instance{  get;  private set;  }

        private ulong handle = OpenVR.k_ulOverlayHandleInvalid;

 

        void OnEnable(){}

        void OnDisable(){}

        public void UpdateOverlay(){}

        public bool PollNextEvent(ref VREvent_t pEvent){}

 

        public struct IntersectionResults{

            public Vector3 point;

            public Vector3 normal;

            public Vector2 UVs;

            public float distance;

        }    //立钻哥哥:public struct IntersectionResults{}

 

        public bool ComputeIntersection(Vector3 source, Vector3 direction, ref IntersectionResult results){}

 

    }    //立钻哥哥:public class SteamVR_Overlay:MonoBehaviour{}

}    //立钻哥哥:namespace Valve.VR{}

 

++[SteamVR]([Player_VR/SteamVRObjects/[SteamVR]])(SteamVR控制器)

++++立钻哥哥:这个“[SteamVR]”可以理解为控制器,就是一个空物体挂了几个脚本,这些脚本包括:SteamVR_Behaviour.csSteamVR_Render.csSteamVR_ActivateActionSetOnLoad.cs

++++\Assets\ThirdPartyPlugins\SteamVR\Scripts\SteamVR_Behaviour.cs

using System;

using System.Collections;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using UnityEngine;

 

#if UNITY_2017_2_OR_NEWER

    using UnityEngine.XR;

#else

    using XRSettings = UnityEngine.VR.VRSettings;

    using XRDevice = UnityEngine.VR.XRDevice;

#endif

 

namespace Valve.VR{

    public class SteamVR_Behaviour : MonoBehaviour{

        private const string openVRDeviceName = OpenVR;

        public static bool forcingInitialization = false;

 

        private static SteamVR_Behaviour _instance;

        public static SteamVR_Behaviour instance{}

 

        public bool initializeSteamVROnAwake = true;

        public bool doNotDestroy = true;

 

        [HideInInspector]

        public SteamVR_Render steamvr_render;

 

        private static bool initializing = false;

        public static void Initialize(bool forceUnityVRToOpenVR=false){}

 

        protected void Awake(){}

        public void InitializeSteamVR(bool forceUnityVRToOpenVR=false){}

 

        #if UNITY_2018_3_OR_NEWER

            private bool loadedOpenVRDeviceSuccess = false;

            private IEnumerator DoInitializeSteamVR(bool forceUnityVRToOpenVR=false){}

 

            private void XRDevice_deviceLoaded(string deviceName){}

        #else

            private IEnumerator DoInitializeSteamVR(bool forceUnityVRToOpenVR=false){}

        #endif

 

        private void EnableOpenVR(){}

        protected void PreCull(){}

        protected void FixedUpdate(){}

        protected void LateUpdate(){}

        protected void Update(){}

 

        protected void OnQuit(VREvent_t vrEvent){

            #if UNITY_EDITOR

                UnityEditor.EditorApplication.isPlaying = false;

            #else

                Application.Quit();

            #endif

        }

 

    }    //立钻哥哥:public class SteamVR_Behaviour:MonoBehaviour{}

}    //立钻哥哥:namespace Valve.VR{}

++++\Assets\ThirdPartyPlugins\SteamVR\Scripts\SteamVR_Render.cs

//Purpose: Handles rendering of all SteamVR_Cameras.(立钻哥哥:用途:处理所有SteamVR_Camera的渲染

using UnityEngine;

using System.Collectons;

using Valve.VR;

 

namespace Valve.VR{

    public class SteamVR_Render : MonoBehaviour{

        public SteamVR_ExternalCamera externalCamera;

        public string externalCameraConfigPath = externalcamera.cfg;

 

        public static EVREye eye{  get;  private set;  }

        public static SteamVR_Render instance{}

 

        static private bool isQuitting;

        void OnApplicationQuit(){}

 

        static public void Add(SteamVR_Camera vrcam){}

        static public void Remove(SteamVR_Camera vrcam){}

        static public SteamVR_Camera Top(){}

 

        private SteamVR_Camera[] cameras = new SteamVR_Camera[0];

        void AddInternal(SteamVR_Camera vrcam){}

        void RemoveInternal(SteamVR_Camera vrcam){}

        SteamVR_Camera TopInternal(){}

 

        public TrackedDevicePose_t[] poses = new TrackedDevicePose_t[OpenVR.k_unMaxTrackedDeviceCount];

        public TrackedDevicePose_t[] gamePoses = new TrackedDevicePose_t[0];

 

        static private bool _pauseRendering;

        static public bool pauseRendering{}

 

        private IEnumerator RenderLoop(){}

        void RenderExternalCamera(){}

        private void OnInputFocus(bool hadFocus){}

        private string GetScreenshotFliename(uint screenshotHandle, EVRScreenshotPropertyFilenames screenshotPropertyFilename){}

        private void OnRequestScreenshot(VREvent_t vrEvent){}

        private void OnEnable(){}

        private void OnSteamVRInitialized(bool success){}

        private void OnDisable(){}

        private void Awake(){}

        public void UpdatePoses(){}

        void Update(){}

    

    }    //立钻哥哥:public class SteamVR_Render:MonoBehaviour{}

}    //立钻哥哥:namespace Valve.VR{}

++++\Assets\ThirdPartyPlugins\SteamVR\Input\SteamVR_ActivateActionSetOnLoad.cs

using UnityEngine;

using System.Collectons;

 

namespace Valve.VR{

    //Automatically activates an action set on Start() and deactivates the set on OnDestroy(). Optionally deactivating all other sets as well.(立钻哥哥:自动激活Start()和OnDestroy()上的操作集。还可以选择停用所有其他集.

    public class SteamVR_ActivateActionSetOnLoad : MonoBehaviour{

        public SteamVR_ActionSet actionSet = SteamVR_Input.GetActionSet(default);

        public SteamVR_Input_Sources forSources = SteamVR_Input_Sources.Any;

 

        public bool disableAllOtherActionSets = false;

        public bool activateOnStart = true;

        public bool deactivateOnDestroy = true;

 

        private void Start(){

            if(actionSet != null && activateOnStart){

                //Debug.Log(string.Format(立钻哥哥:[SteamVR] Activating {0} action set., actionSet.fullPath));

                actionSet.Activate(forSources, 0, disableAllOtherActionSets);

            }

        }

 

        private void OnDestroy(){

            if(actionSet != null && deactivateOnDestroy){

                //Debug.Log(string.Format(立钻哥哥:[SteamVR] Deactivating {0} action set., actionSet.fullPath));

                actionSet.Deactivate(forSources);

            }

        }

 

    }    //立钻哥哥:public class SteamVR_ActivateActionSetOnLoad:MonoBehaviour{}

}     //立钻哥哥:namespace Valve.VR{}

 

++FallbackObjects([Player_VR/NoSteamVRFallbackObjects])备选方案物体

++++立钻哥哥:这里应该是没有“VR”设备时的备选方案,估计可以使用PC进行操作

++++\Assets\ThirdPartyPlugins\SteamVR\InteractionSystem\Core\Scripts\FallbackCameraController.cs

//Purpose: Controllers for the non-VR debug camera.(立钻哥哥:用途:用于非vr调试相机的控制器

using UnityEngine;

using System.Collections;

 

namespace Valve.VR.InteractionSystem{

    [RequireComponent(typeof(Camera))]

    public class FallbackCameraController : MonoBehaviour{

        public float speed = 4.0f;

        public float shiftSpeed = 16.0f;

        public bool showInstructions = true;

 

        private Vector3 startEulerAngles;

        private Vector3 startMousePosition;

        private float realtime;

 

        void OnEnable(){}

        void Update(){}

        void OnGUI(){}

 

        //[WASD/Arrow Keys to translate the camera.](立钻哥哥:WASD/箭头键移动相机。

        //[Right mouse click to rotate the camera.](立钻哥哥:右击鼠标可旋转相机.

        //[Left mouse click for standard interactions.](立钻哥哥:单击鼠标左键进行标准交互

 

   }    //立钻哥哥:public class FallbackCameraController:MonoBehaviour{}

}    //立钻哥哥:namespace Valve.VR.InteractionSystem{}

 

++FallbackHand([Player_VR/NoSteamVRFallbackObjects/FallbackHand])

++++立钻哥哥:这是在没有VR设备情况下,备用操作的手

++++\Assets\ThirdPartyPlugins\SteamVR\InteractionSystem\Core\Scripts\Hand.cs

//Purpose: The hands used by the player in the vr interaction system.(立钻哥哥:用途:玩家在vr交互系统中使用的手.

using UnityEngine;

using System;

using System.Collections;

using System.Collections.Generic;

using System.Collections.ObjectModel;

using UnityEngine.Events;

using System.Threading;

 

namespace Valve.VR.InteractionSystem{

    //Links with an appropriate SteamVR controller and facilitates interactions with objects in the virtual world.(立钻哥哥:链接到适当的“SteamVR”控制器,并方便与虚拟世界中的对象进行交互

    public class Hand : MonoBehaviour{

        //The flags used to determine how an object is attached to the hand.(立钻哥哥:用于确定对象如何附加到手的标志.

        [Flags]

        public enum AttachmentFlags{}

 

        public const AttachmentFlags defaultAttachmentFlags = AttachmentFlags.ParentToHand | AttachmentFlags.DetachOthers | AttachmentFlags.DetachFromOtherHand | AttachmentFlags.TurnOnKinematic | AttachmentFlags.SnapOnAttach;

 

        public Hand otherHand;

        public SteamVR_Input_Sources handType;

 

        public SteamVR_Behaviour_Pose trackedObject;

        public SteamVR_Action_Boolean grabPinchAction = SteamVR_Input.GetAction<SteamVR_Action_Boolean>(GrabPinch);

        public SteamVR_Action_Boolean grabGripAction = SteamVR_Input.GetAction<SteamVR_Action_Boolean>(GrabGrip);

        public SteamVR_Action_Vibration hapticAction = SteamVR_Input.GetAction<SteamVR_Action_Vibration>(Haptic);

        public SteamVR_Action_Boolean uiInteractAction = SteamVR_Input.GetAction<SteamVR_Action_Boolean>(InteractUI);

 

        public struct AttachedObject{

            public GameObject attachedObject;

            public Interactable interactable;

            public Rigidbody attachedRigidbody;

            public CollisionDetectionMode collisionDetectionMode;

            public bool attachedRigidbodyWasKinematic;

            public bool attachedRigidbodyUsedGravity;

            public GameObject originalParent;

            public bool isParentedToHand;

            public GrabTypes grabbedWithType;

            public AttachmentFlags attachmentFlags;

            public Vector3 initialPositionOffset;

            public Quaternion initialRotationalOffset;

            public Transform attachedOffsetTransform;

            public Transform handAttachmentPointTransform;

            public Vector3 easeSourcePosition;

            public Quaternion easeSourceRatation;

            public float attachTime;

 

            public bool HasAttachFlags(AttachmentFlags flag){

                return (attachmentFlags & flag) == flag;

            }

        }    //立钻哥哥:public struct AttachedObject{}

 

        public ReadOnlyCollection<AttachedObject> AttachedObjects;

 

        //The Interactable object this Hand is currently hovering over.(立钻哥哥:这只手当前悬停的可交互对象.

        public Interactable hoveringInteractable{}

 

        //Active GameObject attached to this Hand.(立钻哥哥:活动的GameObject附在这只手上.

        public GameObject currentAttachedObject{}

        public AttachedObject? currentAttachedObjectInfo{}

        public SteamVR_Behaviour_Skeleton skeleton{}

 

        public void ShowController(bool permanent = false){}

        public void HideController(bool permanent = false){}

        public void ShowSkeleton(bool permanent = false){}

        public void HideSkeleton(bool permanent = false){{}

        public bool HasSkeleton(){}

        public void Show(){}

        public void Hide(){}

        public void SetVisibility(bool visible){}

        public void SetSkeletonRangeOfMotion(EVRSkeletalMotionRange newRangeOfMotion, float blendOverSeconds=0.1f){}

        public void SetTemporarySkeletonRangeOfMotion(SkeletalMotionRangeChange temporaryRangeOfMotionChange, float blendOverSeconds=0.1f){}

        public void ResetTemporarySkeletonRangeOfMotion(float blendOverSeconds=0.1f){}

        public void SetAnimationState(int stateValue){}

        public void StopAnimation(){}

 

        //Attach a GameObject to this GameObject.(立钻哥哥:将GameObject(游戏物体)附加到这个GameObject(游戏物体)上.

       //[objectToAttach]: The GameObject to attach.(立钻哥哥:[objectToAttach]:要附加的GameObject.

       //[flags]: The flags to use for attaching the object.(立钻哥哥:[flags]:用于附加对象的标志.

       //[attachmentPoint]: Name of the GameObject in the hierarchy of this Hand which should act as the attachment point for this GameObject.(立钻哥哥:[attachmentPoint]:这只手的层次结构中GameObject的名称,它应该作为这个GameObject的连接点.

        public void AttachObject(GameObject objectToAttach, GrabTypes graddedWithType, AttachmentFlags flags=defaultAttachmentFlags, Transform attachmentOffset=null){}

 

       public bool ObjectIsAttached(GameObject go){}

       public void ForceHoverUnlock(){}

 

       //Detach this GameObject from the attached object stack of this Hand.(立钻哥哥:从这只手的附加对象堆栈中分离这个GameObject.

        //[objectToDetach]: The GameObject to detach from this Hand.(立钻哥哥:[objectToDetach]:要从这只手分离的GameObject.

        public void DetachObject(GameObject objectToDetach, bool restoreOriginalParent=true){}

 

       //Get the world velocity of the VR Hand.(立钻哥哥:得到VR手的世界速度.

        public Vector3 GetTrackedObjectVelocity(float timeOffset=0){}

 

       //Get the world space angular velocity of the VR Hand.(立钻哥哥:得到VR手的世界空间角速度.

        public Vector3 GetTrackedObjectAngularVelocity(float timeOffset=0){}

 

        public void GetEstimatedPeakVelocities(out Vector3 velocity, out Vector3 angularVelocity){}

        private void CleanUpAttachedObjectStack(){}

        protected virtual void Awake(){}

        protected virtual void OnDestroy(){}

        protected virtual void OnTransformUpdated(SteamVR_Behaviour_Pose updatedPose, SteamVR_Input_Sources updateSource){}

        protected virtual IEnumerator Start(){}

        protected virtual void UpdateHovering(){}

        protected virtual bool CheckHoveringForTransform(Vector3 hoverPosition, float hoverRadius, ref float closestDistance, ref Interactable closestInteractable, Color debugColor){}

        protected virtual void UpdateNoSteamVRFallback(){}

        private void UpdateDebugText(){}

        protected virtual void OnEnable(){}

        protected virtual void OnDisable(){}

        protected virtual void Update(){}

 

        //Returns true when the hand is currently hovering over the interactable passed in.(立钻哥哥:当指针当前悬停在传入的可交互物体上时,返回true

        public bool IsStillHovering(Interactable interactable){}

 

        protected virtual void HandFollowUpdate(){}

        protected virtual void FixedUpdate(){}

        protected void UpdateAttachedVelocity(AttachedObject attachedObjectInfo){}

        protected Vector3 TargetItemPosition(AttachedObject attacheObject){}

        protected Quaternion TargetItemRotation(AttachedObject attachedObject){}

        protected bool GetUpdateAttachedVelocities(AttachedObject attachedObjectInfo, out Vector3 velocityTarget, out Vector3 angularTarget){}

        protected virtual void OnInputFocus(bool hasFocus){}

        protected virtual void OnDrawGizmos(){}

        private void HandDebugLog(string msg){}

 

        //Continue to hover over this object indefinitely, whether or not the Hand moves out of its interaction trigger volume.(立钻哥哥:无论手是否移出交互触发范围,都将无限期地悬停在该对象上

        public void HoverLock(Interactable interactable){}

 

        //Stop hovering over this object indefinitely.(立钻哥哥:停止无限期地悬停在这个物体上.

        public void HoverUnlock(Interactable interactable){}

 

        public void TriggerHapticPulse(ushort microSecondsDuration){}

        public void TriggerHapticPulse(float duration, float frequency, float amplitude){}

        public void ShowGrabHint(){}

        public void HideGrabHint(){}

        public void ShowGrabHint(string text){}

        public GrabTypes GetGrabString(GrabTypes explicitType=GrabTypes.None){}

        public GrabTypes GetGrabEnding(GrabTypes explicitType=GrabTypes.None){}

        public bool IsGrabEnding(GameObject attachedObject){}

        public bool IsGrabbingWithType(GrabTypes type){}

        public bool IsGrabbingWithOppositeType(GrabTypes type){}

        public GrabTypes GetBestGrabbingType(){}

        public GrabTypes GetBestGrabbingType(GrabTypes preferred, bool forcePreference=false){}

        private void InitController(){}

        public void SetRenderModel(GameObject prefab){}

        public void SetHoverRenderModel(RenderModel hoverRenderModel){}

        public int GetDeviceIndex(){}

 

    }    //立钻哥哥:public class Hand:MonoBehaviour{}

 

    [System.Serializable]

    public class HandEvent : UnityEvent<Hand>{}

 

    UNITY_EDITOR

    [UnityEditor.CustomEditor(typeof(Hand))]

    public class HandEditor : UnityEditor.Editor{

        public override void OnInspectorGUI(){}

    }    //立钻哥哥:public class HandEditor:UnityEditor.Editor{}

 

}    //立钻哥哥:namespace Valve.VR.InteractionSystem{}

 

++InputModule([Player_VR/InputModule])输入模块

++++立钻哥哥:[Purpose: Makes the hand act as an input module for Unitys event system.(目的:使手作为Unity事件系统的输入模块)]

++++\Assets\ThirdPartyPlugins\SteamVR\InteractionSystem\Core\Scripts\InputModule.cs

//Purpose: Makes the hand act as an input module for Unitys event system.(立钻哥哥:目的:使手作为Unity事件系统的输入模块.

using UnityEngine;

using System.Collecitons;

using UnityEngine.EventSystems;

 

namespace Valve.VR.InteractionSystem{

    public class InputModule : BaseInputModule{

        private GameObject submitObject;

    

        private static InputModule _instance;

        public static InputModule instance{}

 

        public override bool ShouldActivateModule(){}

        public void HoverBegin(GameObject gameObject){}

        public void HoverEnd(GameObject gameObject){}

        public void Submit(GameObject gameObject){}

        public override void Process(){}

    }    //立钻哥哥:public class InputModule:BaseInputModule{}

}    //立钻哥哥:namespace Valve.VR.InteractionSystem{}

 

++知识点01public static InputModule instance{}单例

++++立钻哥哥\Assets\ThirdPartyPlugins\SteamVR\InteractionSystem\Core\Scripts\InputModule.cs

private static InputModule _instance;

public static InputModule instance{

    get{

        if(_instance == null){

            _instance = GameObject.FindObjectOfType<InputModule>();

        }

        return _instance;

    }

}

 

++知识点02public override bool ShouldActivateModule(){}

++++立钻哥哥\Assets\ThirdPartyPlugins\SteamVR\InteractionSystem\Core\Scripts\InputModule.cs

public override bool ShouldActivateModule(){

    if(!base.ShouldActivateModule){

       return false;

    }

    return submitObject != null;

}

 

++知识点03public void HoverBegin(GameObject gameObject){}

++++立钻哥哥\Assets\ThirdPartyPlugins\SteamVR\InteractionSystem\Core\Scripts\InputModule.cs

public void HoverBegin(GameObject gameObject){

    PointerEventData pointerEventData = new PointerEventData(eventSystem);

    ExecuteEvents.Execute(gameObject, pointerEventData, ExecuteEvents.pointerEnterHandler);

}

 

++知识点04public void HoverEnd(GameObject gameObject){}

++++立钻哥哥\Assets\ThirdPartyPlugins\SteamVR\InteractionSystem\Core\Scripts\InputModule.cs

public void HoverEnd(GameObject gameObject){

    PointerEventData pointerEventData = new PointerEventData(eventSystem);

pointerEventData.selectedObject = null;

    ExecuteEvents.Execute(gameObject, pointerEventData, ExecuteEvents.pointerEnterHandler);

}

 

++知识点05public void Submit(GameObject gameObject){}

++++立钻哥哥\Assets\ThirdPartyPlugins\SteamVR\InteractionSystem\Core\Scripts\InputModule.cs

public void Submit(GameObject gameObject){

     submitObject = gameObject;

}

 

++知识点06public override void Process(){}

++++立钻哥哥\Assets\ThirdPartyPlugins\SteamVR\InteractionSystem\Core\Scripts\InputModule.cs

public override void Process(){

    if(submitObject){

        BaseEventData data = GetBaseEventData();

        data.selectedObject = submitObject;

        ExecuteEvents.Execute(submitObject, data, ExecuteEvents.submitHandler);

 

       submitObject = null;

    }

}

 

++知识点07:BaseInputModule

++++立钻哥哥C:\Users\unity\AppData\Local\Temp\MetadataAsSource\f5f8a652081f4ec99a4c8a9b8a92baf2\6cc51b7c5187442c852bf027ee8c061d\BaseInputModule.cs

//程序集 UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null

// E:\E_ProgramFiles_02\UnitySetup64-2018.3.0f2\Unity\Editor\Data\UnityExtensions\Unity\GUISystem\UnityEngine.UI.dll

using System.Collections.Generic;

 

namespace UnityEngine.EventSystems{

    //A base module that raises events and sends them to GameObjects.(立钻哥哥:一个引发事件并将其发送到GameObjects的基本模块.

    [RequireComponent(typeof(EventSystem))]

    public abstract class BaseInputModule : UIBehaviour{

        protected List<RaycastResult> m_RaycastResultCache;

        protected BaseInput m_InputOverride;

 

        protected BaseInputModule();

 

        //The current BaseInput being used by the input module.(立钻哥哥:输入模块使用的当前基输入.

        public BaseInput input{  get;  }

 

        //Used to override the default BaseInput for the input module.(立钻哥哥:用于覆盖输入模块的默认BaseInput.

        public BaseInput inputOverride{  get;  set;  }

 

        protected EventSystem eventSystem{  get;  }

 

        //Given an input movement, determine the best MoveDirection.(立钻哥哥:给定一个输入移动,确定最佳移动方向.

        protected static MoveDirection DetermineMoveDirection(float x, float y);

        protected static MoveDirection DetermineMoveDirection(float x, float y, float deadZone);

 

        //Given 2 GameObjects, return a common root GameObject (or null).(立钻哥哥:给定两个GameObject,返回一个通用根GameObject(或null).

        protected static GameObject FindCommonRoot(GameObject g1, GameObject g2);

    

        protected static RaycastResult FindFirstRaycast(List<RaycastResult> candidates);

 

        //Called when the module is activated. Override this if you want custom code to execute when you activate your module.(立钻哥哥:当模块被激活时调用。如果希望在激活模块时执行自定义代码,请覆盖此选项.

        public virtual void ActivateModule();

 

        //Called when the module is deactivated. Override this if you want custom code to execute when you deactivate your module.(立钻哥哥:当模块被停用时调用。如果希望在停用模块时执行自定义代码,请覆盖此选项

        public virtual void DeactivateModule();

 

        //Check to see if the module is supported. Override this if you have a platform specific module (eg. TouchInputModule) that you do not want to activate on standalone.(立钻哥哥:检查模块是否受支持。如果您有一个特定于平台的模块(例如TouchInputModule)您不希望在独立时激活

        //返回结果:Is the module supported.(立钻哥哥:是否支持该模块.

        public virtual bool IsModuleSupported();

 

        //Is the pointer with the given ID over an EventSystem object?(立钻哥哥:具有给定ID的指针是否位于EventSystem对象上?

        public virtual bool IsPointerOverGameObject(int pointerId);

 

        //Process the current tick for the module.(立钻哥哥:处理模块的当前标记.

        public abstract void Process();

 

        //Should be activated.(立钻哥哥:应该被激活.

        //返回结果:Should the module be activated.(立钻哥哥:如果模块被激活.

        public virtual bool ShouldActivateModule(){}

 

        //Update the internal state of the Module.(立钻哥哥:更新模块的内部状态.

        public virtual void UpdateModule();

 

        //Given some input data generate an AxisEventData that can be used by the event.(立钻哥哥:给定一些输入数据生成一个AxisEventData,该数据可被事件使用.

        protected virtual AxisEventData GetAxisEventData(float x, float y, float moveDeadZone);

 

        //Generate a BaseEventData that can be used by the EventSystem.(立钻哥哥:生成一个可以被EventSystem使用的BaseEventData

        protected virtual BaseEventData GetBaseEventData();

 

        //Handle sending enter and exit events when a new enter target is found.(立钻哥哥:当找到新的enter目标时,处理发送enter和exit事件.

        protected void HandlePointerExitAndEnter(PointerEventData currentPointerData, GameObject newEnterTarget);

 

        protected override void OnDisable();

        protected override void OnEnable();

 

    }    //立钻哥哥:public abstract class BaseInputModule:UIBehaviour{}

}    //立钻哥哥:namespace UnityEngine.EventSystems{}

++++public class InputModule : BaseInputModule{}

 

++知识点08:PointerEventData

++++立钻哥哥C:\Users\unity\AppData\Local\Temp\MetadataAsSource\f5f8a652081f4ec99a4c8a9b8a92baf2\5a3518c078024486902212bd5a76c299\PointerEventData.cs

//程序集 UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null

//E:\E_ProgramFiles_02\UnitySetup64-2018.3.0f2\Unity\Editor\Data\UnityExtensions\Unity\GUISystem\UnityEngine.UI.dll

using System;

using System.Collections.Generic;

 

namespace UnityEngine.EventSystems{

    //Event payload associated with pointer (mouse/touch) events.(立钻哥哥:与指针(鼠标/触摸)事件关联的事件有效负载.

    public class PointerEventData : BaseEventData{

        //List of objects in the hover stack.(立钻哥哥:悬停堆栈中的对象列表.

        public List<GameObject> hovered;

 

        public PointerEventData(EventSystem eventSystem);

 

        //The GameObject that received the OnPointerDown.(立钻哥哥:接收OnPointerDown的GameObject.

        public GameObject pointerPress{  get;  set;  }

 

        //The camera associated with the last OnPointerPress event.(立钻哥哥:与上次OnPointerPress事件相关的摄像机.

        public Camera pressEventCamera{  get;  }

        public Camera enterEventCamera{  get;  }

 

        //The EventSystems.PointerEventData.InputButton for this event.(立钻哥哥:EventSystems.PointerEventData.InputButton这个事件

        public InputButton button{  get;  set;  }

 

        //Is a drag operation currently occuring.(立钻哥哥:当前正在执行拖动操作.

        public bool dragging{  get;  set;  }

 

        //Should a drag threshold be used? (立钻哥哥:应该使用拖动阈值吗?

        public bool useDragThreshold{  get;  set;  }

 

        //The amount of scroll since the last update.(立钻哥哥:自上次更新以来的滚动量

        public Vector2 scrollDelta{  get;  set;  }

 

        //Number of clicks in a row.(立钻哥哥:一行中的单击次数.

        public int clickCount{  get;  set;  }

 

        //The last time a click event was sent.(立钻哥哥:上一次发送单击事件.

        public float clickTime{  get;  set;  }

 

        [Obsolete(Use either pointerCurrentRaycast.worldNormal or pointerPressRaycast.worldNormal.(立钻哥哥:使用pointerCurrentRaycast.worldNormal或pointerPressRaycast.worldNormal)]

        public Vector3 worldNormal{  get;  set;  }

        public Vector3 worldPosition{  get;  set;  }

 

        //The screen space coordinates of the last pointer click.(立钻哥哥:屏幕空间坐标的最后一个指针点击.

        public Vector2 pressPosition{  get;  set;  }

 

        //Pointer delta since last update.(立钻哥哥:指针增量自从上次更新.

        public Vector2 delta{  get;  set;  }

 

        //Current pointer position.(立钻哥哥:当前指针位置

        public Vector2 position{  get;  set;  }

 

        //Identification of the pointer.(立钻哥哥:指针的标识.

        public int pointerId{  get;  set;  }

 

        public bool eligibleForClick{  get;  set;  }

 

        //RaycastResult associated with the pointer press.(立钻哥哥:与指针按下相关联的RaycastResult.

        public RaycastResult pointerPressRaycast{  get;  set;  }

 

        //RaycastResult associated with the current event.(立钻哥哥:与当前事件关联的RaycastResult.

        public RaycastResult pointerCurrentRaycast{  get;  set;  }

 

        //The object that is receving OnDrag.(立钻哥哥:正在接收OnDrag的对象

        public GameObject pointerDrag{  get;  set;  }

    

        //The object that the press happened on even if it can not handle the press event.(立钻哥哥:即使不能处理press事件,也要处理被压入的对象.

        public GameObject rawPointerPress{  get;  set;  }

 

        //The GameObject for the last press event.(立钻哥哥:最后一个按下事件的GameObject

        public GameObject lastPress{  get;  }

 

        //The object that received OnPointerEnter.(立钻哥哥:接收“OnPointerEnter”的对象.

        public GameObject pointerEnter{  get;  set;  }

 

        //Is the pointer moving.(立钻哥哥:指针在移动吗?

        public bool IsPointerMoving();

 

        //Is scroll being used on the input device.(立钻哥哥:正在输入设备上使用滚动.

        public bool IsScrolling();

 

        public override string ToString();

 

        //Input press tracking.(立钻哥哥:输入按下跟踪

        public enum InputButton{

            Left = 0,

            Right = 1,

            Middle = 2

        }

 

        //The state of a press for the given frame.(立钻哥哥:给定帧的按下状态.

        public enum FramePressState{

            Pressed = 0,

            Released = 1,

            PressedAndReleased = 2,

            NotChanged = 3

        }

 

    }    //立钻哥哥:public class PointerEventData:BaseEventData{}

}    //立钻哥哥:namespace UnityEngine.EventSystems{}

++++PointerEventData pointerEventData = new PointerEventData(eventSystem);

++++ExecuteEvents.Execute(gameObject, pointerEventData, ExecuteEvents.pointerEnterHandler);

++++pointerEventData.selectedObject = null;

 

++知识点09:ExecuteEvents

++++立钻哥哥C:\Users\unity\AppData\Local\Temp\MetadataAsSource\f5f8a652081f4ec99a4c8a9b8a92baf2\f82c7557f9954a8a947e019071a1c2e1\ExecuteEvents.cs

//程序集 UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null

//E:\E_ProgramFiles_02\UnitySetup64-2018.3.0f2\Unity\Editor\Data\UnityExtensions\Unity\GUISystem\UnityEngine.UI.dll

namespace UnityEngine.EventSystems{

    //Helper class that can be used to send IEventSystemHandler events to GameObjects.(立钻哥哥:Helper类,可用于将IEventSystemHandler事件发送到GameObjects.

    public static class ExecuteEvents{

        //IBeginDragHandler execute helper function.(立钻哥哥:IBeginDragHandler执行helper函数.

        public static EventFunction<IBeginDragHandler> beginDragHandler{  get;  }

        public static EventFunction<IDeselectHandler> deselectHandler{  get;  }

        public static EventFunction<ISelectHandler> selectHandler{  get;  }

        public static EventFunction<IUpdateSelectedHandler> updateSelectedHandler{  get;  }

        public static EventFunction<IScrollHandler> scrollHandler{  get;  }

        public static EventFunction<IDropHandler> dropHandler{  get;  }

        public static EventFunction<IEndDragHandler> dragHandler{  get;  }

        public static EventFunction<IDragHandler> dragHandler{  get;  }

        public static EventFunction<ICancelHandler> cancelHandler{  get;  }

        public static EventFunction<IMoveHandler> moveHandler{  get;  }

        public static EventFunction<IInitializePotentialDragHandler> initializePotentialDrag{  get;  }

        public static EventFunction<IPointerUpHandler> pointerUpHandler{  get;  }

        public static EventFunction<IPointerDownHandler> pointerDownHandler{  get;  }

        public static EventFunction<IPointerExitHandler> pointerExitHandler{  get;  }

        public static EventFunction<IPointerEnterHandler> pointerEnterHandler{  get;  }

        public static EventFunction<IPointerClickHandler> pointerClickHandler{  get;  }

        public static EventFunction<ISubmitHandler> submitHandler{  get;  }

 

        public static bool CanHandleEvent<T>(GameObject go) where T : IEventSystemHandler;

        public static bool Execute<T>(GameObject target, BaseEventData eventData, EventFunction<T> functor) where T : IEventSystemHandler;

        public static GameObject ExecuteHierarchy<T>(GameObject root, BaseEventData eventData, EventFunction<T> callbackFunction) where T : IEventSystemHandler;

        public static GameObject GetEventHandler<T>(GameObject root) where T : IEventSystemHandler;

        public static T ValidateEventData<T>(BaseEventData data) where T : class;

 

        public delegate void EventFunction<T1>(T1 handler, BaseEventData eventData);

 

    }    //立钻哥哥:public static class ExecuteEvents{}

}    //立钻哥哥:namespace UnityEngine.EventSystems{}

++++ExecuteEvents.Execute(gameObject, pointerEventData, ExecuteEvent.pointerEnterHandler);

++++ExecuteEvents.Execute(submitObject, data, ExecuteEvent.submitHandler);

 

++知识点10:BaseEventData

++++立钻哥哥C:\Users\unity\AppData\Local\Temp\MetadataAsSource\f5f8a652081f4ec99a4c8a9b8a92baf2\0049f4b839ea4dd18b778f7722b23518\BaseEventData.cs

//程序集 UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null

//E:\E_ProgramFiles_02\UnitySetup64-2018.3.0f2\Unity\Editor\Data\UnityExtensions\Unity\GUISystem\UnityEngine.UI.dll

namespace UnityEngine.EventSystems{

    //A class that contains the base event data that is common to all event types in the new EventSystem.(立钻哥哥:包含基本事件数据的类,这些基本事件数据对新事件系统中的所有事件类型都是通用的.

    public class BaseEventData : AbstractEventData{

        //Construct a BaseEventData tied to the passed EventSystem.(立钻哥哥:构造与传递的事件系统绑定的BaseEventData.

        public BaseEventData(EventSystem eventSystem);

 

        //A reference to the BaseInputModule that sent this event.(立钻哥哥:发送此事件的BaseInputModule的引用.

        public BaseInputModule currentInputModule{  get;  }

 

        //The object currently considered selected by the EventSystem.(立钻哥哥:事件系统当前考虑选择的对象.

        public GameObject selectedObject{  get;  set;  }

 

    }    //立钻哥哥:public class BaseEventData : AbstractEventData{}

}    //立钻哥哥:namespace UnityEngine.EventSystems{}

++++BaseEventData data = GetBaseEventData();

 

 

++++\Assets\ThirdPartyPlugins\OVRUI\OVRInputModule.cs

using System;

using System.Collections.Generic;

using Valve.VR;

 

namespace UnityEngine.EventSystems{

    //VR extension of PointerInputModule which supports gaze and controller pointing.(立钻哥哥:支持凝视和控制器指向的PointerInputModule的VR扩展.

    public class OVRInputModule : PointerInputModule{

        public Valve.VR.SteamVR_Action_Boolean confirmAction = SteamVR_Input.GetAction<SteamVR_Action_Boolean>(InteractUI, Confirm);

        public SteamVR_Input_Sources inputSource = SteamVR_Input_Sources.RightHand;

        public SteamVR_ActionSet ui_InputAction = SteamVR_Input.GetActionSet(InteractUI);

 

        protected override void Start(){

           base.Start();

            if(ui_InputAction != null){

                ui_InputAction.Activate(inputSource);

            }

        }

 

        //For RectTransform, calculate its normal in world space.(立钻哥哥:对于RectTransform,计算它在世界空间中的法线.

       static Vector3 GetRectTransformNormal(RectTransform rectTransform){}

 

        //State for a pointer controlled by a world space ray. E.g. gaze pointer.(立钻哥哥:由世界空间射线控制的指针的状态。如目光指针.

        virtual protected MouseState GetGazePointerData(){}

 

        //Get state for pointer which is a pointer moving in world space across the surface of a world space canvas.(立钻哥哥:获取指针的状态,该指针在世界空间中移动,穿过世界空间画布的表面.

        protected MouseState GetCanvasPointerData(){}

 

        private bool ShouldStartDrag(PointerEventData pointerEvent){}

        static bool IsPointerMoving(PointerEventData pointerEvent){}

        protected Vector2 SwipeAdjustedPosition(Vector2 originalPosition, PointerEventData pointerEvent){}

        protected override void ProcessDrag(PointerEventData pointerEvent){}

        virtual protected PointerEventData.FramePressState GetGazeButtonState(){}

        protected Vector2 GetExtraScrollDelta(){}

 

    }    //立钻哥哥:public class OVRInputModule:PointerInputModule{}

}    //立钻哥哥:namespace UnityEngine.EventSystem{}

++++OVRInputModule inputModule = EventSystem.current.currentInputModule as OVRInputModule;

++++if(OVRInputModule.currentRayCastResult.gameObject != null && uiRay && !interactGrab.GetGrabbedObject()){}

++++lineRenderer.SetPosition(1, Vector3.forward * OVRInputModule.currentRayCastResult.distance);

 

++PlayVolume([Player_VR/PlayVolume])(游戏范围)

++++立钻哥哥:[Purpose: Draw different sized room-scale play areas for targeting content.(用途:绘制不同大小的房间规模的游戏区,为目标的内容)]

++++\Assets\ThirdPartyPlugins\SteamVR\Scripts\SteamVR_PlayArea.cs

//Purpose: Draws different sized room-scale play areas for targeting content.(立钻哥哥:用途:绘制不同大小的房间规模的游戏区域,目标内容

using UnityEngine;

using UnityEngine.Rendering;

using System.Collections;

using Valve.VR;

 

namespace Valve.VR{

    [ExecuteInEditMode, RequireComponent(typeof(MeshRenderer), typeof(MeshFilter))]

    public class SteamVR_PlayArea : MonoBehaviour{

        public float borderThickness = 0.15f;

        public float wireframeHeight = 2.0f;

        public bool drawWireframeWhenSelectedOnly = false;

        public bool drawInGame = true;

 

        public static bool GetBounds(Size size, ref HmdQuad_t pRect){}

        public void BuildMesh(){}

        void OnDrawGizmos(){}

        void OnDrawGizmosSelected(){}

        public void DrawWireframe(){}

        public void OnEnable(){}

        IEnumerator UpdateBounds(){}

 

    }    //立钻哥哥:public class SteamVR_PlayArea:MonoBehaviour{}

}    //立钻哥哥:namespace Valve.VR{}

 

 

 

 

####A.02.01.01、Resources/

####A.02.01.01、Resources/

++A.02.01.01、Resources/

++++立钻哥哥:Resources”允许从指定的路径查找或访问资源

++++Resources”的API详解链接:https://blog.csdn.net/VRunSoftYanlz/article/details/83155518

 

++SkipCanvasLearn(Assets/E1/Prefabs/Resources)

++++立钻哥哥:跳过按钮及布局

++++\Assets\ThirdPartyPlugins\OVRUI\OVRRaycaster.cs

using System;

using System.Collections;

using System.Collections.Generic;

using System.Text;

using UnityEngine;

using UnityEngine.UI;

using UnityEngine.EventSystems;

using UnityEngine.Serialization;

 

//Extension of GraphicRaycaster to support ray casting with world space rays instead of just screen-space pointer positions.(立钻哥哥:扩展GraphicRaycaster来支持世界空间射线的光线投射,而不仅仅是屏幕空间指针的位置.

[RequireComponent(typeof(Canvas))]

public class OVRRaycaster : GraphicRaycaster, IPointerEnterHandler{

    [Tooltip(A world space pointer for this canvas.(立钻哥哥:这个画布的一个世界空间指针)]

    public GameObject pointer;

 

    public int sortOrder = 0;

 

    protected OVRRaycaster(){}

 

    [NonSerialized]

    private Canvas m_Canvas;

    private Canvas canvas{}

 

    public override Camera eventCamera{}

    public override int sortOrderPriority{}

    protected override void Start(){}

 

    //For the given ray, find graphics on this canvas which it intersects and are not blocked by other world objects.(立钻哥哥:对于给定的光线,在画布上找到它与之相交且不被其他世界对象阻塞的图形.

    [NonSerialized]

    private List<RaycastHit> m_RaycastResults = new List<RaycastHit>();

    private void Raycast(PointerEventData eventData, List<RaycastResult> resultAppendList, Ray ray, bool checkForBlocking){}

 

    //Performs a raycast using eventData.worldSpaceRay.(立钻哥哥:使用eventData.worldSpaceRay执行光线转换.

    public override void Raycast(PointerEventData eventData, List<RaycastResult> resultAppendList){}

 

    //Performs a raycast using the pointer object attached to this OVRRaycaster.(立钻哥哥:使用附加到此OVRRaycaster的指针对象执行光线转换.

    public void RaycastPointer(PointerEventData eventData, List<RaycastResult> resultAppendList){}

 

    //Perform a raycast into the screen and collect all graphics underneath it.(立钻哥哥:将光线投射到屏幕上,并收集屏幕下面的所有图形.

    [NonSerialized]

    static readonly List<RaycastHit> s_SortedGraphics = new List<RaycastHit>();

    private void GraphicRaycast(Canvas canvas, Ray ray, List<RaycastHit> results){}

 

    //Get screen position of worldPosition contained in this RaycastResult.(立钻哥哥:获取包含在这个RaycastResult中的worldPosition的屏幕位置

    public Vector2 GetScreenPosition(RaycastResult raycastResult){}

 

    //Detects whether a ray intersects a RectTransform and if it does also returns the world position of the intersection.(立钻哥哥:检测射线是否与RectTransform相交,如果相交,则返回相交点的世界位置.

    static bool RayIntersectsRectTransform(RectTransform rectTransform, Ray ray, out Vector3 worldPos){}

 

    struct RaycastHit{

        public Graphic graphic;

        public Vector3 worldPos;

        public bool fromMouse;

    }    //立钻哥哥:struct RaycastHit{}

 

    //Is this the currently focussed Raycaster according to the InputModule.(立钻哥哥:根据InputModule,这是当前聚焦的光线吗?

    public bool IsFocussed(){}

 

    public void OnPointerEnter(PointerEventData e){}

 

}    //立钻哥哥:public class OVRRaycaster:GraphicRaycaster,IPointerEnterHandler{}

 

 

++Button([SkipCanvasLearn/Button])

++++立钻哥哥:“Button”是跳过按钮的组件

++++\Assets\E1\Scripts\SkipButton.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.UI;

 

public class SkipButton : MonoBehaviour{

    public Button skipBtn;

 

    void Start(){

        skipBtn.onClick.AddListener(OnSkipButtonClick);

    }

 

    private void OnSkipButtonClick(){

        if(DismantleLoadAndCreate.Instanc.prefab){

            Destroy(DismantleLoadAndCreate.Instance.prefab);

        }

        LearnGuideMgr.Instance.StartLearnFlow();

        skipBtn.onClick.RemoveListener(onSkipButtonClick);

    }    //立钻哥哥:private void OnSkipButtonClick(){}

 

}    //立钻哥哥:public class SkipButton:MonoBehaviour{}

++++btn.GetComponentInChildren<SkipButton>().skipBtn.onClick.AddListener(()=>OnSkipBtn_LearnClick(btn));

++++btn.GetComponentInChildren<SkipButton>().skipBtn.onClick.AddListener(()=>{  OnSkipBtn_ExClick(btn);  });

++++[SkipCanvasLearn/Button/Text]:跳过按钮显示文本信息“跳过”设置:

 

 

 

####A.02.01.02、Rsk/

####A.02.01.02、Rsk/

++A.02.01.02、Rsk/(Assets/E1/Prefabs/Rsk/)

++++立钻哥哥:Rsk/”是一些功能模块预制体

++++A.02.01.02.A、New_jianpan_00.prefab

++++A.02.01.02.B、Resources/Experiment/

 

++A.02.01.02.A、New_jianpan_00.prefab

++++立钻哥哥:“New_jianpan_00.prefab”是一个键盘模型预制体,主要是用在登录界面的键入输入

 

 

 

 

#####A.02.01.02.B、Resources/Experiment/

#####A.02.01.02.B、Resources/Experiment/

++A.02.01.02.B、Resources/Experiment/(Assets/E1/Prefabs/Rsk/)

++++立钻哥哥:这个目录下是E1中相关预制体,主要有两个文件夹:DismantlePrefabs/UIPanelPrefabs/

++++A.02.01.02.B.01DismantlePrefabs/

++++A.02.01.02.B.02UIPanelPrefabs/

 

 

######A.02.01.02.B.01、DismantlePrefabs/

######A.02.01.02.B.01、DismantlePrefabs/

++A.02.01.02.B.01、DismantlePrefabs/(Assets/E1/Prefabs/Rsk/Resources/Experiment/)

++++立钻哥哥:这里是关于“拆解模式”相关的预制体

++++A.02.01.02.B.01.011669dd8ad6154f5082d5932ad9f8a216.prefab

++++A.02.01.02.B.01.02CreatDismantleManager.prefab

++++A.02.01.02.B.01.03Root.prefab

 

 

#######A.02.01.02.B.01.01、1669dd8ad6154f5082d5932ad9f8a216.prefab

#######A.02.01.02.B.01.01、1669dd8ad6154f5082d5932ad9f8a216.prefab

++A.02.01.02.B.01.01、1669dd8ad6154f5082d5932ad9f8a216.prefab

++++立钻哥哥:这个预制体应该是一个演示Demo,有一块电路板,上面有几块芯片,可以用射线进行交互

 

++[立钻哥哥的测试板Demo](测试板)

++++立钻哥哥:这是一块测试板的预制体

++++\Assets\ThirdPartyPlugins\YanlzXR.VR\InteractSystem\InteractableObject.cs

//立钻哥哥:可挂在物体上的交互组件,可以响应“Touch、Install、Grab”等事件

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

 

namespace YanlzXR.VR.InteractSystem{

    //立钻哥哥:可交互物体事件信息

    public struct InteractableObjectEventArgs{

        //正在与物体交互的GameObject, 一般为HandController

        public GameObject interactingObject;

    }    //立钻哥哥:public struct InteractableObjectEventArgs{}

 

    //立钻哥哥:事件代理定义

    //[sender]:发送事件的物体

    public delegate void InteractableObjectEventHandler(object sender, InteractableObjectEventArgs e);

 

    //立钻哥哥:可交互组件类

    public class InteractableObject : MonoBehaviour{

        //当HandController碰到此物体时发送此事件

        public event InteractableObjectEventHandler InteractableObjectTouched;

 

        //当HandController离开此物体时发送此事件

        public event InteractableObjectEventHandler InteractableObjectUnTouched;

 

        //当被抓起时触发此事件

        public event InteractableObjectEventHandler InteractableObjectGrabbed;

 

        //当被放下时触发此事件

        public event InteractableObjectEventHandler InteractableObjectUngrabbed;

 

        [HideInInspector]

        public float hitDistance;

 

        //是否可交互

        public bool isInteractable = true;

 

        [Header(所处层级)]

        public uint SortLayer = 0;    //立钻哥哥:所处层级

 

        [Header(在层级中的权重)]

        public uint OrderInLayer = 0;    //立钻哥哥:在层级中的权重

 

        [Header(Touch HightLightSetting)]

        public BaseObjectHightLight objectHighLight;

 

        [Header(GrabSetting)]

        public bool isGrabable;

        public BaseGrabAttach grabAttach;

        public BaseSecondaryGrabAction secondaryGrabAction;

 

        [Header(DisintegrateSetting)]

        public BaseDisintegrateAction disintegrateAction;

 

        protected GameObject primaryGrabbingObject;

        protected GameObject secondaryGrabbingObject;

        protected List<GameObject> grabbingObjects = new List<GameObject>();

        protected List<GameObject> disintegrateObjects = new List<GameObject>();

 

        protected virtual void Awake(){

            GetGrabAttach();

            GetSecondGrabAction();

            GetDisintegrateAction();

 

            if(objectHighLight == null){

                objectHighLight = GetComponentInChildren<BaseObjectHightLight>();

            }

        }    //立钻哥哥:protected virtual void Awake(){}

 

        protected virtual void GetGrabAttach(){}

        protected virtual void GetSecondGrabAction(){}

        protected virtual void GetDisintegrateAction(){}

 

        //可交互物体被Touch时调用

        //[interactingObj]: 主动Touch此InteractableObject的物体

        public virtual void OnInteractableObjectTouched(GameObject interactingObj){}

 

        //可交互物体被Untouch时调用

        //[interactingObj]: Untouch此InteractableObject的物体

        public virtual void OnInteractableObjectUntouched(GameObject interactingObj){}

 

        public virtual void OnInteractableObjectGrabbed(GameObject interactingObj, GameObject attachPoint, RaycastHit hitResult){}

        protected virtual void PrimaryControllerGrab(GameObject interactingObj, GameObject attachPoint, RaycastHit hitResult){}

        protected virtual void SecondaryControllerGrab(GameObject interactingObj){}

 

        //立钻哥哥:强制松手

        protected virtual void ForceReleaseGrab(){}

 

        public virtual void OnInteractableObjectUngrabbed(GameObject interactingObj){}

        public virtual void OnDisintegrated(GameObject interactingObj){}

        public virtual void OnUnDisintegrated(GameObject interactingObj){}

        protected virtual void PrimaryControllerUngrab(GameObject primaryGrabbingObject){}

        protected virtual void SecondaryControllerUngrab(GameObject primaryGrabbingObject){}

        public virtual bool IsGrabbed(GameObject grabbedBy = null){}

        public virtual bool IsSwappble(){}

        public virtual GameObject GetGrabbingObject(){}

 

        //立钻哥哥:获取抓住此物体的第二支手

        public virtual GameObject GetSecondaryGrabbingObject(){}

 

        [HideInInspector]

        public GameObject primaryDisintegratingObject;

 

       [HideInInspector]

        public GameObject secondaryDisintegratingObject;

 

        public virtual GameObject GetPrimaryDisintegratingObject(){}

        public virtual GameObject GetSecondaryDisintegratingObject(){}

        public void ForceStopInteract(){}

        protected virtual void OnDestroy(){}

        protected virtual void Update(){}

 

    }    //立钻哥哥:public class InteractableObject:MonoBehaviour{}

 

}    //立钻哥哥:namespace YanlzXR.VR.InteractSystem{}

++++protected InteractableObject grabbedObject;

++++public virtual void Initialize(InteractableObject grabbedObject, InteractGrab primaryGrabbingObject, InteractGrab secondaryGrabbingObject){}

++++protected InteractableObject grabbedObjectScript;

++++[RequireComponent(typeof(InteractableObject))]

++++InteractableObject ract;

++++ract = GetComponent<InteractableObject>();

++++grabbedObjectScript = givenGrabbedObject.GetComponent<InteractableObject>();

++++if(!ract) ract = gameObject.AddComponent<InteractableObject>();

++++public class Element_Interactable_Base : InteractableObject{}

++++public readonly List<InteractableObject> interactableObjs = new List<InteractableObject>();

++++protected InteractableObject currentTouchObject;

++++public virtual InteractableObject GetTouchedObject(){}

++++[RequireComponent(typeof(InteractableObject))]

++++InteractableObject obj = interactRaycaster.raycastResult[0].transform.GetComponent<InteractableObject>();

++++GetComponent<InteractableObject>().isGrabable = true;

++++protected InteractableObject grabbedObject;

++++InteractableObject obj = interactRaycaster.raycastResult[0].transform.GetComponent<InteractableObject>();

++++InteractableObject interactObj = interactTouch.GetTouchedObject();

++++InteractableObject go = childTfList[i].GetComponent<InteractableObject>();

++++protected virtual bool IsGrabAction(InteractableObject intobj){}

++++protected InteractableObject currentDisintegratedObject;

++++private InteractableObject currentCheckingObject;

++++protected virtual bool IsReleaseAction(InteractableObject intoobj){}

++++InteractableObject go = childTfList[i].GetComponent<InteractableObject>();

++++protected virtual void AttempToGrabObject(InteractableObject interactObj){}

++++InteractableObject grabbedObject = interactGrab.GetGrbbedObject();

++++protected virtual void ChooseGrabSequence(InteractableObject interactObj){}

++++public virtual InteractableObject GetDisintegratableObject(){}

++++protected virtual void InitPrimaryGrab(InteractableObject interactObj){}

++++public virtual bool IsDisintegratable(InteractableObject obj){}

++++protected virtual void InitSecondaryGrab(InteractableObject interactObj){}

++++protected virtual void AttempToReleaseObject(InteractableObject interactObj){}

++++InteractableObject interactableObject = interactTouch.GetTouchedObject();

++++public virtual InteractableObject GetGrabbedObject(){}

++++InteractableObject obj = item.collider.GetComponentInParent<InteractableObject>();

++++public virtual bool IsInteractObjectGrabble(InteractableObject interactObj){}

++++InteractableObject obj = item.collider.GetComponentInParent<InteractableObject>();

++++var interactable = obj.GetComponent<InteractableObject>();

++++private int CompareDistance(InteractableObject i1, InteractableObject i2){}

++++public virtual bool IsObjectTouchable(InteractableObject obj){}

++++\Assets\E1\Scripts\Rsk\Dismantle\Dismantle.cs

using YanlzXR.VR.InteractSystem;

using System;

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using Valve.VR;

using Valve.VR.InteractionSystem;

 

public enum Info{

    one = 0,

    two,

    three,

    four,

    five

}    //立钻哥哥:public enum Info{}

 

//立钻哥哥:拆解脚本

[RequireComponent(typeof(InteractableObject))]

public class Dismantle : BaseDisintegrateAction{

    public Info info;

    public bool isDismantle, isLeftEnter, isRightEnter, canDismantle;

    public string rootGoName;

    Player_VR playerInstance;

    BoxCollider box;

    Transform center;

    private float childScale;

   

    //立钻哥哥:刷新当前模型拆解状态

    public Action<bool> disAction;

 

    float a;

    List<Transform> childTfList = new List<Transform>();

    List<Vector3> childPosOrigin = new List<Vector3>();

 

    private void Awake(){

        if(info == Info.one){

            GetComponent<InteractableObject>().isGrabable = true;

        }

        center = transform.Find(Center);

        center.GetComponent<MeshRenderer>().enabled = false;

        Debug.Log(立钻哥哥:子物体个数  + transform.childCount);

    }

 

    void Start(){

        playerInstance = Player_VR.Instance;

        box = GetComponent<BoxCollider>();

        oriBoxSize = box.size;

 

        if(transform.name == rootGoName){

            InitChildTransformData();

        }

 

        disAction += (a)=>{

            GetComponent<BoxCollider>().enabled = a;

            canDismantle = a;

        };

    }    //立钻哥哥:void Start(){}

 

    Coroutine dismantleState;

    Vector3 v3;

 

    void Update(){}

 

    //立钻哥哥:进入拆解的事件

    public override void OnDisintegrateStart(){

        base.OnDisintegrateStart();

        isDismantle = true;

        dismantleState = StartCoroutine(DismantleState);

        for(int i = 0;  i < childTfList.Count;  i++){

            childTfList[i].GetComponent<Dismantle>()?.Reset();

            childTfList[i].localEulerAngles = Vector3.zero;

        }

    }

 

    public override void ProcessDisintegrateAction(GameObject primaryHand, GameObject secondaryhand){}

    public override void OnDisintegrateStop(){}

 

    //从外部调用当前物体是否可以拆解

    private void ChangeChildCanDis(bool childBool){}

 

    public Dismantle ChangeInfo(int index){}

 

    //初始化子物体信息,并添加到可拆解子物体集合

    public void InitChildTransformData(){}

 

    //获取当前子物体的拆解程度

    private float GetChildForParentDistance(){}

 

    //当重新进入拆解模式时,重置子物体的位置

    public void Reset(){}

   

    //拆解模式

    private IEnumerator DismantleState(){}

 

    //物体跟随两手方向旋转,获取方向,从左手指向右手

    private Vector3 GetHandNormalize(){}

 

    //获取当前点击动作,判断是否进入拆解动作

    private bool GetGripState(SteamVR_Input_Sources source){

        return SteamVR_Input.GetAction<SteamVR_Action_Boolean>(UIUse, GrabGrip).GetState(source);

    }

 

    //获取两手的距离,用于计算子物体的拆解程度

    private float GetHandsDistance(){}

 

}    //立钻哥哥:public class Dismantle:BaseDisintegrateAction{}

++++childTfList[i].GetComponent<Dismantle>()?.Reset();

++++childTfList[i].GetComponent<Dismantle>()?.disAction(childBool);

++++public Dismantle ChangeInfo(int index){}

++++tf.GetComponent<Dismantle>()?.ChangeInfo((int)info + 1).InitChildTransformData();

 

++知识点01:InteractableObject

++++立钻哥哥可交互组件类

//\Assets\ThirdPartyPlugins\LeiJia.VR\InteractSystem\InteractableObject.cs

public struct InteractableObjectEventArgs{

    public GameObject interactingObject;

}

 

public delegate void InteractableObjectEventHandler(object sender, InteractableObjectEventArgs e);

 

public class InteractableObject : MonoBehaviour{

    public event InteractableObjectEventHandler InteractableObjectTouched;

    public event InteractableObjectEventHandler InteractableObjectUnTouched;

    public event InteractableObjectEventHandler InteractableObjectGrabbed;

    public event InteractableObjectEventHandler InteractableObjectUngrabbed;

 

    protected virtual void Awake(){}

}

++++[RequireComponent(typeof(InteractableObject))]

++++GetComponent<InteractableObject>().isGrabable = true;

++++InteractableObject go = childTfList[i].GetComponent<InteractableObject>();

 

++知识点02:BaseDisintegrateAction

++++立钻哥哥拆解动作的基类

public abstract class BaseDisintegrateAction : MonoBehaviour{

    public virtula void OnDisintegrateStart(){}

    public virtual void ProcessDisintegrateAction(GameObject primaryHand, GameObject secondaryhand){}

    public virtual void OnDisintegrateStop(){}

}    //立钻哥哥:public abstract class BaseDisintegrateAction:MonoBehaviour{}

++++public class Dismantle : BaseDisintegrateAction{}

 

++知识点03:Player_VR

++++立钻哥哥玩家控制脚本

public class Player_VR : MonoBehaviour{

    public static Player_VR Instance;

    public Transform head;

    public Camera Main;

    public Transform camRig;

    float renderScale;

    public GameObject leftHand;

    public GameObject rightHand;

    public Transform root;

 

    private void Awake(){  Instance = this;  }

}    //立钻哥哥:public class Player_VR:MonoBehaviour{}

++++Player_VR playerInstance;

++++playerInstance = Player_VR.Instance;

 

++++\Assets\ThirdPartyPlugins\LeiJia.VR\HighLight\OutlineHighLight.cs

 

 

 

 

 

 

 

 

 

 

 

 

【XR游戏开发QQ群:784477094

++立钻哥哥推荐的拓展学习链接(Link_Url)

立钻哥哥推荐的拓展学习链接(Link_Url)

++++立钻哥哥Unity 学习空间: http://blog.csdn.net/VRunSoftYanlz/

++++虚拟现实VR资讯: https://blog.csdn.net/VRunSoftYanlz/article/details/89165846

++++HTC_VIVE开发基础https://blog.csdn.net/VRunSoftYanlz/article/details/81989970

++++Oculus杂谈https://blog.csdn.net/VRunSoftYanlz/article/details/82469850

++++Oculus安装使用https://blog.csdn.net/VRunSoftYanlz/article/details/82718982

++++Unity+SteamVR=>VRhttps://blog.csdn.net/VRunSoftYanlz/article/details/88809370

++++Unity减少VR晕眩症https://blog.csdn.net/VRunSoftYanlz/article/details/89115518

++++SteamVR简介https://blog.csdn.net/VRunSoftYanlz/article/details/86484254

++++SteamVR脚本功能分析https://blog.csdn.net/VRunSoftYanlz/article/details/86531480

++++SteamVR2.0开发指南https://blog.csdn.net/VRunSoftYanlz/article/details/86618187

++++SteamVR2.2.0开发指南https://blog.csdn.net/VRunSoftYanlz/article/details/88784527

++++SteamVR2.2.0快速入门https://blog.csdn.net/VRunSoftYanlz/article/details/88833579

++++SteamVR2.2.0交互系统https://blog.csdn.net/VRunSoftYanlz/article/details/89199778

++++SteamVR2.2.0传送机制https://blog.csdn.net/VRunSoftYanlz/article/details/89390866

++++SteamVR2.2.0官方教程https://blog.csdn.net/VRunSoftYanlz/article/details/89324067

++++SteamVR实战之PMCorehttps://blog.csdn.net/VRunSoftYanlz/article/details/89463658

++++SteamVR/Extrashttps://blog.csdn.net/VRunSoftYanlz/article/details/86584108

++++SteamVR/Inputhttps://blog.csdn.net/VRunSoftYanlz/article/details/86601950

++++OpenXR简介https://blog.csdn.net/VRunSoftYanlz/article/details/85726365

++++VRTK杂谈https://blog.csdn.net/VRunSoftYanlz/article/details/82562993

++++VRTK快速入门(杂谈)https://blog.csdn.net/VRunSoftYanlz/article/details/82955267

++++VRTK官方示例(目录)https://blog.csdn.net/VRunSoftYanlz/article/details/82955410

++++VRTK代码结构(目录)https://blog.csdn.net/VRunSoftYanlz/article/details/82780085

++++VRTK(SceneResources)https://blog.csdn.net/VRunSoftYanlz/article/details/82795400

++++VRTK_ControllerEventshttps://blog.csdn.net/VRunSoftYanlz/article/details/83099512

++++VRTK_InteractTouchhttps://blog.csdn.net/VRunSoftYanlz/article/details/83120220

++++虚拟现实行业应用https://blog.csdn.net/VRunSoftYanlz/article/details/88360157

++++Steam平台上的VRhttps://blog.csdn.net/VRunSoftYanlz/article/details/88960085

++++Steam平台热销VRhttps://blog.csdn.net/VRunSoftYanlz/article/details/89007741

++++VR实验:以太网帧的构成https://blog.csdn.net/VRunSoftYanlz/article/details/82598140

++++实验四:存储器扩展实验https://blog.csdn.net/VRunSoftYanlz/article/details/87834434

++++FrameVR示例V0913https://blog.csdn.net/VRunSoftYanlz/article/details/82808498

++++FrameVR示例V1003https://blog.csdn.net/VRunSoftYanlz/article/details/83066516

++++SwitchMachineV1022https://blog.csdn.net/VRunSoftYanlz/article/details/83280886

++++PlaySceneManagerV1022https://blog.csdn.net/VRunSoftYanlz/article/details/83280886

++++Unity5.x用户手册https://blog.csdn.net/VRunSoftYanlz/article/details/81712741

++++Unity面试题ABChttps://blog.csdn.net/vrunsoftyanlz/article/details/78630687

++++Unity面试题Dhttps://blog.csdn.net/VRunSoftYanlz/article/details/78630838

++++Unity面试题Ehttps://blog.csdn.net/vrunsoftyanlz/article/details/78630913

++++Unity面试题Fhttps://blog.csdn.net/VRunSoftYanlz/article/details/78630945

++++Cocos2dx面试题https://blog.csdn.net/VRunSoftYanlz/article/details/78630967

++++禅道[zentao]https://blog.csdn.net/VRunSoftYanlz/article/details/83964057

++++Lua快速入门篇(Xlua拓展):https://blog.csdn.net/VRunSoftYanlz/article/details/81173818

++++Lua快速入门篇(XLua教程):https://blog.csdn.net/VRunSoftYanlz/article/details/81141502

++++Lua快速入门篇(基础概述)https://blog.csdn.net/VRunSoftYanlz/article/details/81041359

++++框架知识点https://blog.csdn.net/VRunSoftYanlz/article/details/80862879

++++游戏框架(UI框架夯实篇)https://blog.csdn.net/vrunsoftyanlz/article/details/80781140

++++游戏框架(初探篇)https://blog.csdn.net/VRunSoftYanlz/article/details/80630325

++++.Net框架设计https://blog.csdn.net/VRunSoftYanlz/article/details/87401225

++++从零开始学架构https://blog.csdn.net/VRunSoftYanlz/article/details/88095895

++++设计模式简单整理https://blog.csdn.net/vrunsoftyanlz/article/details/79839641

++++专题:设计模式(精华篇)https://blog.csdn.net/VRunSoftYanlz/article/details/81322678

++++U3D小项目参考https://blog.csdn.net/vrunsoftyanlz/article/details/80141811

++++Unity小游戏算法分析https://blog.csdn.net/VRunSoftYanlz/article/details/87908365

++++Unity案例(Vehicle)https://blog.csdn.net/VRunSoftYanlz/article/details/82355876

++++UML类图https://blog.csdn.net/vrunsoftyanlz/article/details/80289461

++++PowerDesigner简介https://blog.csdn.net/VRunSoftYanlz/article/details/86500084

++++Unity知识点0001https://blog.csdn.net/vrunsoftyanlz/article/details/80302012

++++Unity知识点0008https://blog.csdn.net/VRunSoftYanlz/article/details/81153606

++++U3D_Shader编程(第一篇:快速入门篇)https://blog.csdn.net/vrunsoftyanlz/article/details/80372071

++++U3D_Shader编程(第二篇:基础夯实篇)https://blog.csdn.net/vrunsoftyanlz/article/details/80372628

++++Unity引擎基础https://blog.csdn.net/vrunsoftyanlz/article/details/78881685

++++Unity面向组件开发https://blog.csdn.net/vrunsoftyanlz/article/details/78881752

++++Unity物理系统https://blog.csdn.net/vrunsoftyanlz/article/details/78881879

++++Unity2D平台开发https://blog.csdn.net/vrunsoftyanlz/article/details/78882034

++++UGUI基础https://blog.csdn.net/vrunsoftyanlz/article/details/78884693

++++UGUI进阶https://blog.csdn.net/vrunsoftyanlz/article/details/78884882

++++UGUI综合https://blog.csdn.net/vrunsoftyanlz/article/details/78885013

++++Unity动画系统基础https://blog.csdn.net/vrunsoftyanlz/article/details/78886068

++++Unity动画系统进阶https://blog.csdn.net/vrunsoftyanlz/article/details/78886198

++++Navigation导航系统https://blog.csdn.net/vrunsoftyanlz/article/details/78886281

++++Unity特效渲染https://blog.csdn.net/vrunsoftyanlz/article/details/78886403

++++Unity数据存储https://blog.csdn.net/vrunsoftyanlz/article/details/79251273

++++Unity中Sqlite数据库https://blog.csdn.net/vrunsoftyanlz/article/details/79254162

++++WWW类和协程https://blog.csdn.net/vrunsoftyanlz/article/details/79254559

++++Unity网络https://blog.csdn.net/vrunsoftyanlz/article/details/79254902

++++Unity资源加密https://blog.csdn.net/VRunSoftYanlz/article/details/87644514

++++PhotonServer简介https://blog.csdn.net/VRunSoftYanlz/article/details/86652770

++++编写Photon游戏服务器https://blog.csdn.net/VRunSoftYanlz/article/details/86682935

++++C#事件https://blog.csdn.net/vrunsoftyanlz/article/details/78631267

++++C#委托https://blog.csdn.net/vrunsoftyanlz/article/details/78631183

++++C#集合https://blog.csdn.net/vrunsoftyanlz/article/details/78631175

++++C#泛型https://blog.csdn.net/vrunsoftyanlz/article/details/78631141

++++C#接口https://blog.csdn.net/vrunsoftyanlz/article/details/78631122

++++C#静态类https://blog.csdn.net/vrunsoftyanlz/article/details/78630979

++++C#中System.String类https://blog.csdn.net/vrunsoftyanlz/article/details/78630945

++++C#数据类型https://blog.csdn.net/vrunsoftyanlz/article/details/78630913

++++Unity3D默认的快捷键https://blog.csdn.net/vrunsoftyanlz/article/details/78630838

++++游戏相关缩写https://blog.csdn.net/vrunsoftyanlz/article/details/78630687

++++UnityAPI.Rigidbody刚体https://blog.csdn.net/VRunSoftYanlz/article/details/81784053

++++UnityAPI.Material材质https://blog.csdn.net/VRunSoftYanlz/article/details/81814303

++++UnityAPI.Android安卓https://blog.csdn.net/VRunSoftYanlz/article/details/81843193

++++UnityAPI.AndroidJNI安卓JNIhttps://blog.csdn.net/VRunSoftYanlz/article/details/81879345

++++UnityAPI.Transform变换https://blog.csdn.net/VRunSoftYanlz/article/details/81916293

++++UnityAPI.WheelCollider轮碰撞器https://blog.csdn.net/VRunSoftYanlz/article/details/82356217

++++UnityAPI.Resources资源https://blog.csdn.net/VRunSoftYanlz/article/details/83155518

++++JSON数据结构https://blog.csdn.net/VRunSoftYanlz/article/details/82026644

++++CocosStudio快速入门https://blog.csdn.net/VRunSoftYanlz/article/details/82356839

++++Unity企业内训(目录)https://blog.csdn.net/VRunSoftYanlz/article/details/82634668

++++Unity企业内训(第1讲)https://blog.csdn.net/VRunSoftYanlz/article/details/82634733

++++Unity企业内训(第2讲)https://blog.csdn.net/VRunSoftYanlz/article/details/82861180

++++Unity企业内训(第3讲)https://blog.csdn.net/VRunSoftYanlz/article/details/82927699

++++Unity企业内训(第4讲)https://blog.csdn.net/VRunSoftYanlz/article/details/83479776

++++Unity企业内训(第5讲)https://blog.csdn.net/VRunSoftYanlz/article/details/83963811

++++Unity企业内训(第6讲)https://blog.csdn.net/VRunSoftYanlz/article/details/84207696

++++钻哥带您了解产品原型https://blog.csdn.net/VRunSoftYanlz/article/details/87303828

++++插件<Obi Rope>https://blog.csdn.net/VRunSoftYanlz/article/details/83963905

++++计算机组成原理(教材篇)https://blog.csdn.net/VRunSoftYanlz/article/details/82719129

++++5G接入:云计算和雾计算https://blog.csdn.net/VRunSoftYanlz/article/details/88372718

++++云计算通俗讲义https://blog.csdn.net/VRunSoftYanlz/article/details/88652803

++++立钻哥哥Unity 学习空间: http://blog.csdn.net/VRunSoftYanlz/

--_--VRunSoft:lovezuanzuan--_--ww4ww--_--

发布了130 篇原创文章 · 获赞 149 · 访问量 16万+

猜你喜欢

转载自blog.csdn.net/VRunSoftYanlz/article/details/89463658