Unity平台 + Vuforia SDK实现的AR程序开发
- 追加部分
- 思路简介
- 【Turret对象】CannonSystem脚本
- 【DiskProjectile对象】Projectile脚本
- 【MIKU对象】Target脚本
- 碰撞触发条件
- UI动态按钮
- 【BUG】关于Unity编辑器除选项卡外白屏的问题
- 接触的功能区
- 1.Vuforia Engine,AR插件
- 2.UI,用户界面
- 3.Audio,音源
- 4.Shaders,Material材质渲染方法
- 5.MMD插件,动作编辑器
- 6.Effects,特效
- 7.Collider,碰撞体
- 8.RigidBody,刚体
- 9.TrailRenderer,尾迹渲染器
- 10.Animation/Animator,动画系统
- 11.Switch Platform,平台发布系统
- 没有涉及到的功能区
- GameObject的灵魂——2D/3D Object
- 模型的灵魂——Animation/Animator
- Light、Camera——光线,摄像机对象
- Video——录像机
- Component选项卡
- 追加篇总结
作者写在前面的话:
没啥好说的,这个追加篇,就是……嗯应老师要求抽空再搞了搞,增加了两物体碰撞。以及尝试进入UnityUI领域。操作上还是比较简单的。理解上也没啥难点。嗯…就是需要时间还有一点运气?
追加部分
思路简介
【Turret对象】CannonSystem脚本
主要功用:限制Turret对象射击单位次数及力,及制造炮弹对象和控制Turret对应动画
此Turret模型来源于Unity官方教程,emmm国内翻译好的视频链接在下,包含下载link
bilibili Instaco栗课 [中英双字]Unity官方教程_使用Vuforia制作AR内容01-05
由于本系列教程重点不在3D模型上面故,大多数均采用现有大佬们的模型,每个模型我均会说明出处,以及在文件中ReadMe注明模型来源官网。
简单的就不说了,前面3个篇章,该讲的基础内容已经很全面了。直接上代码
//CannonSystem脚本如其名,主要功能是生成炮弹projectile对象并给force,从炮塔口
using UnityEngine;
using UnityEngine.Events;
public class CannonSystem : MonoBehaviour
{
[Header("Firing Properties")]
public float maxProjectileForce = 18000f; //炮弹的最大力限制
public float cooldown = 1f; //发射冷却时间
[Header("Projectile Properties")]
public GameObject projectilePrefab; //炮弹引用接口
Transform projectileSpawnTransform; //炮弹物体产生的初始位置
bool canShoot = true;
Animator anim; //坦克动画组件
void Awake()
{
//获取坦克发射的炮弹的生成点 通过坦克对象内炮嘴路径来提供, 虽然低效但实用
projectileSpawnTransform = GameObject.Find("Geometry/Cockpit/Turret Elevation Pivot Point/Projectile Spawn Point").transform;
//获取坦克动画控制器
anim = GetComponent<Animator> ();
}
public void FireProjectile()
{
if (!canShoot)
return;
//生成炮弹实例
GameObject go = (GameObject)Instantiate(projectilePrefab, projectileSpawnTransform.position, projectileSpawnTransform.rotation);
Vector3 force = projectileSpawnTransform.transform.forward * maxProjectileForce; //设置力的方向
go.GetComponent<Rigidbody>().AddForce(force); //给予物理动能
anim.SetTrigger ("Fire"); //设置坦克动画为Fire状态(自动会恢复,Animator设置)
canShoot = false;
Invoke("CoolDown", cooldown); //延迟调用CoolDown函数
}
void CoolDown()
{
canShoot = true;
}
}
没什么难点步骤如下
- 获取Turret对象的Projectile Spawn Point模型区块的位置(作为炮弹的起始位置)
- 获取Turret对象的动画控制器Animator
- Fire生成炮弹projectile对象,并给予力使其运动。
- 设置Turrent动画状态为Fire(可在Animator中查看Fire状态)
- 增加延迟调用 Invoke() 。
【DiskProjectile对象】Projectile脚本
**此脚本设置炮弹自身的设定(存续时间爆炸持续时间等)、爆炸函数(包含自毁)
//这个脚本控制着我们射击射弹的行为。 它处理爆炸力以及销毁自己
using UnityEngine;
using UnityEngine.Events;
public class Projectile : MonoBehaviour
{
[Header("Projectile Properties")] //UnityAPI,在Unity界面添加大标题。Public的属性均可在Unity进行修改,且永久生效。
public float lifeTime = 2.0f; //炮弹存在时间,为零就自动爆炸,存在时间决定运动距离
public float explosionDuration = 3f; //爆炸持续时间
public float explosionForce = 100f; //Unity的碰撞系统含有力这一定义,用于计算被碰撞物体的速度
public float explosionRadius = 4f; //爆炸半径
public LayerMask targetLayerMask; //用于确定哪些图层蒙版中的对象受爆炸影响
[Header("Object References")]
public GameObject body; //炮弹的网格部分(mesh renderer)
public GameObject explosionParticles; //爆炸粒子系统
Rigidbody rigidBody; //炮弹的刚体
Collider sphereCollider; //炮弹的碰撞体
bool exploded; //是否爆炸
void Awake()
{
//获取碰撞体和刚体的引用
sphereCollider = GetComponent<Collider> ();
rigidBody = GetComponent<Rigidbody>();
}
void Update()
{
//随时间减少炮弹存在时间
lifeTime -= Time.deltaTime;
//炮弹时间为0,自动爆炸
if (lifeTime <= 0f)
{
Explode();
}
Debug.Log("炮弹自动爆炸,自毁结束");
}
void OnCollisionEnter( Collision collision )
{
//Unity提供的碰撞监测函数,当碰撞时,爆炸
Explode();
//尝试从炮弹击中的物体中获取目标脚本
Target target = collision.gameObject.GetComponent<Target>();
//如果从被炮弹碰撞到的物体中获取到脚本,则调用这个脚本的Hit函数
if ( target != null )
target.Hit();
Debug.Log("获取到目标脚本Hit函数,碰撞结束");
}
void Explode()
{
//如果爆炸标识为已爆炸,则返回空(即是一个炮弹只能炸一回)要么是存在时间=0炸,要么是碰撞炸
if (exploded)
return;
//调用该函数即标识为已爆炸
exploded = true;
//禁用炮弹的所有组件,渲染器,碰撞器,刚体,脚本(Update)
body.SetActive( false );
rigidBody.isKinematic = true; //运动学,力、碰撞或关节将不再影响刚体
sphereCollider.enabled = false; //碰撞关闭
//开启爆炸粒子特效
explosionParticles.SetActive(true);
//获取,所有在爆炸半径并且在设定的影响图层中的碰撞体组
Collider[] colliders = Physics.OverlapSphere(transform.position, explosionRadius, targetLayerMask);
//循环操作获取到的碰撞体组
for (int i = 0; i < colliders.Length; i++)
{
//获取某一碰撞体
Rigidbody rb = colliders[i].GetComponent<Rigidbody>();
//以爆炸力使物体起飞(位移)
rb.AddExplosionForce(explosionForce, transform.position, explosionRadius, 2f);
}
Destroy(gameObject, explosionDuration); //在爆炸持续时间结束后,销毁炮弹
Debug.Log("炮弹销毁,爆炸结束");
}
}
两个重要函数void OnCollisionEnter( Collision collision )
这个函数是Unity内置碰撞检测函数,主要用途是,当Projectile对象碰撞到其他碰撞体后进行的操作。操作内容为:projectile物体调用自身的explode函数,然后获取Miku对象下Targe脚本,调用Target.Hit()函数令Miku自毁。void Explode()
炮弹爆炸函数,将炮弹对象的所有组件关闭,即不再显示炮弹。再开启爆炸粒子特效,获取爆炸半径内提前设定被影响图层的碰撞体组,然后循环操作获取到的碰撞体组对象,以爆炸力来驱使碰撞组对象移动。执行完循环后炮弹对象自毁。
【MIKU对象】Target脚本
没东西。只是为了销毁自身
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Target : MonoBehaviour
{
public float timeAfterHit = .5f; //被碰撞后与消失间隔
public void Hit()
{
Destroy(gameObject, timeAfterHit);
}
}
碰撞触发条件
1 碰撞双方必须都有Collider组件
2 碰撞的主动方必须有Rigidbody组件
3 刚体不能勾选IsKinematic
4 碰撞体不能够勾选IsTigger
UI动态按钮
应用到Sprite精灵2D图形对象。主要功能是在一张大图中去截取一部分成为一个小精灵对象,然后给小精灵命名,通过精灵名称就能在场景中直接使用。其次,sprite还可以用来制作动画。将导入的图片类型设置为Sprite可直接拖到场景面板里,并带有随屏幕大小自动缩放功能,还可以加Collider进行射线检测。总的来说,Sprite2D图形对象是一个十分便捷的功能。
动态功能实现是由——Btn_Option动画控制器。动态体现为按钮向右平移并回复到初始位置及颜色进行更改(颜色更改是由Transition——Sprite Swap实现的)
【BUG】关于Unity编辑器除选项卡外白屏的问题
可能因素:你的显存崩了,
解决方法:改用以集成图形(图形处理器)启动就不会出现此问题 / 选项卡——重置布局
现象:我双开Unity使用高性能图形处理器再加谷歌浏览器多开页面,就会出现浏览器白屏+Unity白屏。emmm
接触的功能区
总结一下这个项目接触到的功能模块,并附加复杂性排序
1.Vuforia Engine,AR插件
安装时勾选选项获取的Unity编辑器AR插件,给与开发者GameObject选项卡下增加Vuforia Engine物体集群。
Vuforia Engine物体集群
主要分两大类,第一个目标:单图目标,六面体多图目标,圆柱形目标,二维码目标,模型目标等。第二个辅助:3D扫描快速建模,地平线、中空识别并依托其构建AR对象。AR Camera为AR应用必备的组件,取代默认Camera。
VirtualButton增强现实按钮
是ImageTarget物体的ImageTargetBehaviour提供的。【Add V B】模拟出人类在现实空间中触碰按钮的行为(当然现在的实现原理只是简单的图像碰撞域的识别)
2.UI,用户界面
Canvas画布
Canvas是所有UI Component的父节点没错是最基础的节点,用于提供渲染着色显示等背景。在这里主要是承载Vuforia VB的图像Image和文本Text。
Image图像组件
按钮的蓝色,按钮的红色,其实是图片的切换。
Text文本组件
按钮的文字显示。
3.Audio,音源
Audio Source音源组件
在本程序中,主要是用于物体被跟踪发现时和物体跟踪消失时(这是ImageTarget下Default Trackable Event脚本设置的)开启进场声源,退场声源。以及DanceVB被触碰后开启背景音乐(其实这个在MIku物体的Animator是可以设置且正常播放的,但我可惜不行,不知道原因,后来为了在Android端进行开发后从Animator动画系统转为了Animation动画系统也就没有背景音乐设定的地方了)。
4.Shaders,Material材质渲染方法
Shaders渲染是在Miku模型从Windows平台转换到Android平台时遇到的,原因是Android端不支持MMD渲染方式,需要选择Mobile材质渲染方式。
5.MMD插件,动作编辑器
mmd只是一个动作编辑器,并不能制作模型或是编辑模型,也就是要在已有的模型基础上,自动化编辑产生一系列动作按时间顺序——>动画。而且……emmm不管是模型还是插件都是有版权的,hhhh慎用。先了解一下规则。建议用国外的模型。
6.Effects,特效
本程序引入了一个自发光Effects包,用于MIKU模型的自发光特效,主要是区别被射线法选定前后的区别。还有炮弹引入的爆炸粒子(Particle System)特效。
7.Collider,碰撞体
在本应用中主要是用于,坦克产生的炮弹碰撞MIKU模型完成一次碰撞,然后调用Miku模型挂载的Target脚本中的Hit函数,进行MIku对象销毁Destroy()。
8.RigidBody,刚体
这个是构成碰撞行为的必要条件之一。刚体是启用一个物体物理行为的主要组件。一旦附加刚体组件,物体将受重力影响。如果刚体附加了Collider,则可以检测碰撞。 刚体可以接受力和扭矩,但Transform不能。
9.TrailRenderer,尾迹渲染器
创建材质球,添加材质,并修改shaders渲染器方法。
10.Animation/Animator,动画系统
在Miku模型动画设置的时候涉及过一点点,嗯,就是简单的文件拖拽。哈哈哈哈
11.Switch Platform,平台发布系统
安卓平台需要下载其配套的发布功能包,你只需要安装到Unity根目录后,选择安卓平台Building即可,苹果/主机等等都是如此操作,哎,真的是太方便了,以至于我都忘记有这个东西了。优秀的厂商在不断进步,减低开发者的成本,真的是令人喜爱。
也就是说你使用Unity平台开发安卓程序,不需要懂任何的Android知识,嘻嘻嘻unityNB
没有涉及到的功能区
GameObject的灵魂——2D/3D Object
模型这个方面基本是拿来主义,也没有细细深入,不过我觉得这个是大坑…告辞
模型的灵魂——Animation/Animator
动画系统和模型一样粗略的有了解,但不全面也不精细,简单的使用还是会一点。制作完不动的模型,那么就是怎么让模型动起来,欸……又一个大坑。告辞
Light、Camera——光线,摄像机对象
emmm这个地方,涉及的不多,细节了解的更不多,只有射线法选中对象试验过。光是一点没涉及过。
Video——录像机
emmm完全没用过。
Component选项卡
告辞
追加篇总结
一直没搞懂,那个PlayOnStateChange脚本到底,怎么能够在其他文件夹下引入到Vuforia工程来,而不需要将这个脚本放到Vufoira/Script/目录下。emmm……恼火
还有关于追加的代码就不更新了,如果有需要评论留言吧,或者私聊。因为我需要修改下目标识别数据库,懒得改了,就不commit了。