01VR房地产中射线作用及代码了解

一、房地产中关于射线的用处##

1.用来瞬移(曲线)。
2.直线用来与物体进行交互。

二、直线射线的代码解析(与物体在场景中交互处理)##

using UnityEngine;
using System.Collections;

//通过这个代码可以控制手柄发射一条射线。
public class LaserPointer : MonoBehaviour
{
    //public bool active = true;
    public Color color;
    public float thickness = 0.002f;
    private GameObject pointer;

    public Transform launchTarget;
    private GameObject aim;

    private GameObject holder;

    private Material colorMaterial;
    private Material overlayColorMaterial;
    void Awake()
    {
        holder = new GameObject("Laser");
        //holder.transform.parent = this.transform;
         pointer = GameObject.CreatePrimitive(PrimitiveType.Cube);
        pointer.transform.parent = holder.transform;
        pointer.transform.localScale = new Vector3(thickness, thickness, 100f);
        pointer.transform.localPosition = new Vector3( 0f, 0f, 50f);
        Object.Destroy(pointer.transform.GetComponent<Collider>());
        aim = GameObject.CreatePrimitive(PrimitiveType.Sphere);
        Object.Destroy(aim.transform.GetComponent<Collider>());
        aim.transform.parent = holder.transform;
        aim.transform.localScale = new Vector3(thickness*5, thickness*5, thickness*5);
        aim.transform.localPosition = Vector3.zero;

        if (colorMaterial == null)
        {
            colorMaterial = new Material(Shader.Find("MyShader/Color"));
        }
        colorMaterial.SetColor("_Color", color);
        pointer.GetComponent<MeshRenderer>().material = colorMaterial;
        aim.GetComponent<MeshRenderer>().material = colorMaterial;
        if (overlayColorMaterial == null)
        {
            overlayColorMaterial = new Material(Shader.Find("MyShader/ColorOverlay"));
        }
        overlayColorMaterial.SetColor("_Color", color);
        if (launchTarget==null)
        {
            launchTarget = this.transform;
        }
    }

    public bool isWorking
    {
        get
        {
            if(holder)
            {
                return holder.activeSelf;
            }
            return false;
        }
        set
        {
            if (holder)
            {
                holder.SetActive(value);
            }
        }
    }

    private bool _isOver = false;
   
    public void setValue(Vector3 position,Vector3 forward, float distance,bool isOver=false)
    {
        //isOver = true;
        if (holder != null)
        {
            
            pointer.transform.localScale = new Vector3(thickness, thickness, distance);
            pointer.transform.localPosition = new Vector3(0f, 0f, distance / 2f);
            holder.transform.position = position;
            holder.transform.forward = forward;
            aim.transform.position = position + forward.normalized * distance;

            if (isOver != _isOver)
            {
                _isOver = isOver;
                if (isOver)
                {
                    pointer.GetComponent<MeshRenderer>().material = overlayColorMaterial;
                    aim.GetComponent<MeshRenderer>().material = overlayColorMaterial;
                }
                else
                {
                    pointer.GetComponent<MeshRenderer>().material = colorMaterial;
                    aim.GetComponent<MeshRenderer>().material = colorMaterial;
                }

            }


        }
    }

    public void setValue(Vector3 startPos,Vector3 endPos, bool isOver = false)
    {
        Vector3 forward = endPos - startPos;
        setValue(startPos, forward, Vector3.Distance(endPos,startPos),isOver);
    }


   
}

二、特定要求检测射线的发出(比如:按下Trigger才发射射线出来)射线的长度(只显示从手柄到我们进行交互物体的距离)—————————————————————这里用监听进行按键的检测。

                      公司有一套架构,做了一套架构用来检测手柄交互(按键信息的检测)

三、架构信息简单理解。

using System;
using Mvc.Base;

namespace Mvc
{
   
    public class MvcTool
    {
        /// <summary>
        /// 事件消息的发送
        /// </summary>
        /// <param name="noticeType"></param>
        /// <param name="data"></param>
        /// <param name="manageName"></param>
        public static void sendNotice(string noticeType, object data = null, string manageName = NoticeTypes.ManageName)
        {
            Manage.getInstance(manageName).sendNotice(noticeType, data);
        }

        /// <summary>
        /// 消息监听注册
        /// </summary>
        /// <param name="noticeType"></param>
        /// <param name="listener">Listener(string noticeType,object data=null)</param>
        /// <param name="data"></param>

      //Listener是一个委托*******************************************************

        public static void addNoticeListener(string noticeType, Listener listener,string manageName = NoticeTypes.ManageName)
        {
            Manage.getInstance(manageName).addNoticeListener(noticeType, listener);
        }

        /// <summary>
        /// 消息监听去除
        /// </summary>
        /// <param name="noticeType"></param>
        /// <param name="listener"></param>
        /// <param name="manageName"></param>
        public static void removeNoticeListener(string noticeType, Listener listener,string manageName = NoticeTypes.ManageName)
        {
            Manage.getInstance(manageName).removeNoticeListener(noticeType, listener);
        }
        /// <summary>
        /// 查找消息接收者对象
        ///tagName标记名,若标记名不为空以标记名进行管理,若标记名为空则以类名进行管理
        /// </summary>
        /// <param name="?"></param>
        /// <returns></returns>
        public static INotice retrieveReceiver(string tagName, string manageName = NoticeTypes.ManageName)
        {
            return Manage.getInstance(manageName).retrieveReceiver(tagName);
        }

        /// <summary>
        /// 获取消息接收者对象注册名,若没有返回空
        /// </summary>
        /// <param name="receiver"></param>
        /// <param name="manageName"></param>
        /// <returns></returns>
        public static string getReceiveTagName(INotice receiver,string manageName = NoticeTypes.ManageName)
        {
            return Manage.getInstance(manageName).getReceiveTagName(receiver);
        }


    }
}


理解委托信息


using System;
using System.Collections.Generic;
using UnityEngine;

namespace Mvc.Base
{
    /// <summary>
    /// 监听功能函数
    /// </summary>
    /// <param name="noticeType"></param>
    /// <param name="data"></param>
    public delegate void Listener(string noticeType, object data = null);

    internal struct TempReceiver
    {
        internal INotice receiver;
        internal string tagName;

        internal bool isAdd;
    }

    internal struct TempListener
    {
        internal string noticeType;
        internal Listener listener;
        internal bool isAdd;
    }

    internal struct TempNotice
    {
        internal string noticeType;
        internal object data;
    }
    public class Manage
    {
        private static Dictionary<string, Manage> _manages = new Dictionary<string, Manage>();
        private Dictionary<string, List<INotice>> _receiverDic;
        private Dictionary<string, INotice> _receiverClassDic;
        private Dictionary<INotice, string> _receiverTagDic;

        private Dictionary<string, List<Listener>> _listeners;

        private List<TempReceiver> _tempReceiverWorkList;
        private List<TempListener> _tempListenerWorkList;
        private List<TempNotice> _tempNoticeList;

        private int _index = 0;

        public Manage()
        {
            _receiverDic = new Dictionary<string, List<INotice>>();
            _receiverClassDic = new Dictionary<string, INotice>();
            _receiverTagDic = new Dictionary<INotice, string>();

            _listeners = new Dictionary<string, List<Listener>>();

            _tempReceiverWorkList = new List<TempReceiver>();
            _tempListenerWorkList = new List<TempListener>();
            _tempNoticeList = new List<TempNotice>();
        }

        public static Manage getInstance(string name)
        {
            if (!_manages.ContainsKey(name))
            {
                _manages[name] = new Manage();
            }
            return _manages[name];
        }

        /// <summary>
        /// 某标记对象是否存在
        ///tagName标记名,若标记名不为空以标记名进行管理,若标记名为空则以类名进行管理
        /// </summary>
        /// <param name="tagName"></param>
        /// <returns></returns>
        public bool hasReceiver(string tagName)
        {
            return _receiverClassDic.ContainsKey(tagName);
        }

        /// <summary>
        /// 获得监听者注册标记名
        /// </summary>
        /// <param name="receiver"></param>
        /// <returns></returns>
        public string getReceiveTagName(INotice receiver)
        {
            if (_receiverTagDic.ContainsKey(receiver))
            {
                return _receiverTagDic[receiver];
            }
            return null;
        }
        /// <summary>
        /// 获得新添加监听者标记名
        /// </summary>
        /// <param name="receiver"></param>
        /// <returns></returns>
        private string getAddReceiveDefaultTagName(INotice receiver)
        {
            if (_receiverTagDic.ContainsKey(receiver))
            {
                return _receiverTagDic[receiver];
            }
            Type type = receiver.GetType();
            _index++;
            string tagName = type.Name + _index.ToString();
            return tagName;
        }
        /// <summary>
        /// 消息是否在发送状态中
        /// 消息发送过程中不能对队列进行操作
        /// </summary>
        private bool _isWorking = false;
        /// <summary>
        /// 添加消息接收者
        ///tagName标记名,若标记名不为空以标记名进行管理,若标记名为空则以类名进行管理
        /// </summary>
        /// <param name="receiver"></param>
        /// <param name="tagName"></param>
        public void addNoticeReceiver(INotice receiver, string tagName = null)
        {

            if (_isWorking)
            {//在消息发送过程中,注册延后 
                TempReceiver temp = new TempReceiver();
                temp.receiver = receiver;
                temp.tagName = tagName;
                temp.isAdd = true;
                _tempReceiverWorkList.Add(temp);
                return;
            }
            if (tagName == null)
            {
                tagName = getAddReceiveDefaultTagName(receiver);
            }
            if (!_receiverTagDic.ContainsKey(receiver))
            {

                if (!hasReceiver(tagName))
                {
                    string[] arr = receiver.listNoticeTypes();
                    foreach (string noticeType in arr)
                    {
                        if (!_receiverDic.ContainsKey(noticeType))
                        {
                            _receiverDic[noticeType] = new List<INotice>();
                        }
                        List<INotice> list = _receiverDic[noticeType];

                        if (!list.Contains(receiver))
                        {
                            int priority = receiver.getPriority();
                            if (receiver.getPriority() < 0)
                            {
                                list.Add(receiver);
                            }
                            else
                            {
                                int count = list.Count;
                                bool isIn = false;
                                for (int j = 0; j < count; j++)
                                {
                                    if (priority > list[j].getPriority())
                                    {
                                        list.Insert(j, receiver);
                                        isIn = true;
                                        break;
                                    }
                                }
                                if (isIn)
                                {
                                    list.Add(receiver);
                                }
                            }
                        }
                    }
                    _receiverClassDic[tagName] = receiver;
                    _receiverTagDic[receiver] = tagName;
                }
                else
                {
                    Debug.LogError("该标记名已经存在" + tagName);
                    throw new Exception("该标记名已经存在" + tagName);
                }

            }
            else
            {
                Debug.LogError("该消息接收者已经存在" + tagName);
                throw new Exception("该消息接收者已经存在" + tagName);
            }
        }

        /// <summary>
        /// 去除消息接收者
        ///tagName标记名,若标记名不为空以标记名进行管理,若标记名为空则以类名进行管理
        ///tagName标记名,在添加时用标记名进行管理,则去除时需提供标记名
        /// </summary>
        /// <param name="?"></param>
        /// <returns></returns>
        public void removeNoticeReceiver(INotice receiver, string tagName = null)
        {
            if (_isWorking)
            {//在消息发送过程中,注册延后 
                TempReceiver temp = new TempReceiver();
                temp.receiver = receiver;
                temp.tagName = tagName;
                temp.isAdd = false;
                _tempReceiverWorkList.Add(temp);
                return;
            }
            if (tagName == null)
            {
                tagName = getAddReceiveDefaultTagName(receiver);
            }
            if (hasReceiver(tagName))
            {
                foreach (KeyValuePair<string, List<INotice>> kv in _receiverDic)
                {
                    List<INotice> list = kv.Value;
                    if (list.Contains(receiver))
                    {
                        list.Remove(receiver);
                    }
                }
                _receiverClassDic.Remove(tagName);
                _receiverTagDic.Remove(receiver);
            }
        }

        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="?"></param>
        /// <returns></returns>
        public void sendNotice(string noticeType, object data = null)
        {
            if (_isWorking)
            {
                TempNotice tempNotice = new TempNotice();
                tempNotice.noticeType = noticeType;
                tempNotice.data = data;
                _tempNoticeList.Add(tempNotice);
                return;
            }
            _isWorking = true;

            if (_receiverDic.ContainsKey(noticeType))
            {
                List<INotice> list = _receiverDic[noticeType];
                foreach (INotice receiver in list)
                {


#if !UNITY_EDITOR
                    try
                    {
#endif
                    receiver.handlerNotice(noticeType, data);
#if !UNITY_EDITOR
                    }
                    catch (Exception e)
                    {
                        Type type = receiver.GetType();
                        Debug.LogError("INotice Error>>> noticeType:[" + noticeType + "] receiver:[" + type.Name + "]");
                    }
#endif
                }
            }

            if (_listeners.ContainsKey(noticeType))
            {
                List<Listener> list = _listeners[noticeType];
                foreach (Listener listener in list)
                {
#if !UNITY_EDITOR
                    try
                    {
#endif
                    listener(noticeType, data);
#if !UNITY_EDITOR
                    }
                    catch (Exception e)
                    {
                        Debug.LogError("Listener Error");
                    }
#endif
                }
            }

            _isWorking = false;
            if (_tempReceiverWorkList.Count > 0)
            {
                foreach (TempReceiver temp in _tempReceiverWorkList)
                {
                    if (temp.isAdd)
                    {
                        addNoticeReceiver(temp.receiver, temp.tagName);
                    }
                    else
                    {
                        removeNoticeReceiver(temp.receiver, temp.tagName);
                    }
                }
                _tempReceiverWorkList.Clear();
            }
            if (_tempListenerWorkList.Count > 0)
            {
                foreach (TempListener temp in _tempListenerWorkList)
                {
                    if (temp.isAdd)
                    {
                        addNoticeListener(temp.noticeType, temp.listener);

                    }
                    else
                    {
                        removeNoticeListener(temp.noticeType, temp.listener);
                    }
                }
                _tempListenerWorkList.Clear();
            }

            if (_tempNoticeList.Count > 0)
            {
                TempNotice tempNotice = _tempNoticeList[0];
                _tempNoticeList.RemoveAt(0);
                sendNotice(tempNotice.noticeType, tempNotice.data);
            }
        }



        /// <summary>
        /// 查找消息接收者对象
        ///tagName标记名,若标记名不为空以标记名进行管理,若标记名为空则以类名进行管理
        /// </summary>
        /// <param name="?"></param>
        /// <returns></returns>
        public INotice retrieveReceiver(string tagName)
        {
            if (hasReceiver(tagName))
            {
                return _receiverClassDic[tagName] as INotice;
            }
            return null;
        }

        /// <summary>
        /// 功能监听添加
        /// </summary>
        /// <param name="noticeType"></param>
        /// <param name="listener"></param>
        /// <param name="data"></param>
        public void addNoticeListener(string noticeType, Listener listener)
        {
            if (_isWorking)
            {//在消息发送过程中,注册延后 
                TempListener temp = new TempListener();
                temp.noticeType = noticeType;
                temp.listener = listener;
                temp.isAdd = true;
                _tempListenerWorkList.Add(temp);
                return;
            }
            if (!_listeners.ContainsKey(noticeType))
            {
                _listeners[noticeType] = new List<Listener>();
            }
            List<Listener> list = _listeners[noticeType];
            if (!list.Contains(listener))
            {
                list.Add(listener);
            }
        }
        /// <summary>
        /// 功能监听删除
        /// </summary>
        /// <param name="noticeType"></param>
        /// <param name="listener"></param>
        public void removeNoticeListener(string noticeType, Listener listener)
        {
            if (_isWorking)
            {//在消息发送过程中,注册延后 
                TempListener temp = new TempListener();
                temp.noticeType = noticeType;
                temp.listener = listener;
                temp.isAdd = false;
                _tempListenerWorkList.Add(temp);
                return;
            }
            if (_listeners.ContainsKey(noticeType))
            {
                List<Listener> list = _listeners[noticeType];
                if (list.Contains(listener))
                {
                    list.Remove(listener);
                }
            }
        }
    }
}

using System.Collections;
using System.Collections.Generic;
using Mvc;


public class VrNotice:MvcTool
{
   
    /// <summary>
    /// ui 显示
    /// </summary>
    public const string UI_SHOW = "ui show";
    /// <summary>
    /// 3Dui 显示
    /// </summary>
    public const string UI_3D_SHOW="ui 3d show";
    /// <summary>
    /// ui 关闭
    /// </summary>
    public const string UI_CLOSE = "ui close";
    /// <summary>
    /// 3Dui关闭
    /// </summary>
    public const string UI_3D_CLOSE = "ui 3d close";
    /// <summary>
    /// 添加UI条目
    /// </summary>
    public const string ADD_UI_ITEM = "add ui item";

    public const string ADD_RAY_ITEM = "add ray item";

    public const string REMOVE_RAY_ITEM = "remove ray item";
    /// <summary>
    /// 删除UI条目
    /// </summary>
    public const string REMOVE_UI_ITEM = "remove ui item";
    /// <summary>
    /// 添加model条目
    /// </summary>
    public const string ADD_MODEL_ITEM = "add model item";
    /// <summary>
    /// 删除model条目
    /// </summary>
    public const string REMOVE_MODEL_ITEM = "remove model item";
    /// <summary>
    /// 场景切换
    /// </summary>
    public const string SCENE_CHANGE = "scene change";
    /// <summary>
    /// 没有item被选中
    /// </summary>
    public const string NO_ITEM_SELECTED = "no item selected";
    /// <summary>
    /// 射线
    /// </summary>
    public const string LASER_TO = "laser to";
    /// <summary>
    /// VR按键操作
    /// </summary>
    public const string VR_KEY_OPER = "vr key oper";
    /// <summary>
    /// 标记传送
    /// </summary>
    public const string SIGN_TELEPORT = "sign teleport";
    /// <summary>
    /// 标记传送功能
    /// </summary>
    public const string SIGN_TELEPORT_FUN = "sign teleport fun";
    /// <summary>
    /// 关闭传送功能标记
    /// </summary>
    public const string CANCEL_TELEPORT_FUN = "cancel teleport fun";
    /// <summary>
    /// 取消传送
    /// </summary>
    public const string CANCEL_TELEPORT = "cancel teleport";
    /// <summary>
    /// 传送
    /// </summary>
    public const string TELEPORT = "teleport";
    public const string TELEPORT_OVER = "teleport over";
    /// <summary>
    /// 挤压传送
    /// </summary>
    public const string GRIPPED_TELEPORT = "gripped teleport";
    public const string GRIPPED_TELEPORT_OVER = "gripped teleport over";
    /// <summary>
    /// 移动vr定位区域
    /// </summary>
    public const string MOVE_PLAYAREA = "move play area";
    /// <summary>
    /// 传送功能
    /// </summary>
    public const string TELEPORT_FUN = "teleport fun";

    /// <summary>
    /// 圆盘顺时针滑动消息
    /// </summary>
    public const string PADGESTURE_SHUN = "pad gesture shun";

    /// <summary>
    /// 圆盘逆时针滑动消息
    /// </summary>
    public const string PADGESTURE_NI = "pad gesture ni";

    /// <summary>
    /// 圆盘左滑动
    /// </summary>
    public const string PADGESTURE_LEFT = "pad gesture left";
    /// <summary>
    /// 圆盘右滑动
    /// </summary>
    public const string PADGESTURE_RIGHT = "pad gesture right";
    /// <summary>
    /// 圆盘上滑动
    /// </summary>
    public const string PADGESTURE_UP = "pad gesture up";
    /// <summary>
    /// 圆盘下滑动
    /// </summary>
    public const string PADGESTURE_DOWN = "pad gesture down";

    /// <summary>
    /// 画布提示
    /// </summary>
    public const string PROMPT = "prompt";

    /// <summary>
    /// 播放声音
    /// </summary>
    public const string PLAYAUDIO = "play audio";

    /// <summary>
    /// 停止播放声音
    /// </summary>
    public const string STOPAUDIO = "stop audio";

    /// <summary>
    /// 暂停播放声音
    /// </summary>
    public const string PAUSEAUDIO = "pause audio";
    /// <summary>
    /// 场景切换
    /// </summary>
    public const string CHANGE_SCENE = "change scene";
    /// <summary>
    /// 更新菜单
    /// </summary>
    public const string UP_MENU = "up menu";

    public static void socketSend(Hashtable data)
    {
        sendNotice(SocketClient.SOCKET_SEND, data);
    }

    ///// <summary>
    ///// 切换场景
    ///// </summary>
    ///// <param name="sceneName">场景名</param>
    ///// <param name="isLoadSence">是否加载场景界面</param>
    //public static void changeScene(string sceneName,bool isLoadSence=false)
    //{
    //    ChangeSceneSync.getInstance().toScene(sceneName, isLoadSence);
    //}
}

3.按键操作已经用委托处理了,后面就是调用了。

一开始进行监听
监听后的处理操作
监听的移除

三、总结##

上面就是对手柄按键的交互进行了一种更好检测。不用再每帧都去对手柄按键进行检测监听。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容

  • 在我们的游戏开发过程中,有一个很重要的工作就是进行碰撞检测。例如在射击游戏中子弹是否击中敌人,在RPG游戏中是否捡...
    壹米玖坤阅读 24,167评论 0 17
  • VRTK是由一些大神对SteamVR进行一定的优化后封装出来的便捷快速VR开发工具,下面一步一步来了解这个神插件。...
    砍了那只鸭阅读 7,246评论 3 15
  • 本文来源于两年前我的一篇CSDN博客。CSDN博客本来就没写多少,现在也基本是到简书上混了。所以各位大大请自觉绕过...
    晓梦蝉君阅读 42,500评论 5 12
  • 那只停下了的笔,搁浅在纸上 有墨还在肢体里,散发出幽香 似怀念笔尖触纸,流畅的语句 和一些繁复情绪,铺写成故事 你...
    木九月阅读 449评论 4 6
  • 时间一直走,没有尽头,只有路口。我们总是以为,没有尽头的时光是用来虚度的,所以一而再再而三地浪费光阴。殊不...
    莉莉安L阅读 260评论 5 2