一、房地产中关于射线的用处##
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());
aim = GameObject.CreatePrimitive(PrimitiveType.Sphere);
Object.Destroy(aim.transform.GetComponent());
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().material = colorMaterial;
aim.GetComponent().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().material = overlayColorMaterial;
aim.GetComponent().material = overlayColorMaterial;
}
else
{
pointer.GetComponent().material = colorMaterial;
aim.GetComponent().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
{
///
/// 事件消息的发送
///
///
///
///
public static void sendNotice(string noticeType, object data = null, string manageName = NoticeTypes.ManageName)
{
Manage.getInstance(manageName).sendNotice(noticeType, data);
}
///
/// 消息监听注册
///
///
/// Listener(string noticeType,object data=null)
///
//Listener是一个委托*******************************************************
public static void addNoticeListener(string noticeType, Listener listener,string manageName = NoticeTypes.ManageName)
{
Manage.getInstance(manageName).addNoticeListener(noticeType, listener);
}
///
/// 消息监听去除
///
///
///
///
public static void removeNoticeListener(string noticeType, Listener listener,string manageName = NoticeTypes.ManageName)
{
Manage.getInstance(manageName).removeNoticeListener(noticeType, listener);
}
///
/// 查找消息接收者对象
///tagName标记名,若标记名不为空以标记名进行管理,若标记名为空则以类名进行管理
///
///
///
public static INotice retrieveReceiver(string tagName, string manageName = NoticeTypes.ManageName)
{
return Manage.getInstance(manageName).retrieveReceiver(tagName);
}
///
/// 获取消息接收者对象注册名,若没有返回空
///
///
///
///
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
{
///
/// 监听功能函数
///
///
///
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 _manages = new Dictionary();
private Dictionary> _receiverDic;
private Dictionary _receiverClassDic;
private Dictionary _receiverTagDic;
private Dictionary> _listeners;
private List _tempReceiverWorkList;
private List _tempListenerWorkList;
private List _tempNoticeList;
private int _index = 0;
public Manage()
{
_receiverDic = new Dictionary>();
_receiverClassDic = new Dictionary();
_receiverTagDic = new Dictionary();
_listeners = new Dictionary>();
_tempReceiverWorkList = new List();
_tempListenerWorkList = new List();
_tempNoticeList = new List();
}
public static Manage getInstance(string name)
{
if (!_manages.ContainsKey(name))
{
_manages[name] = new Manage();
}
return _manages[name];
}
///
/// 某标记对象是否存在
///tagName标记名,若标记名不为空以标记名进行管理,若标记名为空则以类名进行管理
///
///
///
public bool hasReceiver(string tagName)
{
return _receiverClassDic.ContainsKey(tagName);
}
///
/// 获得监听者注册标记名
///
///
///
public string getReceiveTagName(INotice receiver)
{
if (_receiverTagDic.ContainsKey(receiver))
{
return _receiverTagDic[receiver];
}
return null;
}
///
/// 获得新添加监听者标记名
///
///
///
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;
}
///
/// 消息是否在发送状态中
/// 消息发送过程中不能对队列进行操作
///
private bool _isWorking = false;
///
/// 添加消息接收者
///tagName标记名,若标记名不为空以标记名进行管理,若标记名为空则以类名进行管理
///
///
///
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();
}
List 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);
}
}
///
/// 去除消息接收者
///tagName标记名,若标记名不为空以标记名进行管理,若标记名为空则以类名进行管理
///tagName标记名,在添加时用标记名进行管理,则去除时需提供标记名
///
///
///
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> kv in _receiverDic)
{
List list = kv.Value;
if (list.Contains(receiver))
{
list.Remove(receiver);
}
}
_receiverClassDic.Remove(tagName);
_receiverTagDic.Remove(receiver);
}
}
///
/// 发送消息
///
///
///
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 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 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);
}
}
///
/// 查找消息接收者对象
///tagName标记名,若标记名不为空以标记名进行管理,若标记名为空则以类名进行管理
///
///
///
public INotice retrieveReceiver(string tagName)
{
if (hasReceiver(tagName))
{
return _receiverClassDic[tagName] as INotice;
}
return null;
}
///
/// 功能监听添加
///
///
///
///
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();
}
List list = _listeners[noticeType];
if (!list.Contains(listener))
{
list.Add(listener);
}
}
///
/// 功能监听删除
///
///
///
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 list = _listeners[noticeType];
if (list.Contains(listener))
{
list.Remove(listener);
}
}
}
}
}
using System.Collections;
using System.Collections.Generic;
using Mvc;
public class VrNotice:MvcTool
{
///
/// ui 显示
///
public const string UI_SHOW = "ui show";
///
/// 3Dui 显示
///
public const string UI_3D_SHOW="ui 3d show";
///
/// ui 关闭
///
public const string UI_CLOSE = "ui close";
///
/// 3Dui关闭
///
public const string UI_3D_CLOSE = "ui 3d close";
///
/// 添加UI条目
///
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";
///
/// 删除UI条目
///
public const string REMOVE_UI_ITEM = "remove ui item";
///
/// 添加model条目
///
public const string ADD_MODEL_ITEM = "add model item";
///
/// 删除model条目
///
public const string REMOVE_MODEL_ITEM = "remove model item";
///
/// 场景切换
///
public const string SCENE_CHANGE = "scene change";
///
/// 没有item被选中
///
public const string NO_ITEM_SELECTED = "no item selected";
///
/// 射线
///
public const string LASER_TO = "laser to";
///
/// VR按键操作
///
public const string VR_KEY_OPER = "vr key oper";
///
/// 标记传送
///
public const string SIGN_TELEPORT = "sign teleport";
///
/// 标记传送功能
///
public const string SIGN_TELEPORT_FUN = "sign teleport fun";
///
/// 关闭传送功能标记
///
public const string CANCEL_TELEPORT_FUN = "cancel teleport fun";
///
/// 取消传送
///
public const string CANCEL_TELEPORT = "cancel teleport";
///
/// 传送
///
public const string TELEPORT = "teleport";
public const string TELEPORT_OVER = "teleport over";
///
/// 挤压传送
///
public const string GRIPPED_TELEPORT = "gripped teleport";
public const string GRIPPED_TELEPORT_OVER = "gripped teleport over";
///
/// 移动vr定位区域
///
public const string MOVE_PLAYAREA = "move play area";
///
/// 传送功能
///
public const string TELEPORT_FUN = "teleport fun";
///
/// 圆盘顺时针滑动消息
///
public const string PADGESTURE_SHUN = "pad gesture shun";
///
/// 圆盘逆时针滑动消息
///
public const string PADGESTURE_NI = "pad gesture ni";
///
/// 圆盘左滑动
///
public const string PADGESTURE_LEFT = "pad gesture left";
///
/// 圆盘右滑动
///
public const string PADGESTURE_RIGHT = "pad gesture right";
///
/// 圆盘上滑动
///
public const string PADGESTURE_UP = "pad gesture up";
///
/// 圆盘下滑动
///
public const string PADGESTURE_DOWN = "pad gesture down";
///
/// 画布提示
///
public const string PROMPT = "prompt";
///
/// 播放声音
///
public const string PLAYAUDIO = "play audio";
///
/// 停止播放声音
///
public const string STOPAUDIO = "stop audio";
///
/// 暂停播放声音
///
public const string PAUSEAUDIO = "pause audio";
///
/// 场景切换
///
public const string CHANGE_SCENE = "change scene";
///
/// 更新菜单
///
public const string UP_MENU = "up menu";
public static void socketSend(Hashtable data)
{
sendNotice(SocketClient.SOCKET_SEND, data);
}
/////
///// 切换场景
/////
///// 场景名
///// 是否加载场景界面
//public static void changeScene(string sceneName,bool isLoadSence=false)
//{
// ChangeSceneSync.getInstance().toScene(sceneName, isLoadSence);
//}
}
3.按键操作已经用委托处理了,后面就是调用了。
三、总结##
上面就是对手柄按键的交互进行了一种更好检测。不用再每帧都去对手柄按键进行检测监听。