В этом уроке мы вернемся к библиотеке Vuforia Augmented Reality (AR), исследуя один из ее самых интересных ресурсов — Image Target . Мы расширим игру Shoot the Cubes, которую мы создали на предыдущих уроках, добавив новый уровень, где игрок должен защищать свою базу от атакующих кубов.
Этот учебник может быть выполнен в одиночку, хотя, если вы хотите познакомиться с AR с помощью Vuforia и Unity3D, ознакомьтесь с предыдущими статьями серии.
- Мобильная разработкаПокемон GO Стиль дополненной реальности с Vuforia
- Мобильная разработкаСоздайте игру дополненной реальности Pokémon GO Style с Vuforia
Цели изображения
Любое изображение может быть Vuforia Image Target . Однако чем детальнее и сложнее изображение, тем лучше оно будет распознаваться алгоритмом.
Многие факторы будут частью распознавания вычислений, но в основном изображение должно иметь разумный уровень контрастности, разрешения и отличительных элементов. Фотография голубого неба не сработает очень хорошо, но картинка с травой будет работать изящно. Целевые изображения могут быть отправлены вместе с приложением, загружены в приложение через облако или непосредственно созданы пользователем в приложении.
Добавление цели
Давайте начнем с добавления элемента ImageTarget в наш проект Unity.
Сначала загрузите материалы курса с кнопки на боковой панели. Затем в своем проекте Unity создайте новую сцену с именем DefendTheBase : в окне « Проект» выберите папку « Сцены » и нажмите « Создать» > « Сцена». Теперь откройте эту сцену и удалите все объекты сцены по умолчанию из иерархии.
Далее мы добавим свет и камеру. Нажмите Add > Light > Directional Light, чтобы добавить направленный свет. Выберите этот новый источник света и установите « Мягкую тень» в качестве параметра « Тип тени» .
После этого перетащите объект ARCamera из Vuforia > Prefabs . Выберите объект ARCamera и на панели инспектора установите лицензионный ключ приложения, созданный на странице разработчика Vuforia ( инструкции см. В первом руководстве ). Выберите DEVICE_TRACKING для World Center Mod .
Наконец, перетащите ImageTarget в иерархию от Vuforia > Prefabs .
Теперь мы должны добавить базу данных Vuforia. Сначала перейдите на https://developer.vuforia.com/target-manager . Нажмите на Добавить базу данных и выберите имя.
Есть три типа базы данных на выбор:
- Устройство : база данных сохраняется на устройстве, и все цели обновляются локально.
- Облако : База данных на серверах Vuforia.
- VuMark : База данных, эксклюзивная для целей VuMark. Он также сохраняется на устройстве.
В этом случае выберите опцию « Устройство» и нажмите « Создать» .
Выберите новую базу данных, чтобы мы могли начать добавлять к ней цели. Теперь пришло время добавить цели в базу данных. Сейчас мы просто будем использовать опцию Single Image .
Перейдите к ранее загруженным файлам, выберите ImageTarget1 , установите его ширину 1 и нажмите « Добавить» . (Примечание. Если вы предпочитаете создавать собственную цель изображения, сначала прочтите руководство .)

Теперь вы можете скачать базу данных, выбрав Unity Editor в качестве выбранной платформы. Откройте файл и выберите все элементы для импорта. Мы также должны подготовить нашу сцену Unity для распознавания ImageTarget с этой базой данных, которую мы создали.
В редакторе Unity нажмите на объект I mageTarget . Сначала найдите и разверните Image Target Behavior в инспекторе объектов. Выберите тип предопределенного . Выберите цель изображения, которую мы создали ранее для базы данных . Наконец, убедитесь, что опции Enable Extended Tracking и Enable Smart Terrain отключены.

Префаб ImageTarget состоит из ряда компонентов, включая некоторые сценарии, такие как Image Target Behavior, T urn Off Behavior и обработчик событий по умолчанию для Tracker . Если вы хотите глубоко понять, как работает система, прочитайте эти сценарии и попытайтесь понять их связь с другими компонентами.
Для этого урока мы не будем копать слишком глубоко. Нам нужно сконцентрироваться только на обработчике событий по умолчанию для трекера , который принимает вызовы, когда изменяется статус отслеживания цели изображения. Итак, давайте использовать этот скрипт в качестве основы для создания нашего собственного поведения скрипта.
Создайте копию этого скрипта, которую мы можем расширить. Сначала выберите Обработчик событий по умолчанию , нажмите на опции и выберите Редактировать скрипт . Теперь сделайте копию сценария. Если вы используете MonoDevelop, нажмите « Файл» > « Сохранить как» и сохраните как ImageTargetBehavior , сохранив его в папке « Сценарии ».
Скрипт TargetBehaviorScript
Нам не понадобится пространство имен Vuforia в нашем скрипте. Уберите строку « namespace Vuforia » и скобки. Это означает, что нам нужно явно ссылаться на пространство имен Vuforia когда мы хотим получить доступ к его классам:
|
1
2
3
4
5
6
|
using UnityEngine;
using System.Collections;
public class BaseScript : MonoBehaviour, Vuforia.ITrackableEventHandler
{
// code here
}
|
Наиболее важным методом в этом классе будет метод OnTrackableStateChanged который принимает вызовы, когда целевое изображение найдено или потеряно устройством камеры. В соответствии с целевым статусом он вызывает OnTrackingFound или OnTrackingLost , и нам нужно будет также отредактировать эти методы. Но сначала давайте подумаем о том, как мы хотим, чтобы цель изображения работала.
В этой игре пользователь будет защищать базу, которая появляется на изображении цели. Давайте рассмотрим следующую игровую механику:
- Как только цель распознается системой, появляется база, и враги начинают появляться и летят к базе в стиле камикадзе.
- Каждый раз, когда враг поражает базу, база будет получать некоторый урон, и враг будет уничтожен.
- Чтобы выиграть игру, пользователь должен стрелять и уничтожать всех врагов, прежде чем база будет уничтожена.
- Если цель изображения потеряна (больше не видна с камеры устройства), игра запустит таймер обратного отсчета. Если таймер обнуляется, игра проиграна. Пока цель потеряна, все враги перестанут продвигаться к базе.
Поэтому нам нужно адаптировать игровую механику к тому, что мы создали в предыдущем уроке. В следующем разделе мы создадим логику появления врага с пустым объектом с именем _SpawnController , используя ту же логику, что и в первой части игры.
А пока давайте посмотрим на логику отслеживания найденных.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
private void OnTrackingFound ()
{
EnableRendererAndCollider ();
// Inform the system that the target was found
StartCoroutine (InformSpawnCtr (true));
}
private void OnTrackingLost ()
{
DisableRendererAndCollider ();
// Inform the system that the target was lost
StartCoroutine (InformSpawnCtr (false));
}
// inform SpanController that base was founded
private IEnumerator InformSpawnCtr (bool isOn)
{
// move spawning position
GameObject spawn = GameObject.FindGameObjectWithTag («_SpawnController»);
yield return new WaitForSeconds (0.2f);
// inform SpanController
if (isOn) {
spawn.GetComponent<SpawnScript2> ().BaseOn (transform.position);
} else {
spawn.GetComponent<SpawnScript2> ().BaseOff ();
}
}
|
Вернувшись в редактор Unity, мы можем создать базовый объект, который будет порождаться контроллером spawn.
Сначала на объекте ImageTarget отключите скрипт обработчика событий по умолчанию .
Затем нажмите « Добавить компонент» и выберите целевой сценарий поведения . На панели « Иерархия» щелкните правой кнопкой мыши ImageTarget и создайте новый куб с именем « Base ». Этот куб должен быть вставлен в объект ImageTarget .
Убедитесь, что на базе включены Box Collider и Mesh Renderer .
При желании вы также можете вставить объект Plane в ImageTarget, используя ImageTarget, ранее представленный в Vuforia, в качестве текстуры. Это создаст интересный эффект, проецируя тени от цели и создавая более богатый опыт.

Адаптация SpawnScript
Теперь мы адаптируем _SpawnController, использованный в последнем уроке. Сохраните текущую сцену и откройте ShootTheCubesMain из последнего урока. На панели « Иерархия» выберите _SpawnController и перетащите его в папку « Prefabs », чтобы сделать его « Unity Prefab» .
Сохраните эту новую сцену и снова откройте DefendTheBase . Перетащите _SpawnController из папки prefabs на панель « Иерархия» . Выбрав _SpawnController , нажмите « Добавить тег» на панели « Инспектор» . Назовите новый тег _SpawnController и примените его к объекту.
В окне «Проект» выберите элемент « Куб» в папке « Prefab » и установите для его тега « Инспектор» значение «Враг».

Наконец, откройте папку Scripts и откройте SpawnScript . Нам нужно, чтобы этот скрипт адаптировался к загруженной сцене.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
using UnityEngine;
using UnityEngine.SceneManagement;
using System.Collections;
using System.Collections.Generic;
using Vuforia;
public class SpawnScript : MonoBehaviour
{
#region VARIABLES
private bool mSpawningStarted = false;
// Cube element to spawn
public GameObject mCubeObj;
// Qtd of Cubes to be Spawned
public int mTotalCubes = 10;
private int mCurrentCubes = 0;
// Time to spawn the Cubes
public 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 initialization
void Start ()
{
mScene = SceneManager.GetActiveScene();
mCubes = new List<GameObject> ();
if ( mScene.name == «ShootTheCubesMain» )
{
StartSpawn();
}
}
// Update is called once per frame
void Update ()
{
}
#endregion // UNITY_METHODS
|
Далее нам нужно создать два открытых метода для приема вызовов от TargetBehaviorScript когда цель найдена или потеряна:
-
BaseOn (Vector3 basePosition), когда цель обнаруживается камерой и отображается объект Base . Он изменит позицию нереста, запустит процесс и проинформирует все кубы, которые были ранее добавлены на сцену, о том, что база видна. -
Метод
BaseOff()будет использоваться, когда цель потеряна. Это остановит процесс постановки и сообщит всем элементам куба, что база была потеряна.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
#region PUBLIC_METHODS
// Base was found by the tracker
public void BaseOn (Vector3 basePosition)
{
Debug.Log («SpawnScript2: BaseOn»);
mIsBaseOn = true;
// change position
SetPosition (basePosition);
// start spawning process if necessary
StartSpawn ();
// inform all cubes on screen that base appeared
InformBaseOnToCubes ();
}
// Base lost by the tracker
public void BaseOff ()
{
mIsBaseOn = false;
mSpawningStarted = false;
// inform all cubes on screen that base is lost
InformBaseOffToCubes ();
}
#endregion // PUBLIC_METHODS
|
SetPosition (System.Nullable<Vector3> pos) использует текущую позицию цели для изменения осей x, y и z объекта, а также может получить null значение, когда загруженная сцена — ShootTheCubesMain .
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
#region PRIVATE_METHODS
// We’ll use a Coroutine to give a little
// delay before setting the position
private IEnumerator ChangePosition ()
{
Debug.Log («ChangePosition»);
yield return new WaitForSeconds (0.2f);
// Define the Spawn position only once
// change the position only if Vuforia is active
if (VuforiaBehaviour.Instance.enabled)
SetPosition (null);
}
// Set position
private void SetPosition (System.Nullable<Vector3> pos)
{
if (mScene.name == «ShootTheCubesMain») {
// get the camera position
Transform cam = Camera.main.transform;
// set the position 10 units ahead of the camera position
transform.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() отвечают за информирование всех поэтапных кубов о текущем базовом состоянии.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
// Inform all spawned cubes of the base position
private void InformBaseOnToCubes ()
{
// Debug.Log(«InformBaseOnToCubes»);
foreach (GameObject cube in mCubes) {
cube.GetComponent<CubeBehaviorScript> ().SwitchBaseStatus (mIsBaseOn);
}
}
// Inform to all cubes that the base is off
private void InformBaseOffToCubes ()
{
// Debug.Log(«InformBaseOffToCubes»);
foreach (GameObject cube in mCubes) {
cube.GetComponent<CubeBehaviorScript> ().SwitchBaseStatus (mIsBaseOn);
}
}
|
SpawnLoop() и SpawnElement() используют почти ту же логику, что и в предыдущем уроке.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
// Start spawning process
private void StartSpawn ()
{
if (!mSpawningStarted) {
// begin spawn
mSpawningStarted = true;
StartCoroutine (SpawnLoop ());
}
}
// Loop Spawning cube elements
private IEnumerator SpawnLoop ()
{
if (mScene.name == «ShootTheCubesMain») {
// Defining the Spawning Position
StartCoroutine (ChangePosition ());
}
yield return new WaitForSeconds (0.2f);
// Spawning the elements
while (mCurrentCubes <= (mTotalCubes — 1)) {
// Start the process with different conditions
// depending on the current stage name
if (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 cube
private GameObject SpawnElement ()
{
// spawn the element on a random position, inside a imaginary sphere
GameObject cube = Instantiate (mCubeObj, (Random.insideUnitSphere * 4) + transform.position, transform.rotation) as GameObject;
// define a random scale for the cube
float scale = Random.Range (0.5f, 2f);
// change the cube scale
cube.transform.localScale = new Vector3 (scale, scale, scale);
return cube;
}
#endregion // PRIVATE_METHODS
|
Создание врагов
Теперь нам нужно создать несколько врагов. Мы будем использовать объект Cube, который мы создали в последнем уроке, внося некоторые изменения в его скрипт.
В папке Prefabs добавьте объект Cube в иерархию. Затем выберите объект и отредактируйте CubeBehaviorScript .
Мы сохраним почти ту же логику в этом скрипте, но со следующими отличиями:
- Куб будет преследовать Базу, когда цель найдена камерой.
- Когда Куб поразит Базу , он разрушит себя и нанесет некоторый урон Базе .
- Сценарий должен знать имя загруженной сцены и соответственно адаптироваться.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
using UnityEngine;
using UnityEngine.SceneManagement;
using System.Collections;
public class CubeBehaviorScript : MonoBehaviour {
#region VARIABLES
public float mScaleMax = 1f;
public float mScaleMin = 0.2f;
public int mCubeHealth = 100;
// Orbit max Speed
public float mOrbitMaxSpeed = 30f;
public float velocityToBase = 0.4f;
public int damage = 10;
// Orbit speed
private float mOrbitSpeed;
// Orbit direction
private Vector3 mOrbitDirection;
// Max Cube Scale
private Vector3 mCubeMaxScale;
// Growing Speed
public 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 и начать двигаться к нему.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
#region UNITY_METHODS
void Start () {
// Get Scene name
mScene = SceneManager.GetActiveScene();
CubeSettings();
}
void Update () {
// makes the cube orbit and rotate
RotateCube();
if ( mScene.name == «DefendTheBase» ) {
// move cube towards the base, when it’s visible
MoveToBase ();
}
// scale cube if needed
if ( !mIsCubeScaled )
ScaleObj();
}
#endregion
|
CubeSettings() также необходимо адаптировать в соответствии с загруженной сценой. Куб вращается только по оси Y для сцены DefendTheBase .
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
#region PRIVATE_METHODS
private void CubeSettings ()
{
// defining the orbit direction
float 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 name
if ( mScene.name == «ShootTheCubesMain» )
{
mOrbitDirection = new Vector3( x, y, z );
}
else if ( mScene.name == «DefendTheBase» )
{
// orbit only on y axis
mOrbitDirection = new Vector3 (0, y, 0);
// scale size must be limited
mScaleMin = 0.05f;
mScaleMax = 0.2f;
velocityToBase = 0.2f;
}
// rotating around its axis
float rx = Random.Range (-1f, 1f);
float ry = Random.Range (-1f, 1f);
float rz = Random.Range (-1f, 1f);
mRotationDirection = new Vector3 (rx, ry, rz);
// defining speed
mOrbitSpeed = Random.Range (5f, mOrbitMaxSpeed);
// defining scale
float scale = Random.Range (mScaleMin, mScaleMax);
mCubeMaxScale = new Vector3 (scale, scale, scale);
// set cube scale to 0, to grow it later
transform.localScale = Vector3.zero;
// getting Explosion Sound Effect
mExplosionFx = GetComponent<AudioSource> ();
}
|
Мы добавим новую логику в метод RotateCube() . Объекты куба будут вращаться вокруг базы, пока цель видна. Когда цель не видна, они будут продолжать вращаться вокруг камеры , используя ту же логику, что и в предыдущем уроке.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
// Rotate the cube around the base
private void RotateCube ()
{
// rotate around base or camera
if (mIsBaseVisible && mBase != null && mIsAlive) {
// rotate cube around base
transform.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 1
private void ScaleObj(){
// growing obj
if ( transform.localScale != mCubeMaxScale )
transform.localScale = Vector3.Lerp( transform.localScale, mCubeMaxScale, Time.deltaTime * mGrowingSpeed );
else
mIsCubeScaled = true;
}
|
Чтобы переместить объект к базе, нам нужно сначала проверить, присутствует ли база, а затем применить шаги позиционирования к объекту.
|
1
2
3
4
5
6
7
8
9
|
// Move the cube toward the base
private void MoveToBase ()
{
// make the cube move towards the base only if base is present
if (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() еще не создан.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
// make a damage on target
private void TargetHit (GameObject target)
{
Debug.Log («TargetHit: » + target.name);
if (target.name == «Base») {
// make damage on base
MyBase baseCtr = target.GetComponent<MyBase> ();
baseCtr.TakeHit (damage);
StartCoroutine (DestroyCube ());
}
}
// Destroy Cube
private IEnumerator DestroyCube(){
mIsAlive = false;
mExplosionFx.Play();
GetComponent<Renderer>().enabled = false;
yield return new WaitForSeconds(mExplosionFx.clip.length);
Destroy(gameObject);
}
#endregion
|
Наконец, мы добавим открытые методы, которые будут вызываться, когда куб получает удар, когда он сталкивается с базой или когда база меняет статус.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
#region PUBLIC_METHODS
// Cube gor Hit
// return ‘false’ when cube was destroyed
public 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 status
public void SwitchBaseStatus (bool isOn)
{
// stop the cube on the movement toward base
mIsBaseVisible = isOn;
if (isOn) {
mBase = GameObject.Find («Base»);
} else {
mBase = null;
}
}
#endregion
|
Контроль базового здоровья
Враги ставятся и летят к базе, но они не наносят никакого урона при столкновении — ни на базу, ни на противника. Нам нужно создать скрипт для реагирования на коллизии, а также добавить панель состояния на экран, чтобы пользователь знал, насколько хорошо они работают.
Давайте начнем добавлять панель здоровья. На панели « Иерархия» в редакторе Unity выберите « Создать» > « Интерфейс» > « Слайдер» . Новый элемент Canvas будет добавлен в иерархию. Он содержит элементы пользовательского интерфейса, в том числе новый слайдер . Разверните холст и выберите ползунок .
Измените имя элемента слайдера на UIHealth . На панели « Инспектор» разверните « Прямоугольное преобразование» и установите « Ширина» на 400 и « Высота» на 40 . Установите Pos X на -220 , Pos Y на 30 и Pos Z на 0 .
Теперь разверните скрипт слайдера в иерархии. Отмените выбор опции Interactable . Для Target Graphic , нажмите на маленькую «точку» справа и выберите фоновое изображение.
- Установите минимальное значение 0 и максимальное значение 100 .
- Выберите Целые числа .
- Установите значение 100 .

Теперь разверните панель « Слайдер», чтобы отобразить его дочерние элементы: фон , область заливки и область обработки слайдов .
- Удалить область слайда ручки .
- Выберите Фон и установите его Цвет на более темный оттенок зеленого, например
#12F568FF. - Разверните Fill Area и выберите объект Fill и установите его цвет
#7FEA89FF.
Вот так должно выглядеть окно игры с индикатором здоровья.

Базовый сценарий здоровья
Код очень прост; он просто вычитает урон, нанесенный противникам, из общего количества здоровья базы. Как только здоровье становится равным нулю, игрок проигрывает игру. Это также добавит анимацию вращения на базу. Создайте новый C # скрипт с именем MyBase .
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class MyBase : MonoBehaviour
{
#region VARIABLE
public float rotationSpeed = 10f;
public int health = 100;
public AudioClip explosionSoundFx;
public AudioClip hitSoundFx;
// TODO choose a different sound for the Hit
private bool mIsAlive = true;
private AudioSource mAudioSource;
public Slider mHealthSlider;
#endregion // VARIABLES
#region UNITY_METHODS
// Use this for initialization
void Start ()
{
mAudioSource = GetComponent<AudioSource> ();
mHealthSlider.maxValue = health;
mHealthSlider.value = health;
}
// Update is called once per frame
void Update ()
{
RotateBase ();
}
#endregion // UNITY_REGION
#region PRIVATE_METHODS
private void RotateBase ()
{
if ( mIsAlive && gameObject != null ) {
// implement object rotation
transform.Rotate ( Vector3.up, rotationSpeed * Time.deltaTime);
}
}
// Destroy base
private IEnumerator DestroyBase ()
{
mIsAlive = false;
mAudioSource.clip = explosionSoundFx;
mAudioSource.Play ();
GetComponent<Renderer> ().enabled = false;
// inform all Enemies that Base is Lost
GameObject[] 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 damage
public void TakeHit (int damage)
{
health -= damage;
mHealthSlider.value = health;
if (health <= 0) {
StartCoroutine (DestroyBase ());
} else {
mAudioSource.clip = hitSoundFx;
mAudioSource.Play ();
}
}
#endregion // PUBLIC_METHODS
}
|
Теперь нам нужно добавить и настроить скрипт.
Выберите Base в иерархии, нажмите Add Component и добавьте аудиоисточник . Теперь перетащите MyBase на элемент Base и на панели « Инспектор» разверните MyBase . Выберите звуковой эффект для взрыва и нажмите. Я использовал клип для взрыва, использованный в последнем уроке, но не стесняйтесь добавлять свой. Наконец, в Health Slider , выберите элемент UISlider .

Защита базы
Наш новый игровой опыт почти закончен. Нам нужно только выстрелить лазерами, чтобы начать защищать нашу базу. Давайте создадим скрипт для лазера!
Сначала перетащите _PlayerController из папки Prefab в иерархию. Разверните _PlayerController и выберите _LaserController . На панели « Инспектор» найдите Laser Script и нажмите « Изменить» .
Единственное, что нам нужно изменить в этом скрипте — это положение лазера.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
// Shot the Laser
private void Fire ()
{
// Get ARCamera Transform
Transform cam = Camera.main.transform;
// Define the time of the next fire
mNextFire = Time.time + mFireRate;
// Set the origin of the RayCast
Vector3 rayOrigin = cam.position;
// Show the Laser using a Coroutine
StartCoroutine (LaserFx ());
// Holds the Hit information
RaycastHit hit;
// Set the origin position of the Laser Line
// It will add 10 units down from the ARCamera
// We adopted this logic for simplicity
Vector3 laserStartPos = new Vector3 (cam.position.x, cam.position.y -2f, cam.position.z);
mLaserLine.SetPosition (0, laserStartPos);
// Checks if the RayCast hit something
if (Physics.Raycast (rayOrigin, cam.forward, out hit, mFireRange)) {
// Set the end of the Laser Line to the object hit
mLaserLine.SetPosition (1, hit.point);
// check target type
if (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 range
mLaserLine.SetPosition (1, cam.forward * mFireRange);
}
}
|
Пробовать игру
Это было много работы, но теперь пришло время играть в игру! Распечатайте целевое изображение и попробуйте запустить игру на своем телефоне или планшете. Повеселитесь и посмотрите, сможете ли вы придумать способы улучшить игру!
На этом этапе вы хорошо понимаете, как работает система Vuforia и как ее использовать с Unity. Я ожидаю, что вам понравилось это путешествие так же, как и мне. До скорого!
Чтобы узнать больше об дополненной реальности с Vuforia и Unity, посмотрите наш видеокурс здесь на Envato Tuts +!


