Quantcast
Channel: 平板电脑
Viewing all articles
Browse latest Browse all 500

Использование сенсорных жестов для управления параметрами физики в Unity* 3D с TouchScript

$
0
0

Download PDF

Автор: Линн Томпсон

При разработке игр и программ моделирования может понадобиться предоставить пользователям возможность управления ресурсами, которые используются в моделировании физики. Из этой статьи вы узнаете, как разрабатывать сцены Unity* 3D с настроенными сенсорными жестами для изменения физических характеристик используемых ресурсов, включая расположение, размер, массу и скорость. Эти изменения можно использовать для улучшения пользовательского интерфейса моделирования или для повышения эстетического качества сцены. В данном примере показана среда Unity 3D под управлением Windows* 8 в качестве удобной платформы для управления физическими характеристиками в играх и программах моделирования с помощью сенсорных жестов.

Настройка сцены Unity 3D

Я настроил геометрию этой сцены в Autodesk 3ds Max*. Я применил к поверхности волновой модификатор и модификатор изгиба; с одной стороны поверхности находится зеленая башня. Эту сцену я экспортировал из Autodesk 3ds Max в формате FBX, а затем импортировал в Unity 3D (см. рис. 1). Измененная поверхность с изгибом и волнами влияет на движение других ресурсов, добавляемых на сцену во время выполнения.

 


Примечание. Убедитесь, что геометрические объекты, импортируемые из сторонних приложений, не содержат настолько много фрагментов поверхностей, что движок Unity 3D будет перегружен или просто перестанет работать. В определенных средах разработки может указываться максимальное допустимое количество вершин и треугольников на каждый импортированный ресурс. Ресурсы в этом примере не используют никакие материалы, шейдеры и текстуры, но если такие ресурсы используются, следует учитывать их влияние на производительность целевой платформы разработки.


 


Рисунок 1. Башня с одной стороны поверхности, применены модификаторы изгиба и волн

Кроме того, с геометрией «отображение во время выполнения» импортированы сферы, которые не отображаются во время выполнения. Эти сферы я разместил над волнообразными выступами (см. рис. 2).

Рисунок 2. Поверхность с волнами, сферы не отрисовываются во время выполнения

Я использую расположение этих сфер в качестве места, откуда сферы будут попадать в сцену. Эти сферы я добавил программно, поэтому добавить их физические свойства нужно тоже програм­мно. Я делаю это с помощью следующего кода (обратите внимание, что имена 17 создающихся сфер - TargetSpawn[000 - 016]):


	int spawnPoint = 1;
	string spawnPointString = "";
	Vector3 spawnPosition = new Vector3(0.0f,0.0f,0.0f);
	Quaternion spawnRotation = new Quaternion(0.0f,0.0f,0.0f,0.0f);
	float spawnTime = 0.0f;


	void Update ()
	{



		spawnTime += Time.deltaTime;
		if(spawnTime > 1.0f)
		{
			spawnTime = 0.0f;

			if(spawnPoint == 17){spawnPoint = 1;}

			if(spawnPoint < 10){spawnPointString = "TargetSpawn00" + spawnPoint;}
			else{spawnPointString = "TargetSpawn0" +  spawnPoint;}

			GameObject spawnPointGO = GameObject.Find(spawnPointString);
			spawnPosition = spawnPointGO.transform.position;

			GameObject targetSphere = (GameObject)Instantiate
			 (GameObject.CreatePrimitive (PrimitiveType.Sphere),
			spawnPosition,spawnRotation);

			Color randomColor = new
			 Color(Random.value,Random.value,Random.value,1.0f);
			targetSphere.renderer.material.color = randomColor;


			targetSphere.collider.tag = "targetSphere";

			targetSphere.transform.localScale = new Vector3(10.0f,10.0f,10.0f);
			targetSphere.AddComponent ("Rigidbody");
			targetSphere.AddComponent ("GenericPan");
			targetSphere.AddComponent ("PanGesture");
			Destroy (targetSphere,60.0f);

			spawnPoint += 1;

		}
	}




При реализации приведенного выше сценария волнообразная основа заполняется твердыми физическими сферами, которые исчезают через 60 секунд (обратите внимание на вызов функции Destroy в предпоследней строке сценария). Можно настроить время до разрушения создаваемых сфер (в моем случае оно равно 60 секундам) на основе возможностей целевой платформы и нужных характеристик сцены. Башня в конце сцены настроена так, чтобы стрелять по капсулам, если они оказываются слишком близко. Эта башня не настроена для упреждающего сопровождения сфер и обычно промахивается (см. рис. 3).

Рисунок 3. Башня стреляет капсулами по создающимся твердым сферам

Создающиеся сферы скатываются в глубину платформы, а капсулы, которыми стреляет зеленая башня, отталкивают их к задней стенке. Больше всего на производительность в этой сцене Unity 3D влияет огромное количество выпущенных башней капсул и созданных сфер, одновременно отображающихся в активном представлении.

Прокрутка

IВ предыдущем разделе я программно применил сценарий GenericPan к созданным сферам.
Этот сценарий GenericPan позволяет пользователям передвигать сферу с помощью жеста прокрутки. Хотя сфера перемещается, преобразование ее локального расположения изменяется в функции Update сценария. Объект по-прежнему является частью физического моделирования при жесте прокрутки, он может взаимодействовать с другими объектами сцены. Я также применил жест GenericPan к прямоугольной задней стенке в сцене, чтобы с помощью стенки можно было передвигать сферы внутри выемки платформы. Можно переносить заднюю стенку, чтобы поместить ее перед башней и защитить, таким образом, созданные сферы от попадания выпускаемых башней капсул. Вот полный код сценария:


using TouchScript.Events;
using TouchScript.Gestures;
using UnityEngine;
using System;
using System.Collections;


public class GenericPan : MonoBehaviour
{
	private Vector3 targetPan;
	private Vector3 startPos;
	private float panSpeed;
	private float panFrac;
	private bool panning;


	void Start ()
	{
		startPos = targetPan = transform.localPosition;
		panSpeed = 10.0f;
		panFrac = 10.0f;
		panning = false;
		GetComponent<PanGesture>().StateChanged += onPanStateChanged;

	}

	void Update ()
	{

		if(panning)
		{
			//this.rigidbody.velocity = transform.forward * Vector3.Magnitude (transform.localPosition - targetPan);


			panFrac = panSpeed * Time.deltaTime;
        	transform.localPosition = Vector3.Lerp(transform.localPosition, targetPan, panFrac);
			panning = false;
		}
	}

	private void onPanStateChanged(object sender, GestureStateChangeEventArgs e)
    {
        switch (e.State)
        {
            case Gesture.GestureState.Began:
            case Gesture.GestureState.Changed:
                var target = sender as PanGesture;
                Debug.DrawRay(transform.position, target.WorldTransformPlane.normal);
                Debug.DrawRay(transform.position, target.WorldDeltaPosition.normalized);

                var local = new Vector3(transform.InverseTransformDirection(target.WorldDeltaPosition).x, transform.InverseTransformDirection(target.WorldDeltaPosition).y, transform.InverseTransformDirection(target.WorldDeltaPosition).z);
                targetPan += transform.InverseTransformDirection(transform.TransformDirection(local));
				panning = true;
                //if (transform.InverseTransformDirection(transform.parent.TransformDirection(targetPan - startPos)).y < 0) targetPan = startPos;
                break;
        }

    }

}



Обратите внимание, что в функции onPanStateChangedпеременная Vector3 localиспользует все три оси, тогда как в других моделях пользовательского интерфейса я использовал только оси x- и y-. Можно настроить нужным образом функциональность и других атрибутов, включая скорость прокрутки. При перемещении задней стенки для защиты сфер от выпускаемых башней капсул не так просто правильно разместить эту стенку. Нужно изменить переменную Vector3 localв отдельном сценарии, чтобы задняя стенка защищала сферы от попадания капсул из башни.

Касание

Далее для изменения физических характеристик я настроил жест касания. Я программно добавил этот жест к сферам во время их создания с помощью следующего кода:


targetSphere.AddComponent ("GenericTap");
targetSphere.AddComponent ("TapGesture");

Сценарий GenericTapвыполняет все модификации твердых тел в функции onTapи не использует функцию Update. Функция onTapувеличивает размер сферы в 2 раза при каждом ее касании пользователем. Я добавил это поведение, чтобы отслеживать сферы на сцене и удобнее наблюдать за их поведением. Каждый раз, когда пользователь касается сферы, ее физическая масса увеличивается в 10 раз. Результат виден на рис. 4: попадание выпущенных башней капсул не приводит к перемещению крупной сферы, которой пользователь коснулся 2 или 3 раза, тогда как другие сферы с легкостью перемещаются при попаданиях.


Рисунок 4. Попадание капсул не приводит к перемещению сферы с увеличенными размером и массой

Код сценария GenericTapвыглядит так:


using UnityEngine;
using System.Collections;
using TouchScript.Events;
using TouchScript.Gestures;


public class GenericTap: MonoBehaviour {

	private Vector3 startScale;

	void Start ()
	{

	startScale = transform.localScale;
	if (GetComponent<TapGesture>() != null) GetComponent<TapGesture>().StateChanged += onTap;


	}

	void Update ()
	{

	}

	private void onTap(object sender, GestureStateChangeEventArgs 	gestureStateChangeEventArgs)
    	{
        if (gestureStateChangeEventArgs.State == Gesture.GestureState.Recognized)
		{
            		transform.rigidbody.mass *= 10;
			transform.localScale *= 2.0f;
		}
	}

}



Этот сценарий прост: масса и размер сферы дискретно изменяются при выполнении жеста касания. В более сложной игровой среде жест касания может запускать последовательность событий, где масса и размер будут последовательно увеличиваться за определенное время и в зависимости от других элементов моделируемой сцены. Еще одно возможное улучшение состоит в использовании метода Time.deltaTimeдля настройки последовательности жестов для снижения массы и размера двойными касаниями.

Нажатие и отпускание

Затем я настраиваю жест «нажатие и отпускание», чтобы увеличить скорость движения созданных сфер в зависимости от времени между нажатием и отпусканием. Эта функциональность также добавляется программным образом во время создания:


			targetSphere.AddComponent ("PressGesture");
			targetSphere.AddComponent ("ReleaseGesture");
			targetSphere.AddComponent ("GenericPressRelease");

Я настраиваю сценарий GenericPressReleaseдля переключения двух логических переменных в функциях onPressи onRelease. Первая логическая переменная отслеживает, как изменилась скорость в последнем цикле жеста «нажатие и отпускание», чтобы в текущем цикле применить противоположное изменение. Вторая логическая переменная отслеживает, задействован ли сценарий в цикле жеста «нажатие и отпускание». Если да, то в зависимости от этого увеличивается или уменьшается скорость поступательного движения сферы. Для этого я использую параметр rigidbody.velocityсозданной сферы. Я использую переменную времени, чтобы регулировать величину изменения скорости поступательного движения. Результат таков: скорость движения сферы вперед увеличивается каждый нечетный раз, когда сфера получает жест «нажатие и отпускание», и уменьшается каждый четный раз при получении этого жеста. Код жеста «нажатие и отпускание» таков:


using UnityEngine;
using System.Collections;
using TouchScript.Events;
using TouchScript.Gestures;


public class GenericPressRelease : MonoBehaviour {

	private Vector3 startScale;
	private float velocityMult;
	private bool pressed;
	private bool currentlyIncreasing;
	private float timeSinceChanged;

	void Start ()
	{

	startScale = transform.localScale;
	velocityMult = 10.0f;
	pressed = false;
	currentlyIncreasing = true;
	timeSinceChanged = 0.0f;
	if (GetComponent<PressGesture>() != null) GetComponent<PressGesture>().StateChanged += onPress;
    if (GetComponent<ReleaseGesture>() != null) GetComponent<ReleaseGesture>().StateChanged += onRelease;

	}

	void Update ()
	{
		timeSinceChanged += Time.deltaTime;
		if(timeSinceChanged >= 0.25 && currentlyIncreasing && velocityMult <= 100 && pressed)
		{
			velocityMult += 10.0f;
			rigidbody.velocity = transform.forward * velocityMult;
			timeSinceChanged = 0.0f;
		}
		if(timeSinceChanged >= 0.25 && !currentlyIncreasing && velocityMult >= 0 && pressed)
		{
			velocityMult += -10.0f;
			rigidbody.velocity = transform.forward * velocityMult;
			timeSinceChanged = 0.0f;
		}

	}

	private void onPress(object sender, GestureStateChangeEventArgs gestureStateChangeEventArgs)
    {
        if (gestureStateChangeEventArgs.State == Gesture.GestureState.Recognized)
		{
			pressed = true;
		}
	}
	private void onRelease(object sender, GestureStateChangeEventArgs gestureStateChangeEventArgs)
    {
        if (gestureStateChangeEventArgs.State == Gesture.GestureState.Recognized)
		{
			pressed = false;
			currentlyIncreasing = !currentlyIncreasing;
		}
    }

}



Эта функциональность может быть полезной в играх со стрельбой, где может возрастать скорость снарядов, вследствие чего попадание будет иначе воздействовать на цели. Кроме того, в играх со стрельбой можно настроить эту функцию в качестве защитного механизма: нажатие или отпускание пользователем будет снижать скорость и ослаблять влияние попадания. Эту функцию можно использовать в играх в стиле Тетриса, чтобы при увеличении скорости движения фигур давать пользователю больше очков.

Другие физические свойства

Я использовал жесты, показанные в этой статье, для управления такими характеристиками ресурсов сцены Unity 3D, как расположение, размер, масса и скорость движения. Другие параметры твердых тел, которыми удобно управлять с помощью жестов, — угловая скорость, сопротивление движению и центр масс. Можно связать эти параметры твердых тел, управляемые с помощью жестов, с существующими параметрами, такими как цвет и текстура. Также есть возможность создавать собственные переменные для моделирования физики твердых тел. Пример — переменная hitDamage, которая увеличивается при каждом касании; при обнаружении попадания из объекта вычитается определенное количество «здоровья».

Заключение

IЯ создал и запустил пример физического моделирования с твердыми телами, приведенный в этой статье, с помощью Unity 3D под управлением Windows 8 на ультрабуке. Я настроил наибольшее время жизни выпускаемых башней снарядов и создаваемых сфер для этой платформы. В результате моделирование должным образом реагировало на запрограммированные сенсорные жесты. Время жизни актива — всего один из параметров, которые нужно учитывать при изменении физических характеристик. При этом приложение не должно давать пользователю возможности приведения физического моделирования в состояние, из-за которого снизится производительность и скорость реагирования всего приложения. Для этого проще всего ограничить минимальные и максимальные значения всех изменяемых физических характеристик. Если учитывать вопросы производительности, Windows 8 на ультрабуках является жизнеспособной платформой для разработки моделей Unity 3D с изменением характеристик ресурсов сцены при физическом моделировании.

Другие материалы:

Об авторе

Линн Томпсон — специалист в области ИТ, более 20 лет проработавший в области компьютеризации предпринимательской и производственной сфер. Одной из первых его работ стало использование САПР для создания и редактирования чертежей контрольных приборов для энергосистем. Тогда же он получил степень бакалавра электротехники в Университете Небраски (г. Линкольн). В эпоху бума доткомов Линн занимался системным администри­рованием операционных систем, баз данных и приложений на различных платформах в одном из ИТ-интеграторов. Позже, после «краха доткомов», он участвовал во множестве проектов в роли ИТ-консультанта. Линн работал с компаниями, работающими в сфере легкой промыш­ленности, а также в нефтегазовой и оборонной индустрии. Сейчас он вновь вернулся к своей специальности и работает инженером-энергетиком. Линн получил магистерскую степень инженера со специализацией в области управления техническими системами (также в Университете Небраски).

 

  • multi touch
  • Unity 3D
  • TouchScript
  • unity
  • 开发人员
  • Microsoft Windows* 8
  • Windows*
  • Unity
  • 中级
  • 游戏开发
  • 笔记本电脑
  • 平板电脑
  • URL
  • 主题专区: 

    IDZone

    Viewing all articles
    Browse latest Browse all 500

    Trending Articles



    <script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>