unity接了deepoon m2,打包出来执行场景有物体严重重影怎么回事

Unity版本与虚拟现实头盔Deepoon大朋版本测试
Unity版本与虚拟现实头盔Deepoon大朋版本测试
本文章由cartzhang编写,转载请注明出处。 所有权利保留。
文章链接:
作者:cartzhang
OCulus DK2比较贵,再说,现在大家开始哄抢CV1,我本着有啥资源,就开弄的原则。
测试了下,我能用的手边有的大朋Deepoon头盔。
一、看这里
Unity官方与OC runtime版本兼容性说明:
需要测试的是Unity与大朋,Unity与DK2 runtime的版本。
先说,Oculus Dk2,现有的Unity版本5.3.0版,测试过,直接PlayerSetting中勾选Virtual Reality Supported,OC runtime版本0.8.0,直接肯定是没有问题的嘛。
在编辑器模式下,直接可以在DK2头盔中看到效果。
既然这样,我就顺带把大朋拿来用用,同样环境,大鹏插上,同样可用,也可以在大朋VR头盔中看到Unity编辑效果。
三、Unity5.1版本搭配大鹏0.4版本
说明使用的是大朋特别定制版本的,内部版本号:1.2.4.81,对于OC runtime版本为0.6.0.1,不要问我咋知道的,我们是定制啊。
大朋有个切换模式,我需要Dk2模式,切换到Dk2模型下。
在Unity版本为5.1.1版本,编辑器模型下,同样勾选PlayerSetting中勾选Virtual Reality Supported,结果发现,大朋头盔上可以用的,完全没有问题。
但是在Unity5.3版本下,同样设置,大朋则不可用。这个是Unity官方都说了,5.3针对VR做了优化处理,必须要匹配OC runtime 0.8.0版本,还有可能需要更新显卡驱动。
当然,驱动我都更新过了。
所以,所做实验是真实可靠的啊。
四、做个表格,方便看
—————THE ———————-END———
以上,就是这样!!!
若有问题,请随时联系!
非常感谢!!
我的热门文章
即使是一小步也想与你分享1716人阅读
Unity(38)
本文章由cartzhang编写,转载请注明出处。 所有权利保留。
文章链接:
作者:cartzhang
OCulus DK2比较贵,再说,现在大家开始哄抢CV1,我本着有啥资源,就开弄的原则。
测试了下,我能用的手边有的大朋Deepoon头盔。
一、看这里
Unity官方与OC runtime版本兼容性说明:
需要测试的是Unity与大朋,Unity与DK2 runtime的版本。
先说,Oculus Dk2,现有的Unity版本5.3.0版,测试过,直接PlayerSetting中勾选Virtual Reality Supported,OC runtime版本0.8.0,直接肯定是没有问题的嘛。
在编辑器模式下,直接可以在DK2头盔中看到效果。
既然这样,我就顺带把大朋拿来用用,同样环境,大鹏插上,同样可用,也可以在大朋VR头盔中看到Unity编辑效果。
三、Unity5.1版本搭配大鹏0.4版本
说明使用的是大朋特别定制版本的,内部版本号:1.2.4.81,对于OC runtime版本为0.6.0.1,不要问我咋知道的,我们是定制啊。
大朋有个切换模式,我需要Dk2模式,切换到Dk2模型下。
在Unity版本为5.1.1版本,编辑器模型下,同样勾选PlayerSetting中勾选Virtual Reality Supported,结果发现,大朋头盔上可以用的,完全没有问题。
但是在Unity5.3版本下,同样设置,大朋则不可用。这个是Unity官方都说了,5.3针对VR做了优化处理,必须要匹配OC runtime 0.8.0版本,还有可能需要更新显卡驱动。
当然,驱动我都更新过了。
所以,所做实验是真实可靠的啊。
四、做个表格,方便看
—————THE ———————-END———
以上,就是这样!!!
若有问题,请随时联系!
非常感谢!!
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:115752次
积分:2145
积分:2145
排名:第13044名
原创:73篇
译文:19篇
评论:51条
文章:15篇
阅读:23548
文章:24篇
阅读:26967
文章:15篇
阅读:24621君,已阅读到文档的结尾了呢~~
2016年度精品--Unity3D输出安卓无法正常显示,重影的问题及解决办法
扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
2016年度精品--Unity3D输出安卓无法正常显示,重影的问题及解决办法
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='/DocinViewer--144.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口Unity 实现Log实时输出到屏幕或控制台上&一& - [ Unity5学习记录 ] - 看云
本文章由cartzhang编写,转载请注明出处。 所有权利保留。
文章链接:
作者:cartzhang
一、Unity 打印日志
Unity中,在其编辑器上有个专门的Console,快捷键:shift + Ctrl+ c 。
代码中的Debug.Log("this is a test");就会打印到这里。
但是在打包后,只有从Log中找到,能不能找到一个可以实时显示的工具呢?
很明显,必须有啊!!要不写这篇不就是瞎扯了么?!!
我辗转腾挪,到处寻觅,我肯定不是第一个有这个想法的人。
终于有一天,我来到了七环!!!找到了几种方法,与君共享!!
二、我想有个控制台
之前说的Debug.Log();此函数是打印Unity控制台的。
好办,有高人已经重新把控制台给换了地方,打印到界面的控制台上。
就是类似控制台的一个界面。
先放结果图样:
1.问题来了,怎么实现的呢?
我给改了名字叫TestConsole.cs了,因为之前名字为Console,这样想我这样都在一个工程中为大家测试,容易造成混乱。
//#define USE_TESTCONSOLE
using System.Collections.G
using UnityE
namespace Consolation
/// &summary&
/// A console to display Unity's debug logs in-game.
/// &/summary&
class TestConsole : MonoBehaviour
#if USE_TESTCONSOLE
struct Log
public string stackT
public LogT
#region Inspector Settings
/// &summary&
/// The hotkey to show and hide the console window.
/// &/summary&
public KeyCode toggleKey = KeyCode.BackQ
/// &summary&
/// Whether to open the window by shaking the device (mobile-only).
/// &/summary&
public bool shakeToOpen =
/// &summary&
/// The (squared) acceleration above which the window should open.
/// &/summary&
public float shakeAcceleration = 3f;
/// &summary&
/// Whether to only keep a certain number of logs.
/// Setting this can be helpful if memory usage is a concern.
/// &/summary&
public bool restrictLogCount =
/// &summary&
/// Number of logs to keep before removing old ones.
/// &/summary&
public int maxLogs = 1000;
#endregion
readonly List&Log& logs = new List&Log&();
Vector2 scrollP
// Visual elements:
static readonly Dictionary&LogType, Color& logTypeColors = new Dictionary&LogType, Color&
{ LogType.Assert, Color.white },
{ LogType.Error, Color.red },
{ LogType.Exception, Color.red },
{ LogType.Log, Color.white },
{ LogType.Warning, Color.yellow },
const string windowTitle = "Console";
const int margin = 20;
static readonly GUIContent clearLabel = new GUIContent("Clear", "Clear the contents of the console.");
static readonly GUIContent collapseLabel = new GUIContent("Collapse", "Hide repeated messages.");
readonly Rect titleBarRect = new Rect(0, 0, 10000, 20);
Rect windowRect = new Rect(margin, margin, Screen.width - (margin * 2), Screen.height - (margin * 2));
void OnEnable()
#if UNITY_5
Application.logMessageReceived += HandleL
Application.RegisterLogCallback(HandleLog);
void OnDisable()
#if UNITY_5
Application.logMessageReceived -= HandleL
Application.RegisterLogCallback(null);
void Update()
if (Input.GetKeyDown(toggleKey))
visible = !
if (shakeToOpen && Input.acceleration.sqrMagnitude & shakeAcceleration)
void OnGUI()
if (!visible)
windowRect = GUILayout.Window(123456, windowRect, DrawConsoleWindow, windowTitle);
/// &summary&
/// Displays a window that lists the recorded logs.
/// &/summary&
/// &param name="windowID"&Window ID.&/param&
void DrawConsoleWindow(int windowID)
DrawLogsList();
DrawToolbar();
// Allow the window to be dragged by its title bar.
GUI.DragWindow(titleBarRect);
/// &summary&
/// Displays a scrollable list of logs.
/// &/summary&
void DrawLogsList()
scrollPosition = GUILayout.BeginScrollView(scrollPosition);
// Iterate through the recorded logs.
for (var i = 0; i & logs.C i++)
var log = logs[i];
// Combine identical messages if collapse option is chosen.
if (collapse && i & 0)
var previousMessage = logs[i - 1].
if (log.message == previousMessage)
GUI.contentColor = logTypeColors[log.type];
GUILayout.Label(log.message);
GUILayout.EndScrollView();
// Ensure GUI colour is reset before drawing other components.
GUI.contentColor = Color.
/// &summary&
/// Displays options for filtering and changing the logs list.
/// &/summary&
void DrawToolbar()
GUILayout.BeginHorizontal();
if (GUILayout.Button(clearLabel))
logs.Clear();
collapse = GUILayout.Toggle(collapse, collapseLabel, GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal();
/// &summary&
/// Records a log from the log callback.
/// &/summary&
/// &param name="message"&Message.&/param&
/// &param name="stackTrace"&Trace of where the message came from.&/param&
/// &param name="type"&Type of message (error, exception, warning, assert).&/param&
void HandleLog(string message, string stackTrace, LogType type)
logs.Add(new Log
message = message,
stackTrace = stackTrace,
type = type,
TrimExcessLogs();
/// &summary&
/// Removes old logs that exceed the maximum number allowed.
/// &/summary&
void TrimExcessLogs()
if (!restrictLogCount)
var amountToRemove = Mathf.Max(logs.Count - maxLogs, 0);
if (amountToRemove == 0)
logs.RemoveRange(0, amountToRemove);
我在代码最前面添加了宏定义,使用的时候屏蔽此宏定义即可。
2.怎么使用呢?
恩。我写的使用很简单。
随便写个C#代码,在Update中测试的。
// Update is called once per frame
void Update ()
//DebugConsole.Log(" test s");
Debug.Log("Debug log
Console.WriteLine("this is Console Write line test ");
//DebugConsole.instance.AddMessage("this is instance AddMessage test by cartzhang", "warning");
//DebugConsole.Log("this is debug console log test cartzhang");
3.结果上面已经说明了。
这里就不重复了。
4.这怎么实现的呢?
原理很简单。写一个面板,往上面写字啊!
说下啊,这个有个切换按键,就是可以控制是否显示这个面板的,按键为BackQuote,你也可以修改,BackQuote这个键呢,在ESC按键的下面就是这个“~”。
三、这不是我想要的,我要显示在屏幕上。
我想要显示在控制台上,就是CMD出来的那样。
1. 直接写在屏幕上的代码
不过,我先赠送一个显示在屏幕上的。
这样我觉得大部分的人就会满足了,最起码不用自己写GUI .Label()了啊。
说明这个是国外友人好早之前写的,我只改变了其中某些不符合现在Unity 5 的语句,其他没有动。
还是代码:
/*==== DebugConsole.cs ====================================================
* Class for handling multi-line, multi-color debugging messages.
* Original Author: Jeremy Hollingsworth
* Based On: Version 1.2.1 Mar 02, 2006
* Modified: Simon Waite
* Date: 22 Feb 2007
* Modification to original script to allow pixel-correct line spacing
* Setting the boolean pixelCorrect changes the units in lineSpacing property
* to pixels, so you have a pixel correct gui font in your console.
* It also checks every frame if the screen is resized to make sure the
* line spacing is correct (T drag and let go in the editor
* and the text spacing will snap back)
* ::Drop in your standard assets folder (if you want to change any of the
* default settings in the inspector, create an empty GameObject and attach
* this script to it from you standard assets folder.
That will provide
* access to the default settings in the inspector)
* ::To use, call DebugConsole.functionOrProperty() where
* functionOrProperty = one of the following:
* -Log(string message, string color)
Adds "message" to the list with the
* "color" color. Color is optional and can be any of the following: "error",
* "warning", or "normal".
Default is normal.
* Clear() Clears all messages
* isVisible (true,false)
Toggles the visibility of the output.
Does _not_
* clear the messages.
* isDraggable (true, false)
Toggles mouse drag functionality
* =========================================================================*/
//#define USE_DEBUGCONSOLE
using UnityE
using System.C
public class DebugConsole : MonoBehaviour
#if USE_DEBUGCONSOLE
public GameObject DebugGui =
// The GUI that will be duplicated
public Vector3 defaultGuiPosition = new Vector3(0.01F, 0.98F, 0F);
public Vector3 defaultGuiScale = new Vector3(0.5F, 0.5F, 1F);
public Color normal = Color.
public Color warning = Color.
public Color error = Color.
public int maxMessages = 30;
// The max number of messages displayed
public float lineSpacing = 0.02F;
// The amount of space between lines
public ArrayList messages = new ArrayList();
public ArrayList guis = new ArrayList();
public ArrayList colors = new ArrayList();
public bool draggable =
// Can the output be dragged around at runtime by default?
public bool visible =
// Does output show on screen by default or do we have to enable it with code?
public bool pixelCorrect = // set to be pixel Correct linespacing
public static bool isVisible
return DebugConsole.instance.
DebugConsole.instance.visible =
if (value == true)
DebugConsole.instance.Display();
else if (value == false)
DebugConsole.instance.ClearScreen();
public static bool isDraggable
return DebugConsole.instance.
DebugConsole.instance.draggable =
private static DebugConsole s_Instance =
// Our instance to allow this script to be called without a direct connection.
public static DebugConsole instance
if (s_Instance == null)
s_Instance = FindObjectOfType(typeof(DebugConsole)) as DebugC
if (s_Instance == null)
GameObject console = new GameObject();
console.AddComponent&DebugConsole&();
console.name = "DebugConsoleController";
s_Instance = FindObjectOfType(typeof(DebugConsole)) as DebugC
DebugConsole.instance.InitGuis();
return s_I
void Awake()
s_Instance =
InitGuis();
protected bool guisCreated =
protected float screenHeight =-1;
public void InitGuis()
float usedLineSpacing = lineS
screenHeight = Screen.
if(pixelCorrect)
usedLineSpacing = 1.0F / screenHeight * usedLineS
if (guisCreated == false)
if (DebugGui == null)
// If an external GUIText is not set, provide the default GUIText
DebugGui = new GameObject();
DebugGui.AddComponent&GUIText&();
DebugGui.name = "DebugGUI(0)";
DebugGui.transform.position = defaultGuiP
DebugGui.transform.localScale = defaultGuiS
// Create our GUI objects to our maxMessages count
Vector3 position = DebugGui.transform.
guis.Add(DebugGui);
int x = 1;
while (x & maxMessages)
position.y -= usedLineS
GameObject clone =
clone = (GameObject)Instantiate(DebugGui, position, transform.rotation);
clone.name = string.Format("DebugGUI({0})", x);
guis.Add(clone);
position = clone.transform.
while (x & guis.Count)
GameObject temp = (GameObject)guis[x];
temp.transform.parent = DebugGui.
guisCreated =
// we're called on a screensize change, so fiddle with sizes
Vector3 position = DebugGui.transform.
for(int x=0;x & guis.C x++)
position.y -= usedLineS
GameObject temp = (GameObject)guis[x];
temp.transform.position=
bool connectedToMouse =
void Update()
// If we are visible and the screenHeight has changed, reset linespacing
if (visible == true && screenHeight != Screen.height)
InitGuis();
if (draggable == true)
if (Input.GetMouseButtonDown(0))
if (connectedToMouse == false && DebugGui.GetComponent&GUIText&().HitTest((Vector3)Input.mousePosition) == true)
connectedToMouse =
else if (connectedToMouse == true)
connectedToMouse =
if (connectedToMouse == true)
float posX = DebugGui.transform.position.x;
float posY = DebugGui.transform.position.y;
posX = Input.mousePosition.x / Screen.
posY = Input.mousePosition.y / Screen.
DebugGui.transform.position = new Vector3(posX, posY, 0F);
//+++++++++ INTERFACE FUNCTIONS ++++++++++++++++++++++++++++++++
public static void Log(string message, string color)
DebugConsole.instance.AddMessage(message, color);
//++++ OVERLOAD ++++
public static void Log(string message)
DebugConsole.instance.AddMessage(message);
public static void Clear()
DebugConsole.instance.ClearMessages();
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//---------- void AddMesage(string message, string color) ------
//Adds a mesage to the list
//--------------------------------------------------------------
public void AddMessage(string message, string color)
messages.Add(message);
colors.Add(color);
Display();
//++++++++++ OVERLOAD for AddMessage ++++++++++++++++++++++++++++
// Overloads AddMessage to only require one argument(message)
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
public void AddMessage(string message)
messages.Add(message);
colors.Add("normal");
Display();
//----------- void ClearMessages() ------------------------------
// Clears the messages from the screen and the lists
//---------------------------------------------------------------
public void ClearMessages()
messages.Clear();
colors.Clear();
ClearScreen();
//-------- void ClearScreen() ----------------------------------
// Clears all output from all GUI objects
//--------------------------------------------------------------
void ClearScreen()
if (guis.Count & maxMessages)
//do nothing as we haven't created our guis yet
int x = 0;
while (x & guis.Count)
GameObject gui = (GameObject)guis[x];
gui.GetComponent&GUIText&().text = "";
//increment and loop
//---------- void Prune() ---------------------------------------
// Prunes the array to fit within the maxMessages limit
//---------------------------------------------------------------
void Prune()
if (messages.Count & maxMessages)
if (messages.Count &= 0)
diff = messages.Count - maxM
messages.RemoveRange(0, (int)diff);
colors.RemoveRange(0, (int)diff);
//---------- void Display() -------------------------------------
// Displays the list and handles coloring
//---------------------------------------------------------------
void Display()
//check if we are set to display
if (visible == false)
ClearScreen();
else if (visible == true)
if (messages.Count & maxMessages)
// Carry on with display
int x = 0;
if (guis.Count & maxMessages)
//do nothing as we havent created our guis yet
while (x & messages.Count)
GameObject gui = (GameObject)guis[x];
//set our color
switch ((string)colors[x])
case "normal": gui.GetComponent&GUIText&().material.color =
case "warning": gui.GetComponent&GUIText&().material.color =
case "error": gui.GetComponent&GUIText&().material.color =
//now set the text for this element
gui.GetComponent&GUIText&().text = (string)messages[x];
//increment and loop
}// End DebugConsole Class
2.使用方法
//DebugConsole.instance.AddMessage("this is instance AddMessage test by cartzhang", "warning");
//DebugConsole.Log("this is debug console log test cartzhang");
3.结果如图
四、这还不是我想要的,我要显示在控制台上,就是CMD出来的那样。
好吧,你赢了!!
你往下看吧!
-----------THE END ---------------
若有问题,请随时联系!
非常感谢!
由于担心篇幅过长,写成下一篇吧。
再次感谢各位!
页面正在加载中Unity解析VR产业及思考 - Unity3d技术 - 泰课在线 - 国内专业的Unity在线学习平台|Unity3d培训|Unity教程|Unity教程 Unreal 虚幻 AR|移动开发|美术CG|UI平面设计|前端开发 - Powered By EduSoho
Unity解析VR产业及思考
本文为Unity Technologies 技术支持经理 张鑫与原厂讲师 罗志达共同撰写的文稿,旨在于让更多投身VR领域的开发者在创建一个Unity项目之前,从过去,现在与未来的多重角度来了解Unity对VR产业的支持
VR的发展历史与现在火爆的原因
在开始了解如何创建一个VR项目之前,首先需要了解VR的一些历史:1935年,小说家Stanley G.Weinbaum在他的小说中描述了一款虚拟现实的眼镜,而该小说被认为是世界上率先提出虚拟现实概念的作品,故事描述的就是以眼镜为基础,包括视觉,嗅觉,触觉等全方位沉浸式体验的虚拟现实概念;1962年,一部名为Sensorama的虚拟现实原形机被Morton Heilig所研发出来,后来被引用到空军,以虚拟现实的方式进行模拟飞行训练。虽然随后从1970年到1994年的二十多年间,VR领域有许多科学家相继投入研究,但从整体上看,还仅限于相关的技术研究,并没有生产出能交付到使用者手上的产品,直到1994开始,日本游戏公司Sega和任天堂分别针对游戏产业而推出Sega VR-1和Virtual Boy,在当时的确在业内引起了不小的轰动,但因为设备成本高,普及率并没有很大,但也为VR硬件进军To C市场打开了一扇门。
现今VR产业火爆,起因是因为2012年Oculus Rift通过国外知名众筹网站KickStarter募资到160万美元,后来被Facebook以20亿的天价收购。而当时Unity作为第一个支持Oculus眼镜的引擎,吸引了大批开发者投身VR项目的开发中,正式打响了这场VR之战,但经历首轮引爆后,2014年Google发布了Google CardBoard,让消费者能以非常低廉的成本通过手机来体验VR世界,导致许多手游开发者纷纷加入这战局,点燃了今日的&Mobile VR&超级大战
纵观当今市场,基于与Unity一直保持良好关系的硬件公司所讨论出的数据,讨论后所得到的数据,以及独立开发市场分析的结果,2017年会有超过1300万的VR硬件产出,2020年更会超出5000万台,总市值将达30亿美元
VR原理与现状深度探讨
在当今已经销售的沉浸式VR设备中,主要有以下两种设备类型:
1.基于PC的头戴式VR设备,如Oculus Rift。此类设备通过PC来计算,并将计算结果传递给头戴式设备中的显示屏进行显示,进而让用户产生沉浸式VR的体验。就目前而言,该类设备较之其他类型设备,可以提供给用户最好的VR体验,但其缺点是必须要通过USB/HDMI线与PC相连,这也极大地限制了该类设备的灵活性。
2.基于Mobile的头戴式VR设备,如Gear VR,Google Cardboard等。此类设备通过将移动设备进行场景的渲染和计算,并直接作为屏幕来进行显示。该类设备的优点是避免了繁琐的电线连接,便于携带,且移动设备普及率高。但缺点同样突出,即计算和渲染能力较PC相比,逊色许多,且随着体验时间的增加,移动设备的发热程度会迅速上升,从而迫使其降低频率来进行计算,进而造成更大的画面卡顿和延迟,大大降低VR体验的舒适感。
除此之外,还有Sony的Morpheus、HTC的VIVE等硬件设备,据悉也将于明年正式面世。
就目前的VR体验而言,其最亟需解决的问题就是用户体验时的眩晕等身体不适问题。造成身体不适的原因很多,分辨率、画面重影、画面延迟、深度感知不连续等等。人体全身上下有许多感知器官,每时每刻都在不断地感知周围信息并将其传给大脑,大脑则不断对这些信息进行处理,判断其是否正常和&合理&。所以,如果出现了大脑无法识别的冲突信息,大脑就会感到&困扰&,进而产生不适感。以上所说的&重影&、&延迟&和&深度感知不连续&等,均会让大脑感到&困扰&,因为这些现象在人们习以为常的生活中,几乎是不可能出现的。因此,这种情况极大加速了人们大脑的疲劳,甚至出现眩晕恶心等情况,进而大大缩短了VR体验的时间。目前,沉浸式VR的体验时间一般为每次5-10分钟,连续体验不宜超过30分钟。
如何提供给用户更棒的VR体验,已经成了当今VR领域首要的解决问题。就目前而言,主流的硬件厂商都在以下几个方向进行不懈的努力。
1. 提高帧率、降低延迟度
一般来说,一款PC/移动游戏的帧率只需保持在30帧/秒以上,即可满足玩家流畅游戏的需求。但对于沉浸式VR体验来说,30帧/秒是远远不够的。在此,需要先来解释一下延迟度这个概念。
所谓&延迟度&,是指从头戴式设备的传感器将方位信息传入PC机开始,经过PC/移动设备的计算渲染,最后传回到显示屏进行显示的时间间隔,如图1所示。所以,用户眼睛真正看到的实际上是几十毫米之前的场景。
图1:设备延迟度的形成原因。该图取自Nvidia的技术文档《Gameworks VR》。
如果延迟度过长,则用户实际看到的渲染场景是&一顿一顿&进行显示的,进而增加了VR体验的不适感,甚至让人感到眩晕。一般来说,延迟度需要小于20ms且越小越好,这样才能保证较好的VR体验。如果想要延迟度小于20ms,则必须要保证帧率至少达到75帧/秒,甚至90帧/秒以上。而这种性能要求,即便是对于目前的主流家用PC机来说,也算的上是&苛刻&了。
虽然Oculus提出了Async Timewarp技术来尽可能在低帧率的情况下保证延迟度,但该方法目前仅能适用于&头部旋转&(Rotation Timewarp)和小范围慢速度的位置移动(Positional Timewarp)。对于快速移动和动态物体,该方法依然无效,如图2所示。因此,这里需要郑重说明的是,在提高VR体验时,没有任何一种方法比&提高帧率&更为有效。
图2:Async Timewarp方法比较适合与静态场景的显示,但对于动态物体,则会出现&重影&效果,进而造成一定的视觉不适。
2.提升分辨率
目前的硬件需要在距离眼睛很近的位置观看,而屏幕贴近眼睛很容易产生纱窗效应,使眼睛能够看出屏幕中的格点,进而产生不适。坦白说,分辨率问题需要依靠硬件方面的提升才能得以解决。
VR与人体的关系与注意事项
实际上人体对于环境的敏锐度是超乎想像的,一个舒适的VR体验远比一个美观的VR体验更为重要,因为不舒服的体验会导致人体产生强烈的排斥反应,进而造成晕眩或是不适,在目前VR项目的开发原则就是不要让帧率低于75或停止更新。
VR摄像头的结构有如一双眼睛有两个平行绑定的摄像头,且各自拥有独立的校准功能,眼睛往前看的情况下视角(FOV)范围水平角度122&,垂直角度120&,如果是在颈部自由运动的范围下,视角(FOV)能达到水平角度210&,垂直角度160&。有趣的是,如果以每度60x60像素来算,我们认为当屏幕硬件技术进化到12K x 10K时,VR体验将会非常趋近现实。
VR体验最重要的环节还有声音,但许多开发者忽略了声音的重要性,试想把耳朵塞住看电影,整个体验将完全没有沉浸感,因为人的耳朵掌管许多事情,比如平衡感和声音传递,它们就像是两个心型麦克风,人脑通过声音传递到两只耳朵的强度和时间差计算出声音的方向,分析出这段声音是否需要被注意,进而决定你会选择转头往音源方向看去,还是会选择忽略这段声音。也因为人脑有这样的过滤机制,使得即使在很吵杂的环境里,如果有人叫你的名字,你也会特别容易感知到,这就是有名的&鸡尾酒效应&
值得一提的是,人的耳朵接受到高频音(3000Hz以上)时会下意识地往上看,而接受到低频音(750Hz以下)时会往下看,因此在制作VR项目时,这都是有利于引导使用者视线走向的好方法
我们常常提到自己感觉到了速度,,其实那指的是加速度,人体对于加速度是有感的。因此无论是飞机起飞或汽车加速时,你就能感觉到速度快速增加,但人体对于速度本身是感觉不到的,当飞机飞行到稳定速度时,你能在机舱内安稳地用餐而不会觉得飞机正在快速移动,而你现在也无法感觉到地球正在定速转动
重力感是唯一我们无法欺骗身体的感觉,比如在某个VR项目中过山车翻转了180度,但实际上你的身体清楚地意识到其实你重力还是朝下,这时沉浸感就会降低,除非该项目真的配备了能转180度的座椅在体验时搭配使用。
人体比想像中更容易感到疲倦,因此如果长时间佩带VR设备,不管是眼睛还是手部都很容易产生疲劳感。在项目中,如果你过于频繁地引导玩家改变聚焦距离也很容易使人感到疲倦,因此,我们建议最佳的距离是2M-5M。而以目前的硬件设备的性能来看,最佳的内容体验时间大约是5分钟-10分钟,时间过长人体就会产生疲劳感。其他比如突然晃动镜头,突然停止画面或是帧率过低都会让人体产生不舒服的感觉
其实人类并非像我们所想的那样,希望从VR体验中得到真实感,或者说对真实感的追求是有限度的,这是因为人的情感系统天生带有移情反应,会把所有虚拟现实世界里的物体和真实世界划上等号。如果在虚拟现实世界里看到一只朝着你摇尾巴的小狗,你会主观地认定它对你没有伤害而降低警觉性,而当你的项目是恐怖游戏时,这种移情反应将会是一个非常好的切入点。给各位举一个有趣的例子,当你去商场买衣服的时候,你会发现假人永远都是没有头或是没有五官的几何图形,如果假人有张人脸反而会令客人产生恐惧感,这是1970年日本机器人专家森政弘,根据Ernst Jentsch于1906年发表的&恐怖谷心理学&所提出的理论:当人类看到与自己形体相当的假人时会产生正面情感,但是随着假人越接近真实的人类外表与行为时,人们则会突然产生剧烈的排斥与恐惧感,直到假人与正常人类外表与行为完全一致时才会消除这份恐惧感,这样的曲线呈现看起来像是一个山谷,因此称为&恐怖谷理论&
正因为移情反应,开发恐怖游戏更适合使用真实世界的纹理而非卡通纹理,沉浸在虚拟现实内的玩家看到锋利的刀会不由自主的想要避开,看到熊熊烈火会想要绕开,因为有这样的反应,所以虚拟现实也非常适合用在军事训练上,让士兵习惯在危险的环境中生活。
VR的目前市场分析与硬件介绍
针对当前VR开发的问题,我们可以从几个切入点进行讨论
虽然VR硬件百家争鸣,但目前市场上大概有三种类型的VR硬件设备
第1种.必须接上电脑的沉浸头戴式设备(HMD),这种设备的代表就是Oculus Rift,其优点在于沉浸体验很好,但由于是有线设备,其有限的移动范围是个障碍,因此特别合适于双脚不需移动的应用。设备本身价格比较昂贵,因此大多都是应用于to B的领域,现在该设备上的应用大多都是短时间体验,因此非常适合展览或是商业活动展示,但这类活动体验的人数较多,因此如何保持设备的卫生将是个大问题。
第2种.需要自带手机的VR(Mobile VR),现在人手一部手机,因此该类设备只要简单地将纸版折成的可容纳手机的盒子就能体验,代表性的设备有Google Cardboard及Gear VR或是国内的暴风魔镜,虽然体验没有PC头戴设备好,但由于成本低廉,易于携带,开发应用的流程也是手游开发者所熟悉的,因此今年有大量的开发者投入Mobile VR的开发行列,进而带动了整个VR市场的发展。
第3种.整合AR技术的新型态体验,进入CR(Cinematic Reality)新领域,要知道市场上总是有往前冲的领头羊,谷歌所推出的Google Glass就是一个案例,虽然现已成为绝响,但也造就后面的Microsoft Hololens, Magic Leap等新型态眼镜的快速进化。未来眼镜的轻量化,极强的电池续航力将是次世代VR设备的重点,但为了达到眼镜轻量化的效果,代价就是身上必须背着一个用来运算的硬件,如果运行效果能达到预期,我们将踏入次世代VR领域。
除了上述大类之外,也有许多不同的VR装置,比如投影VR或是全息VR。
如何从Unity来开发VR项目
Unity 从5.1开始就把VR SDK集成到引擎内,开发者只要下载最新的Runtime Driver之后,在Unity Player设置内将Virtual Reality Supported打勾,并把硬件连接上电脑就能直接把项目转为VR项目,默认的摄像头会自动切换成为VR摄像头,通过这样的设置,VR的开发过程将与开发一般手游无异,只有在按下Play按钮时,Game View的视角才会切为VR双镜头画面
VR项目的优化基于硬件的差异会有不同的考量,但是与手游相比相对容易,在现今的中端手机装置上,我建议保持下列几点守则,以保证项目运行顺畅:
1.绝对不能降帧
2.减少物体数量,减少物体曲面
3.多用静态物体,采用烘焙光照
4.Draw Call保持100左右
5.小于100k的三角面
6.可以采用高解析的纹理来弥补
7.使用物理引擎来避免CPU消耗过大
8.采用LOD,遮挡剔除,批次运算
Unity 5.1的Profiling功能已经支持Oculus和Gear VR的直接报告,这意味着只要装置连接或是在同网段下,开发者就能透过Profiler来监控VR项目的效能并进行有效优化。
目前Unity的VR开发技术挑战
传统的VR渲染管线,是使用两个相机按照视距摆放并对场景进行渲染。一般来说,渲染时需要在每个相机中依次遍历场景中需要渲染的物体,即整个场景被渲染了两次,如图3所示。这种做法最为直观简单,但其本身存在较高的性能浪费&&同样的场景,近乎一致的相机设置,却进行了两次视域体裁剪(Culling)操作,两遍的图形管线API以及双倍的Drawcall占用。因此,我们在Unity 5.1中针对VR的渲染管线进行了深度优化,比如场景裁剪(Culling)仅做一次,场景中的动态阴影也仅渲染一次等等。同时, Android多线程渲染功能和GPU蒙皮(仅OpenGL ES 3.0)技术的大力支持,让VR方面的渲染性能得到了较大幅度的提升。
图3:传统的VR渲染管线。
接下来的Unity开发计划还会加入更多VR设备相关的API,比如眼球追踪API等。渲染管线也会继续优化,预计5.1之后的渲染管线会有几种走向:
1. 渲染场景时,只遍历一次场景,每个物体只提交一次,但根据照相机的不同Viewport和Transform渲染两遍,如图4所示。该方法较易于实现,且与传统的VR渲染管线相比,该方法对于大量的图形管线API仅调用一次,但缺点是渲染时仍需要消耗两倍的Drawcall。
图4:改进后的VR渲染管线。
2. 原理同方法1,不同的是通过Command Buffer(DX11)来提交和渲染场景中的物体。所以其优点也方法1一致,缺点同样是两倍的Drawcall消耗,以及需要硬件设备支持Command Buffer功能。
3. 在遍历场景进行渲染时,通过硬件Instancing技术针对每个物体渲染两个instance,一个用于左眼相机,一个用于右眼相机。这样做的好处不仅保证了对图形管线API的一次调用,同时还可以大幅降低Drawcall的占用,即虽然显示于两个相机中,但只需要一倍的Drawcall。该方法的缺点是不支持Open GL ES 2.0的设备,同时与标准的Instancing技术也会产生冲突
Unity针对VR的未来计划
如前文所提到的,虽然VR硬件厂商如潮水般的涌入市场,但目前仍缺乏一个商业化思维,简单来说就是尚未找到一个能够赚钱的方法,相对于VR,反而AR领域目前还比较能够变现。但VR前景仍被看好,我们也相信随着更多人投身该行业,相应的商业模式也会迅速确立。
在一次与同行的讨论中,大家各抒己见地说出自己内心想做的项目类型,并描述了可能执行的做法,虽然无法涵盖全部领域,但在此提供给各位一个参考
旅游导览系统
实时視頻串流VR
这几年的科技产业变化突飞猛进,我们对于VR产业是相当乐观的,预测短短几年内我们就能在生活中体验到各种VR或AR项目,以Unity的角度来看,保持技术领先,永远面向开发者,和所有的硬件公司和开发者保持良好互动,为开发者提供一个良好的开发环境来创建出未来优质的VR产品,是我们不会改变的目标。
你还没有登录,请先或!
Unity3D技术交流1群
泰课Unity3D公开课
工作时间:9:00 - 17:00
北京客服:010 -
广州客服:020 -}

我要回帖

更多关于 deepoon m2 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信