一、房地产中关于射线的用处##
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.按键操作已经用委托处理了,后面就是调用了。
三、总结##
上面就是对手柄按键的交互进行了一种更好检测。不用再每帧都去对手柄按键进行检测监听。