使用Vuforia创建神奇宝贝GO风格增强现实游戏:图像目标
在本教程中,我们将跳回Vuforia增强现实(AR)库,探索其最有趣的资源之一-Image Target 。 我们将在之前的课程中扩展“射击立方体”游戏,并增加一个新的等级,玩家需要捍卫自己的基地以免攻击立方体。
图像目标
任何类型的图像都可以是Vuforia 图像目标 。 但是,图像越详细和复杂,算法识别的效果就越好。
识别计算将包括很多因素,但是基本上图像必须具有合理水平的对比度,分辨率和区分元素。 蓝天的照片效果不佳,但是一张草的照片可以正常工作。 图像目标可以随应用程序一起提供,可以通过云上传到应用程序,也可以由用户直接在应用程序中创建。
添加目标
首先,向我们的Unity项目添加一个ImageTarget
元素。
首先,从侧栏中的按钮下载课程资源。 然后,在您的Unity项目中,创建一个名为DefendTheBase的新场景:在“ 项目”窗口中,选择“ 场景”文件夹,然后单击“ 创建” >“ 场景”。 现在打开该场景,并从层次结构中删除所有默认场景对象。
接下来,我们将添加一个灯光和一个摄像头。 单击添加 > 灯光 > 定向光以添加定向光。 选择此新光源并将“ 软阴影”设置为“ 阴影类型”选项。
之后,从Vuforia > Prefabs拖放一个ARCamera对象。 选择ARCamera对象,然后在检查器面板中设置在Vuforia开发人员页面上创建的App许可证密钥 ( 有关说明,请参阅第一个教程 )。 选择DEVICE_TRACKING作为World Center Mod 。
最后,拖放一个ImageTarget 到Vuforia > Prefabs的层次结构。
现在我们必须添加一个Vuforia数据库。 首先,浏览至https://developer.vuforia.com/target-manager 。 单击添加数据库,然后选择一个名称。
有三种类型的数据库可供选择:
- 设备 :数据库保存在设备上,并且所有目标都在本地更新。
- 云 :Vuforia服务器上的数据库。
- VuMark :VuMark目标专用的数据库。 它也保存在设备上。
在这种情况下,选择设备选项,然后单击创建 。
选择新数据库,以便我们可以开始向其中添加目标。 现在是时候向数据库添加目标了。 现在,我们仅使用“ 单个图像”选项。
导航到以前下载的文件,选择ImageTarget1 ,并将其Width设置为1并单击Add 。 (注意:如果您想创建自己的Image Target,请先阅读该指南 。)
![](/assets/blank.gif)
现在,您可以下载数据库,选择Unity Editor作为所选平台。 打开文件,然后选择所有要导入的元素。 我们还必须准备Unity场景,以使用我们创建的该数据库识别ImageTarget 。
在Unity编辑器中,单击I mageTarget对象。 首先,在对象检查器中找到并展开“ 图像目标行为 ”。 选择一种预定义的类型 。 选择我们先前为Database创建的映像目标。 最后,确保同时禁用“ 启用扩展跟踪”和“ 启用智能地形”选项。
![](/assets/blank.gif)
ImageTarget预制件由一系列组件组成,包括一些脚本,例如Image Target Behavior, T urn Off Behavior和Default Tracker Event Handler 。 如果您想深入了解系统的工作原理,请阅读这些脚本并尝试了解它们与其他组件的关系。
但是,对于本教程,我们不会做得太深。 我们只需要专注于Default Tracker Event Handler ,当图像目标跟踪状态发生变化时,它将接收呼叫。 因此,让我们将此脚本用作创建自己的脚本行为的基础。
创建此脚本的副本,我们可以对其进行扩展。 首先选择Default Tracker Event Handler ,单击选项并选择Edit Script 。 现在,复制脚本。 如果使用的是MonoDevelop,请单击“ 文件” >“ 另存为”,然后另存为ImageTargetBehavior ,然后将其保存在“ 脚本”文件夹中。
TargetBehaviorScript脚本
我们的脚本中不需要Vuforia
命名空间。 删除“ namespace Vuforia
”行和括号。 这意味着我们要访问Vuforia
名称空间时需要显式引用它:
using UnityEngine;
using System.Collections;
public class BaseScript : MonoBehaviour, Vuforia.ITrackableEventHandler
{// code here
}
此类中最重要的方法是OnTrackableStateChanged
方法,该方法可在相机设备找到或丢失图像目标时接收呼叫。 根据目标状态,它调用OnTrackingFound
或OnTrackingLost
,我们也需要编辑这些方法。 但是首先,让我们考虑一下我们希望图像目标如何表现。
在此游戏中,用户将捍卫出现在图像目标上的基础。 让我们考虑以下游戏机制:
- 一旦目标被系统识别,基地就会出现,敌人开始以神风队风格生成并飞向基地。
- 每次敌人击中基地时,基地都会受到一定的伤害,敌人将被摧毁。
- 为了赢得游戏,用户必须在摧毁基地之前射击并消灭所有敌人。
- 如果图像目标丢失(从设备相机中不再可见),游戏将启动倒数计时器。 如果计时器为零,则游戏将失败。 当目标丢失时,所有敌人将停止向基地前进。
因此,我们需要在上一个教程中构建的内容之上调整这些游戏机制。 我们将在下一部分使用名为_SpawnController的空对象创建敌人的生成逻辑,使用游戏第一部分中采用的相同逻辑。
现在,让我们看一下跟踪发现的逻辑。
private void OnTrackingFound ()
{EnableRendererAndCollider ();// Inform the system that the target was foundStartCoroutine (InformSpawnCtr (true));
}private void OnTrackingLost ()
{DisableRendererAndCollider ();// Inform the system that the target was lostStartCoroutine (InformSpawnCtr (false));
}// inform SpanController that base was founded
private IEnumerator InformSpawnCtr (bool isOn)
{// move spawning positionGameObject spawn = GameObject.FindGameObjectWithTag ("_SpawnController");yield return new WaitForSeconds (0.2f);// inform SpanControllerif (isOn) {spawn.GetComponent<SpawnScript2> ().BaseOn (transform.position);} else {spawn.GetComponent<SpawnScript2> ().BaseOff ();}
}
回到Unity编辑器中,我们可以创建将由spawn控制器生成的基础对象。
首先,在ImageTarget对象上,禁用“ 默认可跟踪事件处理程序”脚本。
接下来,单击“ 添加组件 ”,然后选择“ 目标行为脚本” 。 在“ 层次结构”面板中,右键单击ImageTarget并创建一个名为“ Base ”的新多维数据集。 该多维数据集应插入ImageTarget对象内。
确保底座已启用Box Collider和Mesh Renderer 。
您也可以选择使用在Vuforia中较早提交的ImageTarget作为纹理在ImageTarget内插入一个Plane对象。 这将产生有趣的效果,从目标投射阴影并创造更丰富的体验。
![](/assets/blank.gif)
修改SpawnScript
现在,我们将适应上一教程中使用的_SpawnController 。 保存当前场景, 然后从上一教程中打开ShootTheCubesMain 。 在“ 层次结构”面板中,选择_SpawnController并将其拖动到Prefabs文件夹以使其成为Unity Prefab 。
保存此新场景,然后重新打开DefendTheBase 。 将_SpawnController从prefabs文件夹拖动到“ 层次结构”面板。 选择_SpawnController后 ,在“ 检查器”面板上单击“ 添加标签 ”。 将新标签命名为_SpawnController并将其应用于对象。
在“项目”窗口中,选择“ 预制”文件夹中的“ 多维数据集”元素,然后将其“ 标记”设置回到“检查器”中,使其位于检查器中。
![](/assets/blank.gif)
最后,打开Scripts文件夹并打开SpawnScript 。 我们需要使此脚本适应加载的场景。
using UnityEngine;
using UnityEngine.SceneManagement;
using System.Collections;
using System.Collections.Generic;using Vuforia;public class SpawnScript : MonoBehaviour
{#region VARIABLESprivate bool mSpawningStarted = false;// Cube element to spawnpublic GameObject mCubeObj;// Qtd of Cubes to be Spawnedpublic int mTotalCubes = 10;private int mCurrentCubes = 0;// Time to spawn the Cubespublic float mTimeToSpawn = 1f; private int mDistanceFromBase = 5;private List<GameObject> mCubes;private bool mIsBaseOn;private Scene mScene;#endregion // VARIABLES#region UNITY_METHODS// Use this for initializationvoid Start (){mScene = SceneManager.GetActiveScene();mCubes = new List<GameObject> ();if ( mScene.name == "ShootTheCubesMain" ){StartSpawn();}}// Update is called once per framevoid Update (){}#endregion // UNITY_METHODS
接下来,我们需要创建两个公共方法来在找到或丢失目标时接收来自TargetBehaviorScript
调用:
当摄像机找到目标并显示Base对象时,将调用
BaseOn (Vector3 basePosition)
。 它将更改生成位置,开始该过程,并通知先前添加到该阶段的所有多维数据集可见该基础。当目标丢失时,将使用
BaseOff()
方法。 它将停止暂存过程,并通知所有多维数据集元素已丢失基础。
#region PUBLIC_METHODS// Base was found by the trackerpublic void BaseOn (Vector3 basePosition){Debug.Log ("SpawnScript2: BaseOn");mIsBaseOn = true;// change positionSetPosition (basePosition);// start spawning process if necessaryStartSpawn ();// inform all cubes on screen that base appearedInformBaseOnToCubes ();}// Base lost by the trackerpublic void BaseOff (){ mIsBaseOn = false;mSpawningStarted = false;// inform all cubes on screen that base is lostInformBaseOffToCubes ();}#endregion // PUBLIC_METHODS
SetPosition (System.Nullable<Vector3> pos)
使用目标的当前位置来修改对象的x,y和z轴,当加载的场景为ShootTheCubesMain时,它也可以接收null
值。
#region PRIVATE_METHODS// We'll use a Coroutine to give a little// delay before setting the positionprivate IEnumerator ChangePosition (){Debug.Log ("ChangePosition");yield return new WaitForSeconds (0.2f);// Define the Spawn position only once// change the position only if Vuforia is activeif (VuforiaBehaviour.Instance.enabled)SetPosition (null);}// Set positionprivate void SetPosition (System.Nullable<Vector3> pos){if (mScene.name == "ShootTheCubesMain") {// get the camera positionTransform cam = Camera.main.transform;// set the position 10 units ahead of the camera positiontransform.position = cam.forward * 10;} else if (mScene.name == "DefendTheBase") {if (pos != null) {Vector3 basePosition = (Vector3)pos;transform.position = new Vector3 (basePosition.x, basePosition.y + mDistanceFromBase, basePosition.z);}}}
InformBaseOnToCubes()
和InformBaseOffToCubes()
负责向所有暂存多维数据集通知当前基本状态。
// Inform all spawned cubes of the base positionprivate void InformBaseOnToCubes (){// Debug.Log("InformBaseOnToCubes");foreach (GameObject cube in mCubes) {cube.GetComponent<CubeBehaviorScript> ().SwitchBaseStatus (mIsBaseOn);}}// Inform to all cubes that the base is offprivate void InformBaseOffToCubes (){// Debug.Log("InformBaseOffToCubes");foreach (GameObject cube in mCubes) {cube.GetComponent<CubeBehaviorScript> ().SwitchBaseStatus (mIsBaseOn);}}
SpawnLoop()
和SpawnElement()
方法使用的逻辑与上一教程几乎相同。
// Start spawning processprivate void StartSpawn (){if (!mSpawningStarted) {// begin spawnmSpawningStarted = true;StartCoroutine (SpawnLoop ());}}// Loop Spawning cube elementsprivate IEnumerator SpawnLoop (){if (mScene.name == "ShootTheCubesMain") {// Defining the Spawning PositionStartCoroutine (ChangePosition ());}yield return new WaitForSeconds (0.2f);// Spawning the elementswhile (mCurrentCubes <= (mTotalCubes - 1)) {// Start the process with different conditions// depending on the current stage nameif (mScene.name == "ShootTheCubesMain" ||(mScene.name == "DefendTheBase" && mIsBaseOn)) {mCubes.Add (SpawnElement ());mCubes [mCurrentCubes].GetComponent<CubeBehaviorScript> ().SwitchBaseStatus (mIsBaseOn);mCurrentCubes++;}yield return new WaitForSeconds (Random.Range (mTimeToSpawn, mTimeToSpawn * 3));}}// Spawn a cubeprivate GameObject SpawnElement (){// spawn the element on a random position, inside a imaginary sphereGameObject cube = Instantiate (mCubeObj, (Random.insideUnitSphere * 4) + transform.position, transform.rotation) as GameObject;// define a random scale for the cubefloat scale = Random.Range (0.5f, 2f);// change the cube scalecube.transform.localScale = new Vector3 (scale, scale, scale);return cube;}#endregion // PRIVATE_METHODS
创造敌人
现在我们需要创建一些敌人。 我们将使用在上一教程中创建的Cube对象,对其脚本进行一些修改。
在Prefabs文件夹中,将一个Cube对象添加到层次结构中。 然后选择对象并编辑CubeBehaviorScript 。
我们将在此脚本中保留几乎相同的逻辑,但有以下差异:
- 当摄像机找到目标时, 立方体将追击基地 。
- 当魔方击中基地时 ,它会自我破坏并对基地造成一定的伤害。
- 脚本需要知道加载的场景的名称并相应地进行调整。
using UnityEngine;
using UnityEngine.SceneManagement;
using System.Collections;public class CubeBehaviorScript : MonoBehaviour {#region VARIABLESpublic float mScaleMax = 1f;public float mScaleMin = 0.2f;public int mCubeHealth = 100;// Orbit max Speedpublic float mOrbitMaxSpeed = 30f;public float velocityToBase = 0.4f;public int damage = 10;// Orbit speedprivate float mOrbitSpeed;// Orbit directionprivate Vector3 mOrbitDirection;// Max Cube Scaleprivate Vector3 mCubeMaxScale;// Growing Speedpublic float mGrowingSpeed = 10f;private bool mIsCubeScaled = false;private bool mIsAlive = true;private AudioSource mExplosionFx;private GameObject mBase;private bool mIsBaseVisible = false;private Vector3 mRotationDirection;private Scene mScene;#endregion
如果场景的名称为DefendTheBase
,则它必须找到Base对象并开始向其移动。
#region UNITY_METHODSvoid Start () {// Get Scene namemScene = SceneManager.GetActiveScene();CubeSettings();}void Update () {// makes the cube orbit and rotateRotateCube();if ( mScene.name == "DefendTheBase" ) {// move cube towards the base, when it's visibleMoveToBase ();}// scale cube if neededif ( !mIsCubeScaled )ScaleObj();}#endregion
CubeSettings()
还需要根据加载的场景进行调整。 多维数据集仅在DefendTheBase
场景的y轴上旋转。
#region PRIVATE_METHODSprivate void CubeSettings (){// defining the orbit directionfloat x = Random.Range ( -1f, 1f );float y = Random.Range (-1f, 1f);float z = Random.Range ( -1f, 1f );// TODO update tutorial with new code// define settings according to scene nameif ( mScene.name == "ShootTheCubesMain" ){mOrbitDirection = new Vector3( x, y, z );}else if ( mScene.name == "DefendTheBase" ){// orbit only on y axismOrbitDirection = new Vector3 (0, y, 0);// scale size must be limitedmScaleMin = 0.05f;mScaleMax = 0.2f;velocityToBase = 0.2f;}// rotating around its axisfloat rx = Random.Range (-1f, 1f);float ry = Random.Range (-1f, 1f);float rz = Random.Range (-1f, 1f);mRotationDirection = new Vector3 (rx, ry, rz);// defining speedmOrbitSpeed = Random.Range (5f, mOrbitMaxSpeed);// defining scalefloat scale = Random.Range (mScaleMin, mScaleMax);mCubeMaxScale = new Vector3 (scale, scale, scale);// set cube scale to 0, to grow it latertransform.localScale = Vector3.zero;// getting Explosion Sound EffectmExplosionFx = GetComponent<AudioSource> ();}
我们将向RotateCube()
方法添加一些新逻辑。 当目标可见时,多维数据集对象将围绕底座旋转。 当目标不可见时,它们将继续使用与上一教程相同的逻辑围绕Camera旋转。
// Rotate the cube around the baseprivate void RotateCube (){// rotate around base or cameraif (mIsBaseVisible && mBase != null && mIsAlive) {// rotate cube around basetransform.RotateAround (mBase.transform.position, mOrbitDirection, mOrbitSpeed * Time.deltaTime);} else {transform.RotateAround (Camera.main.transform.position, mOrbitDirection, mOrbitSpeed * Time.deltaTime);}transform.Rotate (mRotationDirection * 100 * Time.deltaTime);}// Scale object from 0 to 1private void ScaleObj(){// growing objif ( transform.localScale != mCubeMaxScale )transform.localScale = Vector3.Lerp( transform.localScale, mCubeMaxScale, Time.deltaTime * mGrowingSpeed );elsemIsCubeScaled = true;}
要将对象移向基座,我们首先需要检查基座是否存在,然后将定位步骤应用于该对象。
// Move the cube toward the baseprivate void MoveToBase (){// make the cube move towards the base only if base is presentif (mIsBaseVisible && mIsAlive && gameObject != null && mBase != null) {float step = velocityToBase * Time.deltaTime;transform.position = Vector3.MoveTowards (transform.position, mBase.transform.position, step);}}
DestroyCube()
方法与以前相同,但是现在我们将添加一个新方法,即TargetHit(GameObject)
方法,该方法在击中底座时将被调用。 请注意,BaseHealthScript中引用TargetHit()
尚未建立。
// make a damage on targetprivate void TargetHit (GameObject target){Debug.Log ("TargetHit: " + target.name);if (target.name == "Base") {// make damage on baseMyBase baseCtr = target.GetComponent<MyBase> ();baseCtr.TakeHit (damage);StartCoroutine (DestroyCube ());}}// Destroy Cubeprivate IEnumerator DestroyCube(){mIsAlive = false;mExplosionFx.Play();GetComponent<Renderer>().enabled = false;yield return new WaitForSeconds(mExplosionFx.clip.length);Destroy(gameObject);}#endregion
最后,我们将添加要在多维数据集命中时,与基础碰撞时或当基础更改状态时调用的公共方法。
#region PUBLIC_METHODS// Cube gor Hit// return 'false' when cube was destroyedpublic bool Hit( int hitDamage ){mCubeHealth -= hitDamage;if ( mCubeHealth >= 0 && mIsAlive ) {StartCoroutine( DestroyCube());return true;}return false;}public void OnCollisionEnter (Collision col){TargetHit (col.gameObject);}// Receive current base statuspublic void SwitchBaseStatus (bool isOn){// stop the cube on the movement toward basemIsBaseVisible = isOn;if (isOn) {mBase = GameObject.Find ("Base");} else {mBase = null;}}#endregion
控制基础健康
敌人正在上演并飞向基地,但是它们碰撞时不会对基地和敌人造成任何伤害。 我们需要创建一个脚本来响应冲突,还需要在屏幕上添加一个健康栏,以便用户知道他们的状况如何。
让我们开始添加健康栏。 在Unity编辑器的“ 层次结构”面板中,单击创建 > UI > 滑块 。 新的Canvas元素将添加到层次结构中。 它包含UI元素,包括新的Slider 。 展开“ 画布”,然后选择“ 滑块” 。
将滑块元素名称更改为UIHealth 。 在“ 检查器”面板中,展开“ 矩形变换”,然后将“ 宽度”设置为400 ,将“ 高度”设置为40 。 将位置X设置为-220 , 位置Y设置为30 , 位置Z设置为0 。
现在,在层次结构中展开滑块脚本。 取消选择“ 交互”选项。 对于“ 目标图形” ,单击右侧的小“点”,然后选择背景图像。
- 将“ 最小值”设置为0 ,将“ 最大值”设置为100 。
- 选择整数 。
- 将值设置为100 。
![](/assets/blank.gif)
现在,展开“ 滑块”面板以显示其子元素: Background , Fill Area和Handle Slide Area 。
- 删除处理幻灯片区域 。
- 选择背景并将其颜色设置为较深的绿色阴影,例如
#12F568FF
。 - 展开“ 填充区域”并选择“ 填充”对象,并将其颜色设置为
#7FEA89FF
。
这就是游戏窗口与运行状况栏的外观。
![](/assets/blank.gif)
基本运行状况脚本
代码很简单; 它只是从基地生命值的总和中减去敌人造成的伤害。 一旦生命值降为零,玩家就会输掉比赛。 还将向基础添加旋转动画。 创建一个名为MyBase的新C#脚本。
using UnityEngine;
using UnityEngine.UI;
using System.Collections;public class MyBase : MonoBehaviour
{#region VARIABLEpublic float rotationSpeed = 10f;public int health = 100;public AudioClip explosionSoundFx;public AudioClip hitSoundFx;// TODO choose a different sound for the Hitprivate bool mIsAlive = true;private AudioSource mAudioSource;public Slider mHealthSlider;#endregion // VARIABLES#region UNITY_METHODS// Use this for initializationvoid Start (){mAudioSource = GetComponent<AudioSource> ();mHealthSlider.maxValue = health;mHealthSlider.value = health;}// Update is called once per framevoid Update (){RotateBase ();}#endregion // UNITY_REGION#region PRIVATE_METHODSprivate void RotateBase (){if ( mIsAlive && gameObject != null ) {// implement object rotationtransform.Rotate ( Vector3.up, rotationSpeed * Time.deltaTime);}}// Destroy baseprivate IEnumerator DestroyBase (){mIsAlive = false;mAudioSource.clip = explosionSoundFx;mAudioSource.Play ();GetComponent<Renderer> ().enabled = false;// inform all Enemies that Base is LostGameObject[] enemies = GameObject.FindGameObjectsWithTag ("Enemy");foreach (GameObject e in enemies) {e.gameObject.GetComponent<EnemyScript> ().SwitchBaseStatus (false);}yield return new WaitForSeconds (mAudioSource.clip.length);Destroy (gameObject);}#endregion // PRIVATE_METHODS#region PUBLIC_METHODS// receive damagepublic void TakeHit (int damage){health -= damage;mHealthSlider.value = health;if (health <= 0) {StartCoroutine (DestroyBase ());} else {mAudioSource.clip = hitSoundFx;mAudioSource.Play ();}}#endregion // PUBLIC_METHODS
}
现在,我们需要添加和配置脚本。
在层次结构中选择基础 ,单击添加组件 ,然后添加音频源 。 现在将MyBase拖动到Base元素,然后在“ 检查器”面板中,展开MyBase 。 为爆炸和打击选择声音效果。 我已经使用了上一教程中使用的爆炸剪辑,但可以随时添加自己的爆炸剪辑。 最后,在Health Slider中 ,选择UISlider元素。
![](/assets/blank.gif)
保卫基地
我们新的游戏体验即将完成。 我们只需要发射一些激光就可以保卫我们的基地。 让我们为激光创建一个脚本!
首先将_PlayerController从Prefab文件夹拖到层次结构中。 展开_PlayerController并选择_LaserController 。 在“ 检查器”面板中,找到“ 激光脚本” ,然后单击“ 编辑” 。
我们需要在此脚本中更改的唯一内容是激光的位置。
// Shot the Laserprivate void Fire (){// Get ARCamera TransformTransform cam = Camera.main.transform;// Define the time of the next firemNextFire = Time.time + mFireRate;// Set the origin of the RayCastVector3 rayOrigin = cam.position;// Show the Laser using a CoroutineStartCoroutine (LaserFx ());// Holds the Hit informationRaycastHit hit;// Set the origin position of the Laser Line// It will add 10 units down from the ARCamera// We adopted this logic for simplicityVector3 laserStartPos = new Vector3 (cam.position.x, cam.position.y -2f, cam.position.z);mLaserLine.SetPosition (0, laserStartPos); // Checks if the RayCast hit somethingif (Physics.Raycast (rayOrigin, cam.forward, out hit, mFireRange)) {// Set the end of the Laser Line to the object hitmLaserLine.SetPosition (1, hit.point);// check target typeif (hit.collider.tag == "Enemy") {CubeBehaviorScript cubeCtr = hit.collider.GetComponent<CubeBehaviorScript> ();if (cubeCtr != null) {if (hit.rigidbody != null) {hit.rigidbody.AddForce (-hit.normal * mHitForce);cubeCtr.Hit (mLaserDamage);}}}} else {// Set the enfo of the laser line to be forward the camera// using the Laser rangemLaserLine.SetPosition (1, cam.forward * mFireRange);}}
试用游戏
那是很多工作,但是现在该玩游戏了! 打印出目标图像,然后尝试在手机或平板电脑上运行游戏。 玩得开心,看看是否可以提出一些改进游戏的方法!
至此,您已经对Vuforia系统如何工作以及如何在Unity中使用它有了很好的了解。 我希望您和我一样喜欢这次旅行。 再见!
翻译自: https://code.tutsplus.com/tutorials/create-a-pokemon-go-style-augmented-reality-game-with-vuforia-part-3--cms-28246
使用Vuforia创建神奇宝贝GO风格增强现实游戏:图像目标相关推荐
- 使用Vuforia创建神奇宝贝GO风格增强现实游戏
您将要创造的 1.简介 在本系列的第一篇文章中 ,我们讨论了Vuforia在创建增强现实体验方面的出色表现,现在我们准备在实际的应用程序中实践这些概念. 在本教程中,我们将开始在Unity 3D上使用 ...
- 使用Vuforia创建PokémonGO风格增强现实游戏:第2部分
您将要创造的 我们已经开始开发名为Shoot the Cubes的增强现实游戏. 现在是时候通过增加互动和增加体验来改进游戏了. 我们将主要关注Unity给我们带来的可能性,而忽略Vuforia的细节 ...
- 使用高通Vuforia开发AR增强现实游戏(开篇)
@废话在前 之前想做暴风魔镜的VR游戏,最后来香港学习设备没带过来就没继续做,现在开始学习研究做一下AR游戏开发,毕竟对设备的要求比较低,很方便,看了不少资料,最后还是选了Vuforia这个经典的AR ...
- 【Unity教程】创建一个完整的驾驶游戏
专业游戏设计 你会学到什么 在unity HDRP创建一个完整的驾驶游戏 定制不同类型的汽车 将人工智能汽车和人工智能航路点系统添加到你的赛道上 添加汽车展厅菜单以解锁和购买新车 在Blender中设 ...
- 怀旧:制作一款复古风格的游戏
教程信息 难度:中级 预计完成时间:1小时 正如很多古老的事物都会被再一次兴起一样,复古的游戏也越来越受欢迎了.凭借着强烈的复古情怀以及IOS和Andriod设备上大量的休闲类.街机风格的游戏,复古风 ...
- 如何用Unity 和Vuforia 创建一款AR应用
预先善其事,必先利其器,话不多说,一下就是我们使用软件的版本号: · Vuforia 5 · Unity 3D 5.x · Android Studio and SDK tools ...
- Unity 2D游戏开发快速入门第1章创建一个简单的2D游戏
Unity 2D游戏开发快速入门第1章创建一个简单的2D游戏 即使是现在,很多初学游戏开发的同学,在谈到Unity的时候,依然会认为Unity只能用于制作3D游戏的.实际上,Unity在2013年发布 ...
- FreeEIM通讯软件无论是画面风格还是游戏内容
摘要:FreeEIM通讯软件 2012年07月25日而增长最快的将是网络内容安全设备,48小时后,才是王道梦幻修女出来看仙女哦不对,简直是美呆了,FreeEIM通讯软件无论是画面风格还是游戏内容,里面 ...
- android 赛车 源码,android 3D风格赛车游戏源码
android 3D风格赛车游戏源码,基于Libgdx 框架开发,三维视觉,包含20量敌方车辆和10量我方车辆,支持Admob广告插件,带游戏排行榜和成就系统 ,兼容手机.平板电脑等多种屏幕尺寸 ,游 ...
最新文章
- idm 爬取网站 跳转路径_儋州网站案例基本流程,电子元件网络推广,浅析
- WCF中的web.config配置文件
- unzipping/Users/xq/.gradle/wrapper /dists/gradle-3.3-all/55gk2rcmfc6p2dg9u9ohc3hw9/gradle-3.3-all.zi
- android app两种调试方法
- 用友U8清除站点异常任务SQL语句
- java calendar clear_java.util.Calendar clear()方法
- 2014年10月30日-----SQL的基础知识
- java爬取_java实现爬取知乎用户基本信息
- Linux之vim详解
- 【dsp】基于dsp28335的称重系统设计
- [Windows]msvcr110.dll运行库缺失问题解决方案
- [清橙A1364]社交网络结构洞【暴力】
- ISTP概况及网络版检索方法
- PHP 乐心 发送验证码 验证码识别
- 计算机键盘正确指法,键盘指法,详细教您盲打及快速打字指法练习的步骤
- springmvc ajax 传参
- k3 修复服务器,金蝶K3数据修复服务工具包
- virtualbox虚拟机识别U盘的详细教程
- 线程的6种状态(NEW,RUNNABLE,BLOCKED,WAITING,TINED_WATING,TEMINATE)
- C语言编写取单词首字母,C语言练习之单词首字母大写