ta = {1,2,3}
t = {}
table.insert(t,ta)
table.remove(t,1)
如果1处位置是表,那么这里仅仅是删除t对于位于1位置的ta的引用。 ta 本身还存在。
如果不是使用remove,而直接使用t[1] = nil, 那么仅仅是将t将出现问题,print的结果是什么都没有(即便t中还有别的元素),但打印#t,长度却没有改变。而ta仍然健在。所以要避免使用t[1] = nil这样的用法。
另外,如果 :
taa = ta
taa = nil
那么taa是nil,ta仍然健在
]]>local modNum = math.fmod(timer ,1.0 );
打印结果:
timer = 9.2190463617444 modNum = -0.446857218295336
如果专门写一个test.lua去打印,出来的是正确的结果:0.2190463617444.
但是回到Update中,仍然是错误的。注意:当timer在小于0.5时往往没有出现这种错误。
具体原因仍未查明。还请路过高手指教。
]]>
像这样:
以上效果的关键在于屏幕特效Shader中,提取水面的法线贴图时,将uv的移动方向交叉移动,然后将采样得到的两个法线值叠加。
如下:
float2 speed = _Time.y * float2(_WaveXSpeed, _WaveYSpeed);
// Get the normal in tangent space
fixed3 bump1 = UnpackNormal(tex2D(_WaveMap, i.uv.zw + speed)).rgb;
fixed3 bump2 = UnpackNormal(tex2D(_WaveMap, i.uv.zw - speed)).rgb;
fixed3 bump = normalize(bump1+bump2);
// Compute the offset in tangent space
float2 offset = bump.xy * _Distortion * _RefractionTex_TexelSize.xy;
i.scrPos.xy = offset * i.scrPos.z + i.scrPos.xy;
fixed3 refrCol = tex2D( _RefractionTex, i.scrPos.xy/i.scrPos.w).rgb;
如果是雾效,使用的是一张噪声图作为影响雾气密度。在提取时,不要使用normalize()。否则噪声效果就没了。
float2 speed = _Time.y * float2(_FogXSpeed, _FogYSpeed);
fixed3 noiseCol1 = tex2D(_NoiseTex, i.uv + speed ).rgb;
fixed3 noiseCol2 = tex2D(_NoiseTex, i.uv - speed ).rgb;
fixed3 noiseCol = (noiseCol1+noiseCol2); // normalize()了之后就没有效果了
float noise = (noiseCol.r - 0.5) * _NoiseAmount;
float fogDensity = (_FogEnd - worldPos.y) / (_FogEnd - _FogStart);
fogDensity = saturate(fogDensity * _FogDensity * (1 + noise));
如果不采取以上的方式,就只有法线和噪声单方向移动的效果,如下图所示:
以上项目和代码来自冯乐乐的《Unity Shader 入门精要》。
]]>转自:百度百科。
在有限维的情况,任何一个仿射变换都能够由一个矩阵相乘来计算。
]]>|
项目类型 |
实施方案 |
项目特点 |
|
VIVE端VR样板房 |
UE4 |
场景真实;简单交互 |
|
VIVE端VR景区体验游戏 |
Unity |
场景真实;游戏逻辑多 |
|
移动VR游戏 |
unity,3d场景 |
|
|
移动VR场景体验 |
3dsMax建模渲染全景图/实景拍照 |
|
|
AR项目(移动端、Hololens) |
Unity |
需要较好移动性能 |
|
龙星人平台游戏 |
Unity |
游戏功能要求全面 |
|
地理信息服务(GIS、LBS) |
iOS,Android(优先外包) |
使用百度、高德等接口 |
物件模型:网络、自建素材(模型和材质)库
角色动画:无明确要求可使用Mixamo+Fuse;定制化角色使用 Daz Studio。
树:SpeedTree、网络及素材库。
程序:蓝图(代码尽量全部使用蓝图)/ C#
]]>
产生原因:
在VIVE头显模式下,Unity对于薄边缘的抗锯齿效果不佳,并存在高光闪烁的缺陷。
如何解决:
方案1:
使用The Lab Renderer。(需要配合Unity 5.4.0版本使用,使用Unity5.4.4会不时出现屏幕闪动问题)
方案优点:
方案缺点:
方案2:
Unity 5.5,在Quality中设置Anti Aliasing 为4倍或者8倍;在CameraRig的Camera(eye)上挂载抗锯齿脚本(下载地址)Image Effects/Anti-Aliasing,开启SMAA(Subpixel Morphological Anti-aliasing)或者FAA,或者挂载Image Effects/Other/Anti Aliasing(该脚本中使用FXAA3 Console效果相对较好)。建议根据实际场景测试选择。
方案优点:
方案缺点:
问题原因:
unity的抗锯齿方案会导致高光部分闪烁。
如何解决:
使用 The Lab Renderer可以一定程度减小高光闪烁。
补充:UE4不存在此问题在于UE4默认使用TXAA,但TXAA的副作用是让画面变模糊。如果UE4将TXAA改为FXAA,一样闪烁。
如何解决:
不仅是默认的草和树,还有AssetStore上下载的SpeedTree也会出现这种情况。问题出在材质上。
解决方案是将材质替换为Standard Specular Material,树叶之类在Render Mode中使用Transparent或Fade,并且,树不能烘焙。(注意,如果使用Cutout,仍然会出现闪烁情况,不过这个闪烁与抗锯齿相关,且暂无法规避)(并且,如果使用透明的材质显示树叶,由于前后交错的树叶及不透明的树干在深度测试中的问题,树干经常会显示在树叶前面,出现错误)
如图是使用Nature材质的效果:
如图是Standard Specular-Transparent的效果:
如图是Standard Specular-Cutout的效果:
]]>
首先采用上篇博文中的方案二来实现AR的Extanded Tracking。
同时,使用一个空GameObject(命名为AR Objects)来与ImageTarget的transform进行同步。使用AR Objects的child(命名为AR Children)作为漫游中需要执行移动的对象。
在AR Children中挂载两个脚本:MoveAgainstCam.cs和PinchZoom.cs。
MoveAgainstCam.cs用来移动AR Children,模拟漫游效果。PinchZoom.cs用来处理手指输入,放大操作类似于向前移动,缩小操作类似于后退。(效果类似于“放大”和“缩小”)
代码如下:
MoveAgainsCam.cs
namespace Will
{
public class MoveAgainstCam : MonoBehaviour
{
public GameObject m_Camera;
public float m_MoveSpeed = 1.0f;
private Transform m_CamTrans;
//--------------------- Life Cycle -----------------------//
private void Awake()
{
m_CamTrans = m_Camera.transform;
}
//--------------------- Interface -----------------------//
public void MoveForward(float fraction)
{
if(fraction == 0)
{
fraction = 1;
}
transform.position -= m_CamTrans.forward * m_MoveSpeed * fraction;
}
}
}
PinchZoom.cs:
namespace Will
{
public class PinchZoom : MonoBehaviour
{
public float ZoomSpeed = 0.01f; // The rate of change of the field of view in perspective mode.
public float RotateSpeed = 30.0f;
private MoveAgainstCam m_MoveAgainstCamScript;
private void Awake()
{
m_MoveAgainstCamScript = GetComponent();
}
void Update()
{
// If there are two touches on the device...
if (Input.touchCount == 2)
{
// Store both touches.
Touch touchZero = Input.GetTouch(0);
Touch touchOne = Input.GetTouch(1);
/*------------------------ Zoom --------------------------*/
// Find the position in the previous frame of each touch.
Vector2 touchZeroPrevPos = touchZero.position - touchZero.deltaPosition;
Vector2 touchOnePrevPos = touchOne.position - touchOne.deltaPosition;
// Find the magnitude of the vector (the distance) between the touches in each frame.
float prevTouchDeltaMag = (touchZeroPrevPos - touchOnePrevPos).magnitude;
float touchDeltaMag = (touchZero.position - touchOne.position).magnitude;
// Find the difference in the distances between each frame.
float deltaMagnitudeDiff = prevTouchDeltaMag - touchDeltaMag;
// Move
m_MoveAgainstCamScript.MoveForward(-deltaMagnitudeDiff);
}
}
}
}
]]>
优缺点:
优点:使用简单。
缺点:移动时有时模型会出现倾斜和移动的不稳定情况。
具体操作:
如果想了解Vuforia中World Center Mode的设置解释,以及类似口袋妖怪AR游戏的Vuforia实现方式,可参见此处。
方案2(使用Vuforia但不使用Extended Tracking):
优缺点:
优点:绕四周移动设备时,场景中模型的位置相对第一种方法更加稳定。
缺点:需要设置Button用于开启和关闭位置同步状态,否则将ImageTarget移出手机视野时容易模型位置突变为不正确方位。
具体操作:
UpdateTransformByTarget.cs(被绑定在需要展示的模型的父对象上,这个父对象是一个空GameObject) 中主要代码:
namespace Will
{
public class UpdateTransformByTarget : MonoBehaviour
{
public GameObject m_ImageTarget;
public GameObject m_Pipes; //真正用于展示用的模型。
public Text m_ScanButtonText;
private DefaultTrackableEventHandler m_TrackHandler;
private bool m_EnableScanPosition = true;
//----------------------- Life Cycle -------------------------//
// Use this for initialization
void Start()
{
m_TrackHandler = m_ImageTarget.GetComponent();
}
// Update is called once per frame
void Update()
{
if (m_EnableScanPosition)
{
transform.rotation = m_ImageTarget.transform.rotation;
transform.position = m_ImageTarget.transform.position;
}
}
//----------------------- Interface -------------------------//
public void SwitchEnableScanState()
{
m_EnableScanPosition = !m_EnableScanPosition;
// 更新扫描按钮的文字显示
if (m_EnableScanPosition)
{
// 开启了扫描状态
m_ScanButtonText.text = "确定";
// 将AR物件的位置重置
m_Pipes.transform.position = transform.position;
m_Pipes.transform.rotation = transform.rotation;
}
else
{
// 结束了扫描状态
m_ScanButtonText.text = "扫描";
}
}
}
}
]]>
材质:
使用Substance Designer做模型的材质,导出到Unity。
角色创造:
动画:
在3dsMax中进行骨骼绑定(使用CAT就很合适)及人物基本动作动画制作。(衣服、辫子等制作骨骼,但是不必在动作中调其动画)
导出到Unity中后,将Avatar设置为Humanoid(方便之后可能进行的Layer的叠加)。
如有需要,使用Dynamic Bone插件对衣服、辫子等随动骨骼进行物理模拟。
表情动画:
若用3dsMax,使用已经绑好骨骼的模型进行表情变形,借助变形器结合Silder进行表情的动画k帧。导出成FBX。
若用Maya,将脸部的blendshapes先建立好,然后将整个人进行骨骼绑定,然后k动作,动作都k在一个FBX文件中进行导出(Unity中使用Legacy模式)。
(Maya导出注意:导出时记得将用于调blendshapes的脸也选中导出)
将FBX导入Unity,然后将Rig设置为之前已经导入的具备模型基本动作的Avatar(设置为Humanoid,方便后面动画层叠加)。
(导入注意:先将Maya中的贴图先导入unity,然后导入FBX文件,这样导入时FBX中附带的材质就能直接将贴图贴给材质球)
创建AvatarMask,仅将头部设置为绿色,并且Transform设置为之前那个基本动作的Avatar。
在AnimatorController中创建新Layer(如命名Emotion Layer),Emotion Layer的Blending设置中使用Additive ,avatarMask使用刚创建的那个。
于是表情动画与基本动作的动画就叠加了。
头发:
如果需要随风飘动细节较多的头发,可以使用Unity的cloth来模拟。实现方式见此视频。(看此视频需翻墙,设置点的范围时可以不按照视频的方式,使用MaxDistance来设置)
附图:
头发和表情动画的完成效果参考:
]]>
比如,树木的面数应控制在一万面以内,以六七千面为宜。
我们做的一个场景,之前使用了两万、甚至二十万个面的树,导致即便使用i7+GTX1080,帧率仍然在30帧与45帧之间徘徊。并且树枝因为细小的面数太多,贴在上面的材质会出现模糊闪烁的情况。
这是在UE4编辑器中的情况:
i7+ 1060显卡,PC端运行可以勉强达到60帧。
在VR模式中,(即便使用TXAA)存在强烈的闪烁现象,将ScreenPercentage设置到200,仍然存在强烈闪烁,并且帧率下降到38帧。若将ScreenPercentage设置到300,闪烁消失,但帧率降到了20帧,滞后感明显。
使用Speedtree重新建模了树木,放入场景中:
PC(i7+ 1060显卡)运行可以达到110帧以上,VR模式中的闪烁情况也消失了。
在VR模式下,仍然存在闪烁现象。通过将ScreenPercentage设置为200可以大幅减小闪烁,帧率能达到45帧。若将ScreenPercentage设置为300,闪烁完全消失,帧率37帧。
]]>