Animator+RFX组件,给识别图添加动画和特效
-
Animator 的制作:
导入模型动画和特效资源包(连接我会放在文章的最后面),新建文件夹Animator(制作模型动画)和Prafbs(存放使用的模型).
在Animator文件夹新建一个Animator组件,并双击打开动画制作管理界面
然后新建一个空的模型状态(想做几个过渡就新建几个),然后再给这几个模型状态进行连接,连接过后如果想要循环播放,只要把最后一个模型状态动画和第一个模型状态动画连接在一就可以了,具体操作:
最终的动画效果图:并且最后的最后不要忘记给最初的模型添加好我们已经制作好了的动画——AnimatorController(我是重新命名了的),拖拽过来就行了.
-
Vuforia的环境搭建
在这里我用的U3D版本号时2017.3.1f1,在安装的时候已经是勾选了U3D内嵌的Vuforia开发组件的(勾选了就会出现以下图片的界面,如果没有的话的你也可以在U3D官网下载Installer,安装的时候只需要勾选Vuforia就可以了,或者市区Vuforia的官网下载SDK For Unity3D.),然后去Vuforia官网建立一个数据库并且获取LiscensKey(这个密钥的获取方式,网上教材很多,这里就不进行赘述了,这个密钥是对后续工作做了准备的)。密钥准备好以后还要进行一些设置,不然扫描图片以后根本无法出现模型,效果也是没有的,第一把世界中心模式设置为扫描的第一张图片,第二个是设置加载数据库,并把属性改为激活。
接下来有了正式的环境以后,我们就去搭建图片识别(Imgae Target)的开发了:首先在Hierarchy面板新建一个ARcamera和Image,给Image Target选择你之前在Vuforia建立好的数据库,并且选择Target Name。接着就时输入密钥了(进行初始化)。密钥的输入有两种方式:第一种(鼠标点击ARCamera,再点击Open Vuforia configuration);第二种(直接在搜索框里面搜索:Open Vuforia configuration,搜索到以后双击打开就可以看到密钥的输入界面了)(我只列出了第一种方式的图片)
-
Image Target中的DTEH C Sharp 脚本的分析
这个脚本我们打开后其实是利用了模型当中的Render组件控制,当摄像机识别到图片目标以后,我们就打开这个Render(被设置为True),当摄像机没有识别到图片目标以后,我们就关闭这个Render(被设置为False)。而我们必须要实现这个动画效果(即只要扫描到了图片,就展示模型,并且播放模型动画),这是就要对起代码进行改进,达到Animator与ImageTargetController加载在一起(下面的代码是针对DTEH对于实现追踪成功后生成模型与动画),并且修改好以后,拖拽Prefab(AIXI)过来。除此之外还要把Image的子物体模型AIXI的勾勾去掉(因为我们已经在脚本中实现了找到识别图生成模型的功能),不然就会出现Clone并没有销毁(Clone函数中的名称必须和Hierarchy中的创建的名称一样,其他随便)
public GameObject AIXIPrefab;
protected virtual void OnTrackingFound()
{
//找到了需要识别的物体
//找到以后生成AIXI
GameObject AIXI=GameObject.Instantiate(AIXIPrefab);
//把AIXI的位置放在识别图的位置
AIXI.transform.position = this.transform.position;
//把AIXI的主体设置Target的主体
AIXI.transform.parent = this.transform;
}
protected virtual void OnTrackingLost()
{
//丢失了需要识别的物体,只需要进行摧毁即可
Destroy(GameObject.Find("AIXI(Clone)"));
}
我们可以进行测试上面代码的编辑结果,找到生成Clone,丢失销毁克隆体。
- 特效的制作(让人物模型有一个传送门,从龙卷风中缓缓上升)
这里我采用两种特效(42_RFX_Blood_Puddle1和48_RFX_Tonado_Flame1) 重命名以后把这两个特效拖拽到了之前新建的Prefab文件夹里(方重命名便后续改写代码,以免名字混淆)(还是和上一步修改完代码一样的操作,把两个特效拖拽的自定义的两个GameObject),需要注意的是,我们这两个特效不能拖拽到Hierarchy面板上,只需保存在Prefbs即可。
public GameObject AIXIPrefab;
public GameObject HeianPrefab;
public GameObject TonadoPrefab;
protected virtual void OnTrackingFound()
{
//找到了需要识别的物体
//找到以后生成AIXI
GameObject ax=GameObject.Instantiate(AIXIPrefab);
//把AIXI的位置放在识别图的位置
ax.transform.position = this.transform.position;
//把AIXI的主体设置Target的主体
ax.transform.parent = this.transform;
//找到以后生成特效1,后面个参数分别是与识别位置一致,特效进行旋转
GameObject ef1=GameObject.Instantiate(HeianPrefab,transform.position,Quaternion.identity);
ef1.transform.parent = this.transform;
//特效生成10s后销毁
Destroy(ef1,10.0f);
//找到以后生成特效2,后面个参数分别是与识别位置一致,特效进行旋转
GameObject ef2=GameObject.Instantiate(TonadoPrefab,transform.position,Quaternion.identity);
ef2.transform.parent = this.transform;
Destroy(ef2,10.0f);
}
protected virtual void OnTrackingLost()
{
//丢失了需要识别的物体,只需要进行摧毁即可
Destroy(GameObject.Find("AIXI(Clone)"));
//丢失以后销毁特效
Destroy(GameObject.Find("Heian(Clone)"));
Destroy(GameObject.Find("Tonado(Clone)"));
}
- 特效制作好以后,轮到任务上升的控制代码
//这个是我们需要在之前的基础上更改的DTEH代码部分
protected virtual void OnTrackingFound()
{
//找到了需要识别的物体
//找到以后生成AIXI,并且把模型位置向下移动
GameObject ax=GameObject.Instantiate(AIXIPrefab,transform.position-new Vector3(0,1.6f,0),transform.rotation);
//把AIXI的主体设置Target的主体
ax.transform.parent = this.transform;
//找到以后生成特效1,后面个参数分别是与识别位置一致,特效进行旋转
GameObject ef1=GameObject.Instantiate(HeianPrefab,transform.position,Quaternion.identity);
ef1.transform.parent = this.transform;
//特效生成10s后销毁
Destroy(ef1,6.0f);
//找到以后生成特效2,后面个参数分别是与识别位置一致,特效进行旋转
GameObject ef2=GameObject.Instantiate(TonadoPrefab,transform.position,Quaternion.identity);
ef2.transform.parent = this.transform;
Destroy(ef2,6.0f);
}
下面这个代码这个是新建的人物上升代码,挂载在AIXI上面,挂载好以后别忘记了Apply
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ShangSheng : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
//如果模型上升的位置完全在识别图上面时
if (transform.localPosition.y > 0) {
return;
}
//实现模型从识别图以下位置到以上位置的缓慢上升
transform.Translate (new Vector3 (0, 0.5f, 0) * Time.deltaTime);
}
}
- 阴影的制作
新建一个Render Texture(重命名为AR_Plane_Texture),在创建一个平面,给平面添加一个透明的Texture就可以了(在刚才添加过去的Texture面板中点击Shader,选择LegacyShader——Transparent——Diffuse),最后还要添加一个Camera(重命名为YinYing Camera(Camera的ClearFlags设置为Solid,然后在给Camera添加Shader(前面创建的AR_Plane_Texture),
这之后,勾选上AIXI,使它显示出来,并投影出影子来,再给AIXI固定层级关系(给AIXI的面板上面添加Layout,添加好后给AIXI指定层级)
这个时候的影子效果就出来了:(把YinYing Camera的CullingMask设置为AIXI)再把Plane中的Shader颜色改变成黑色就可以了。
- UI界面交互之——截屏(Texture)
新建一个脚本文件命名为ScreamShot,代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ScreenShot : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
public void OnScreeenShotClick()
{
//定义截图的时间,并设置成XX-XX——XX的格式
System.DateTime now = System.DateTime.Now;
string times = now.ToString ();
times = times.Trim ();
times = times.Replace ("/", "-");
//定义的J截图的文件名称
string fileName = "ARScreenShot" + times + ".png";
//当运行在安卓手机的时候 我们把截图放置在手机在带的截图文件夹里面
if (Application.platform == RuntimePlatform.Android) {
//采用Texture2D的格式
Texture2D texture = new Texture2D (Screen.width, Screen.height,TextureFormat.RGB24, false);
//截取全屏后读取贴图texture
texture.ReadPixels(new Rect(0,0,Screen.width,Screen.height),0,0);
texture.Apply ();
//把截屏图片转换成二进制码储存在bytes中
byte[] bytes = texture.EncodeToPNG ();
//指定截图的路径
string destination = "/sdcard/DCIM/Screenshots";
string pathSave = destination + "/" + fileName;
}
}
}
在新建一个Button(UI里面的这些组件都必须放在一个画布上——Canvas),button的防止有一个小技巧那就是在Anchor界面上,先按住键盘上面的Alt键,在选择你的位置就可以了(左上就是TopLeft)
最后再把前面编辑好的ScreenShot脚本挂载在Canvas上面,再去Button界面上添加功能函数(添加的步骤如下图所示,把Canvas拖拽过来后,再去Function里面寻找ScreenShot脚本里面的OnScreenShotClick方法);