Как сделать сенсорное управление в unity
Перейти к содержимому

Как сделать сенсорное управление в unity

  • автор:

Мобильный джойстик сенсорного ввода в Unity

Чтобы сделать управляемого персонажа в мобильной игре, необходимо добавить кнопки, визуально представленные на экране и реагирующие на сенсорный ввод.

В этом уроке я покажу, как создать кнопку, похожую на джойстик, в формате Unity, которая в первую очередь подходит для управления движением на телефонах с сенсорным экраном.

Вы также можете использовать приведенный ниже пример, чтобы добавить больше кнопок и джойстиков. Итак, начнем!

Шаг 1. Создайте все необходимые сценарии

  • Создайте два сценария C#, используя исходный код ниже.

MobileJoystick_UI.cs

using UnityEngine; using UnityEngine.UI; public class MobileJoystick_UI : MonoBehaviour < //Mobile controller graphics public Sprite navigationCircle; public Sprite navigationButton; //Use this in your movement script for the input control public Vector2 moveDirection; //Joystick components size int circleSize = 120; int buttonSize = 100; //How far the joystick should be placed from the side of the screen int marginLeft = 100; //How far the joystick should be placed from the bottom of the screen int marginBottom = 100; Canvas mainCanvas; //Mobile movement [System.Serializable] public class JoystickButton < public Image backgroundCircle; public Image mainButton; public Rect defaultArea; public Vector2 touchOffset; public Vector2 currentTouchPos; public int touchID; public bool isActive = false; >//Move joystick data JoystickButton moveTouch = new JoystickButton(); public static MobileJoystick_UI instance; // Start is called before the first frame update void Start() < if (instance != null) < //There is another instance already present, remove this one Destroy(gameObject); return; >//Assign this instance to a static variable so you can access the movement direction directly at MobileJoystick_UI.instance.moveDirection instance = this; //This function will initialize canvas element along with the joystick button GameObject tmpObj = new GameObject("Canvas"); tmpObj.transform.position = Vector3.zero; mainCanvas = tmpObj.AddComponent(); mainCanvas.renderMode = RenderMode.ScreenSpaceOverlay; mainCanvas.pixelPerfect = true; //Add Canvas Scaler component CanvasScaler canvasScaled = tmpObj.AddComponent(); canvasScaled.scaleFactor = 1; canvasScaled.referencePixelsPerUnit = 100; //Add Graphic Raycaster element tmpObj.AddComponent(); //Setup navigation background GameObject cntrlTmpObj = new GameObject("Movement Circle"); cntrlTmpObj.transform.position = Vector3.zero; cntrlTmpObj.transform.parent = tmpObj.transform; moveTouch.backgroundCircle = cntrlTmpObj.AddComponent(); moveTouch.backgroundCircle.sprite = navigationCircle; moveTouch.backgroundCircle.rectTransform.anchorMin = new Vector2(0, 0); moveTouch.backgroundCircle.rectTransform.anchorMax = new Vector2(0, 0); moveTouch.backgroundCircle.rectTransform.sizeDelta = new Vector2(circleSize, circleSize); moveTouch.backgroundCircle.rectTransform.pivot = new Vector2(0, 0); moveTouch.backgroundCircle.rectTransform.position = new Vector3(marginLeft, marginBottom, 0); //Navigation button cntrlTmpObj = new GameObject("Movement Button"); cntrlTmpObj.transform.position = Vector3.zero; cntrlTmpObj.transform.parent = tmpObj.transform; moveTouch.mainButton = cntrlTmpObj.AddComponent(); moveTouch.mainButton.sprite = navigationButton; moveTouch.mainButton.rectTransform.anchorMin = new Vector2(0, 0); moveTouch.mainButton.rectTransform.anchorMax = new Vector2(0, 0); moveTouch.mainButton.rectTransform.sizeDelta = new Vector2(buttonSize, buttonSize); moveTouch.mainButton.rectTransform.pivot = new Vector2(0, 0); moveTouch.mainButton.rectTransform.position = new Vector3(marginLeft + (circleSize - buttonSize) / 2, marginBottom + (circleSize - buttonSize) / 2, 0); //Save the default location of the joystick button to be used later for input detection moveTouch.defaultArea = new Rect(moveTouch.mainButton.rectTransform.position.x, moveTouch.mainButton.rectTransform.position.y, moveTouch.mainButton.rectTransform.sizeDelta.x, moveTouch.mainButton.rectTransform.sizeDelta.y); > // Update is called once per frame void Update() < //Handle joystick movement #if (UNITY_ANDROID || UNITY_IOS || UNITY_WP8 || UNITY_WP8_1) && !UNITY_EDITOR //Mobile touch input for (var i = 0; i < Input.touchCount; ++i) < Touch touch = Input.GetTouch(i); if (touch.phase == TouchPhase.Began) < MobileButtonsCheck(new Vector2(touch.position.x, Screen.height - touch.position.y), touch.fingerId); >if (touch.phase == TouchPhase.Moved ) < if(moveTouch.isActive && moveTouch.touchID == touch.fingerId) < moveTouch.currentTouchPos = touch.position; >> if (touch.phase == TouchPhase.Ended || touch.phase == TouchPhase.Canceled) < MobileButtonStop(touch.fingerId); >> #else //Desktop mouse input for editor testing if (Input.GetMouseButtonDown(0)) < MobileButtonsCheck(new Vector2(Input.mousePosition.x, Screen.height - Input.mousePosition.y), -1); >if (Input.GetMouseButtonUp(0)) < MobileButtonStop(-1); >moveTouch.currentTouchPos = Input.mousePosition; #endif //Moving if (moveTouch.isActive) < moveTouch.mainButton.rectTransform.position = new Vector3(moveTouch.currentTouchPos.x - moveTouch.touchOffset.x, moveTouch.currentTouchPos.y - moveTouch.touchOffset.y); moveDirection.x = moveTouch.mainButton.rectTransform.position.x - moveTouch.defaultArea.x; moveDirection.y = moveTouch.mainButton.rectTransform.position.y - moveTouch.defaultArea.y; if (Mathf.Abs(moveDirection.x) < 19) < moveDirection.x = 0; >else < moveDirection.x = Mathf.Clamp(moveDirection.x / 75.000f, -1.000f, 1.000f); >if (Mathf.Abs(moveDirection.y) < 19) < moveDirection.y = 0; >else < moveDirection.y = Mathf.Clamp(moveDirection.y / 75.000f, -1.000f, 1.000f); >> else < moveTouch.mainButton.rectTransform.position = new Vector3(moveTouch.defaultArea.x, moveTouch.defaultArea.y); moveDirection = Vector2.zero; >> //Here we check if the clicked/tapped position is inside the joystick button void MobileButtonsCheck(Vector2 touchPos, int touchID) < //Move controller if (moveTouch.defaultArea.Contains(new Vector2(touchPos.x, Screen.height - touchPos.y)) && !moveTouch.isActive) < moveTouch.isActive = true; moveTouch.touchOffset = new Vector2(touchPos.x - moveTouch.defaultArea.x, Screen.height - touchPos.y - moveTouch.defaultArea.y); moveTouch.currentTouchPos = new Vector2(touchPos.x, Screen.height - touchPos.y); moveTouch.touchID = touchID; >> //Here we release the previously active joystick if we release the mouse button/finger from the screen void MobileButtonStop(int touchID) < if (moveTouch.isActive && moveTouch.touchID == touchID) < moveTouch.isActive = false; moveTouch.touchOffset = Vector2.zero; moveTouch.touchID = -1; >> >

TouchPlayerController.cs

using UnityEngine; public class TouchPlayerController : MonoBehaviour < // Update is called once per frame void Update() < //Move Front/Back if (MobileJoystick_UI.instance.moveDirection.y != 0) < transform.Translate(transform.forward * Time.deltaTime * 2.45f * MobileJoystick_UI.instance.moveDirection.y, Space.World); >//Rotate Left/Right if (MobileJoystick_UI.instance.moveDirection.x != 0) < transform.Rotate(new Vector3(0, 14, 0) * Time.deltaTime * 4.5f * MobileJoystick_UI.instance.moveDirection.x, Space.Self); >> >

Шаг 2. Создайте простую сцену, используя приведенные выше сценарии.

  • Создать новую сцену
  • Создайте новый GameObject и назовите его ‘_TouchInput’
  • Прикрепите к нему скрипт MobileJoystick_UI
  • Назначьте переменные ‘Navigation Circle’ и ‘Navigation button’.

Вы можете использовать спрайты ниже или нажмите здесь:

  • После импорта их в Unity обязательно измените тип текстуры на ‘Sprite (2D and UI)’

Шаг 3. Настройка экземпляра проигрывателя

Наконец, мы настраиваем экземпляр игрока (в моем случае это будет простой GameObject с цилиндром внутри):

  • Создайте новый GameObject и назовите его. ‘MobilePlayer’
  • Прикрепите к нему скрипт TouchPlayerController.
  • Создайте новый цилиндр и уменьшите его высоту, пока он не станет почти плоским (в моем случае масштаб равен (x: 1 y: 0,0142 z: 1) )
  • Переместите цилиндр внутри игрового объекта ‘MobilePlayer’.
  • В целях тестирования вы также можете переместить основную камеру внутрь ‘MobilePlayer’ и повернуть ее так, чтобы она была направлена ​​на игрока, вот так:

Теперь пришло время нажать Play и посмотреть, все ли работает.

Sharp Coder Видео проигрыватель

Все работает так, как ожидалось! Управление плеером осуществляется перемещением кнопки-джойстика.

Скрипт MobileJoystick_UI поддерживает как мобильный сенсорный ввод, так и щелчок мышью (если вы играете в редакторе).

Unity Как создать мобильное сенсорное управление

Элементы управления — одна из самых важных частей видеоигры, и неудивительно, что именно они позволяют игрокам взаимодействовать с игровым миром.

Элементы управления игрой — это сигналы, которые передаются посредством взаимодействия с оборудованием (мышь/клавиатура, контроллер, сенсорный экран и т. д.), которые затем обрабатываются игровым кодом, применяя определенные действия.

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

Мобильные элементы управления Unity

В этом уроке я покажу, как создать полнофункциональные мобильные элементы управления (джойстики и кнопки) в Unity с использованием UI Canvas.

Шаг 1. Создайте все необходимые сценарии

В этом руководстве представлены два сценария: SC_ClickTracker.cs и SC_MobileControls.cs. Первый скрипт будет прослушивать события щелчка, а второй скрипт будет считывать значения, сгенерированные из этих событий.

SC_ClickTracker.cs

using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; #if UNITY_EDITOR using UnityEditor; #endif public class SC_ClickTracker : MonoBehaviour, IPointerDownHandler, IDragHandler, IPointerUpHandler < public string buttonName = ""; //This should be an unique name of the button public bool isJoystick = false; public float movementLimit = 1; //How far the joystick can be moved (n x Joystick Width) public float movementThreshold = 0.1f; //Minimum distance (n x Joystick Width) that the Joystick need to be moved to trigger inputAxis (Must be less than movementLimit) //Reference variables RectTransform rt; Vector3 startPos; Vector2 clickPos; //Input variables Vector2 inputAxis = Vector2.zero; bool holding = false; bool clicked = false; void Start() < //Add this button to the list SC_MobileControls.instance.AddButton(this); rt = GetComponent(); startPos = rt.anchoredPosition3D; > //Do this when the mouse is clicked over the selectable object this script is attached to. public void OnPointerDown(PointerEventData eventData) < //Debug.Log(this.gameObject.name + " Was Clicked."); holding = true; if (!isJoystick) < clicked = true; StartCoroutine(StopClickEvent()); >else < //Initialize Joystick movement clickPos = eventData.pressPosition; >> WaitForEndOfFrame waitForEndOfFrame = new WaitForEndOfFrame(); //Wait for next update then release the click event IEnumerator StopClickEvent() < yield return waitForEndOfFrame; clicked = false; >//Joystick movement public void OnDrag(PointerEventData eventData) < //Debug.Log(this.gameObject.name + " The element is being dragged"); if (isJoystick) < Vector3 movementVector = Vector3.ClampMagnitude((eventData.position - clickPos) / SC_MobileControls.instance.canvas.scaleFactor, (rt.sizeDelta.x * movementLimit) + (rt.sizeDelta.x * movementThreshold)); Vector3 movePos = startPos + movementVector; rt.anchoredPosition = movePos; //Update inputAxis float inputX = 0; float inputY = 0; if (Mathf.Abs(movementVector.x) >rt.sizeDelta.x * movementThreshold) < inputX = (movementVector.x - (rt.sizeDelta.x * movementThreshold * (movementVector.x >0 ? 1 : -1))) / (rt.sizeDelta.x * movementLimit); > if (Mathf.Abs(movementVector.y) > rt.sizeDelta.x * movementThreshold) < inputY = (movementVector.y - (rt.sizeDelta.x * movementThreshold * (movementVector.y >0 ? 1 : -1))) / (rt.sizeDelta.x * movementLimit); > inputAxis = new Vector2(inputX, inputY); > > //Do this when the mouse click on this selectable UI object is released. public void OnPointerUp(PointerEventData eventData) < //Debug.Log(this.gameObject.name + " The mouse click was released"); holding = false; if (isJoystick) < //Reset Joystick position rt.anchoredPosition = startPos; inputAxis = Vector2.zero; >> public Vector2 GetInputAxis() < return inputAxis; >public bool GetClickedStatus() < return clicked; >public bool GetHoldStatus() < return holding; >> #if UNITY_EDITOR //Custom Editor [CustomEditor(typeof(SC_ClickTracker))] public class SC_ClickTracker_Editor : Editor < public override void OnInspectorGUI() < SC_ClickTracker script = (SC_ClickTracker)target; script.buttonName = EditorGUILayout.TextField("Button Name", script.buttonName); script.isJoystick = EditorGUILayout.Toggle("Is Joystick", script.isJoystick); if (script.isJoystick) < script.movementLimit = EditorGUILayout.FloatField("Movement Limit", script.movementLimit); script.movementThreshold = EditorGUILayout.FloatField("Movement Threshold", script.movementThreshold); >> > #endif

SC_MobileControls.cs

using System.Collections; using System.Collections.Generic; using UnityEngine; public class SC_MobileControls : MonoBehaviour < [HideInInspector] public Canvas canvas; Listbuttons = new List(); public static SC_MobileControls instance; void Awake() < //Assign this script to static variable, so it can be accessed from other scripts. Make sure there is only one SC_MobileControls in the Scene. instance = this; canvas = GetComponent(); > public int AddButton(SC_ClickTracker button) < buttons.Add(button); return buttons.Count - 1; >public Vector2 GetJoystick(string joystickName) < for(int i = 0; i < buttons.Count; i++) < if(buttons[i].buttonName == joystickName) < return buttons[i].GetInputAxis(); >> Debug.LogError("Joystick with a name '" + joystickName + "' not found. Make sure SC_ClickTracker is assigned to the button and the name is matching."); return Vector2.zero; > public bool GetMobileButton(string buttonName) < for (int i = 0; i < buttons.Count; i++) < if (buttons[i].buttonName == buttonName) < return buttons[i].GetHoldStatus(); >> Debug.LogError("Button with a name '" + buttonName + "' not found. Make sure SC_ClickTracker is assigned to the button and the name is matching."); return false; > public bool GetMobileButtonDown(string buttonName) < for (int i = 0; i < buttons.Count; i++) < if (buttons[i].buttonName == buttonName) < return buttons[i].GetClickedStatus(); >> Debug.LogError("Button with a name '" + buttonName + "' not found. Make sure SC_ClickTracker is assigned to the button and the name is matching."); return false; > >

Шаг 2. Настройте мобильные элементы управления

  • Создайте новый холст (GameObject -> UI -> Canvas).
  • Измените ‘UI Scale Mode’ в Canvas Scaler на ‘Scale With Screen Size’ и измените эталонное разрешение на то, с которым вы работаете (в моем случае это 1000 x 600).
  • Прикрепите скрипт SC_MobileControls к объекту Canvas.
  • Щелкните правой кнопкой мыши объект Canvas -> Пользовательский интерфейс -> Изображение.
  • Переименуйте вновь созданное изображение в «JoystickLeft»
  • Измените спрайт «JoystickLeft» на пустой круг (не забудьте изменить тип текстуры на ‘Sprite (2D and UI)’ после импорта в Unity)

  • Установите «JoystickLeft» значения Rect Transform, такие же, как на скриншот ниже:

  • В компоненте «Изображение» установите для параметра «Цвет альфа» значение 0,5, чтобы сделать спрайт слегка прозрачным:

  • Дублируйте объект «JoystickLeft» и переименуйте его в «JoystickLeftButton»
  • Переместите «JoystickLeftButton» внутрь объекта «JoystickLeft».
  • Измените спрайт «JoystickLeftButton» на закрашенный круг:

  • Установите «JoystickLeftButton» значения Rect Transform, такие же, как на скриншоте ниже:

  • Добавьте компонент Button в «JoystickLeftButton»
  • В компоненте «Кнопка» измените «Переход» на ‘None’
  • Прикрепите скрипт SC_ClickTracker к «JoystickLeftButton»
  • В SC_ClickTracker задайте для имени кнопки любое уникальное имя (в моем случае я установил его ‘JoystickLeft’) и включите флажок ‘Is Joystick’.

Кнопка-джойстик готова. Вы можете иметь любое количество джойстиков (в моем случае их будет 2: один слева для управления движением и один справа для управления вращением).

  • Дублируйте «JoystickLeft» и переименуйте его в «JoystickRight»
  • Разверните «JoystickRight» и переименуйте «JoystickLeftButton» в «JoystickRightButton»
  • Установите «JoystickRight» значения Rect Transform, такие же, как на скриншоте ниже:

  • Выберите объект «JoystickRightButton» и в SC_ClickTracker измените имя кнопки на ‘JoystickRight’

Второй джойстик готов.

Теперь создадим обычную кнопку:

  • Щелкните правой кнопкой мыши объект Canvas -> Пользовательский интерфейс -> Кнопка.
  • Переименуйте объект кнопки в «SprintButton»
  • Измените спрайт «SprintButton» на круг с эффектом скоса:

  • Установите «SprintButton» значения Rect Transform, как на скриншоте ниже:

  • Измените альфу цвета изображения «SprintButton» на 0,5.
  • Прикрепите скрипт SC_ClickTracker к объекту «SprintButton».
  • В SC_ClickTracker измените имя кнопки на ‘Sprinting’
  • Выберите текстовый объект внутри «SprintButton» и измените его текст на ‘Sprint’, а также измените размер шрифта на ‘Bold’

Кнопка Unity для мобильных устройств

Кнопка готова.

Мы собираемся создать еще одну кнопку под названием «Jump»:

  • Дублируйте объект «SprintButton» и переименуйте его в «JumpButton»
  • Измените значение «JumpButton» Pos Y на 250.
  • В SC_ClickTracker измените имя кнопки на ‘Jumping’
  • Измените текст внутри «JumpButton» на ‘Jump’

И последняя кнопка — «Action»:

  • Дублируйте объект «JumpButton» и переименуйте его в «ActionButton»
  • Измените значение «ActionButton» Pos X на -185.
  • В SC_ClickTracker измените Имя кнопки на ‘Action’
  • Измените текст внутри «ActionButton» на ‘Action’

Шаг 3. Внедрите мобильные элементы управления

Если вы выполнили описанные выше шаги, теперь вы можете использовать эти функции для реализации мобильных элементов управления в своем скрипте:

if(SC_MobileControls.instance.GetMobileButtonDown("BUTTON_NAME")) < //Mobile button has been pressed one time, equivalent to if(Input.GetKeyDown(KeyCode. )) >if(SC_MobileControls.instance.GetMobileButton("BUTTON_NAME")) < //Mobile button is being held pressed, equivalent to if(Input.GetKey(KeyCode. )) >//Get normalized direction of a on-screen Joystick //Could be compared to: new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical")) or new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y")) Vector2 inputAxis = SC_MobileControls.instance.GetJoystick("JOYSTICK_NAME");

В качестве примера я буду реализовывать мобильные элементы управления с помощью контроллера FPS из этого руководства. Сначала следуйте этому руководству, оно довольно простое.

Если вы следовали этому руководству, теперь у вас будет объект «FPSPlayer» вместе с Canvas с мобильными элементами управления.

Мы сохраним элементы управления рабочего стола, а также реализуем мобильные элементы управления, что сделает их кроссплатформенными:

  • Откройте скрипт SC_FPSController, прокрутите до строки 28 и удалите эту часть (удаление этой части предотвратит блокировку курсора и позволит нажимать на мобильные элементы управления в редакторе):
 // Lock cursor Cursor.lockState = CursorLockMode.Locked; Cursor.visible = false;
  • Прокрутите до строки 39 и замените:
 bool isRunning = Input.GetKey(KeyCode.LeftShift); float curSpeedX = canMove ? (isRunning ? runningSpeed : walkingSpeed) * Input.GetAxis("Vertical") : 0; float curSpeedY = canMove ? (isRunning ? runningSpeed : walkingSpeed) * Input.GetAxis("Horizontal") : 0;
 bool isRunning = Input.GetKey(KeyCode.LeftShift) || SC_MobileControls.instance.GetMobileButton("Sprinting"); float curSpeedX = canMove ? (isRunning ? runningSpeed : walkingSpeed) * (Input.GetAxis("Vertical") + SC_MobileControls.instance.GetJoystick("JoystickLeft").y) : 0; float curSpeedY = canMove ? (isRunning ? runningSpeed : walkingSpeed) * (Input.GetAxis("Horizontal") + SC_MobileControls.instance.GetJoystick("JoystickLeft").x) : 0;
  • Прокрутите вниз до строки 45 и замените:
 if (Input.GetButton("Jump") && canMove && characterController.isGrounded)
 if ((Input.GetButton("Jump") || SC_MobileControls.instance.GetMobileButtonDown("Jumping")) && canMove && characterController.isGrounded)
  • Прокрутите вниз до строки 68 и замените:
 rotationX += -Input.GetAxis("Mouse Y") * lookSpeed; rotationX = Mathf.Clamp(rotationX, -lookXLimit, lookXLimit); playerCamera.transform.localRotation = Quaternion.Euler(rotationX, 0, 0); transform.rotation *= Quaternion.Euler(0, Input.GetAxis("Mouse X") * lookSpeed, 0);
#if UNITY_IPHONE || UNITY_ANDROID || UNITY_EDITOR rotationX += -(SC_MobileControls.instance.GetJoystick("JoystickRight").y) * lookSpeed; #else rotationX += -Input.GetAxis("Mouse Y") * lookSpeed; #endif rotationX = Mathf.Clamp(rotationX, -lookXLimit, lookXLimit); playerCamera.transform.localRotation = Quaternion.Euler(rotationX, 0, 0); #if UNITY_IPHONE || UNITY_ANDROID || UNITY_EDITOR transform.rotation *= Quaternion.Euler(0, SC_MobileControls.instance.GetJoystick("JoystickRight").x * lookSpeed, 0); #else transform.rotation *= Quaternion.Euler(0, Input.GetAxis("Mouse X") * lookSpeed, 0); #endif

Поскольку движение взгляда будет мешать тестированию джойстика в редакторе, мы используем #if для компиляции для конкретной платформы, чтобы отделить мобильную логику от остальных платформ.

Мобильный контроллер FPS готов, давайте его проверим:

Sharp Coder Видео проигрыватель

Как видите, все джойстики и кнопки работоспособны (кроме кнопки «Action», которая не была реализована из-за отсутствия для нее подходящей функции).

Программирование в Unity для опытных программистов

В Unity скрипты можно использовать для разработки практически любого элемента игры или интерактивного контента с графикой реального времени. Unity поддерживает скрипты на C#, созданные в соответствии с одним из двух основных подходов: традиционным и широко использующимся объектно-ориентированным подходом и информационно-ориентированным подходом, который теперь тоже поддерживается в Unity в отдельных случаях благодаря нашему высокопроизводительному многопоточному стеку информационно-ориентированных технологий (DOTS).

На этой странице

  • Если у вас есть опыт программирования на C++
  • Объекты GameObject и компоненты
  • Программирование компонентов в Unity
  • Преимущества информационно-ориентированного подхода
  • Современное оборудование
  • Отладка в Unity
  • Системы программирования в Unity
  • Настройка редактора Unity

Знакомитесь с Unity, имея знания C++?

Unity поддерживает C#, стандартный в отрасли язык программирования, в некоторой степени похожий на Java или C++.

По сравнению с C++, C# легче в изучении. Кроме того, он относится к категории языков «с управлением памятью», то есть он автоматически распределяет память, устраняет утечки и так далее.

Как правило C# удобнее C++, если вам нужно в первую очередь разработать игру, а потом уже работать над различными сложными аспектами программирования.

Объекты GameObject и компоненты в Unity

Вся интерактивность и игровой процесс в Unity строятся на основе трех фундаментальных блоков: объекты GameObject, компоненты и переменные.

Любой объект в игре является GameObject, будь то персонажи, источники света, спецэффекты, декорации и все остальное.

Компоненты
Игровые объекты сами по себе не имеют никакого поведения. Для того, чтобы объект начал работать, игровому объекту нужны различные атрибуты, добавляемые с помощью компонентов.

Компоненты (Component) определяют поведение игровых объектов, к которым они прикреплены, и управляют ими. Простой пример — создание источника света, включающее прикрепление компонента Light к GameObject (см. ниже). Таким же примером может быть добавление компонента Rigidbody к объекту, чтобы он мог падать.

Компоненты имеют ряд свойств или переменных, которые можно настроить в окне Inspector редактора Unity и/или с помощью скрипта. В примере выше к свойствам источника света относятся дальность, цвет и интенсивность.

Программирование компонентов в Unity

В Unity есть множество самых разнообразных компонентов, но вы вскоре можете столкнуться с необходимостью создать собственный компонент для реализации своих алгоритмов. Это можно сделать с помощью скриптов, в которых описана ваша собственная игровая логика и поведение объектов, и которые затем прикрепляются к игровым объектам как компоненты. Каждый скрипт связывается с внутренними механизмами Unity путем реализации класса, производного от встроенного класса MonoBehaviour.

Компоненты на основе скриптов позволяют запускать игровые события, проверять объект на предмет столкновений, применять физические свойства, программировать реакцию на управление пользователя и многое другое. См. Unity Scripting API для дополнительной информации.

Демофильм Unity Megacity создан на основе DOTS

Преимущества информационно-ориентированного подхода с DOTS

Традиционная модель «игровой объект — компонент» хорошо работает и сегодня, поскольку она проста как для программистов, так и других пользователей, а также удобна для создания интуитивных интерфейсов. Добавите компонент Rigidbody к объекту GameObject — он начнет падать, добавите компонент Light — GameObject начнет излучать свет. Все остальное также подчиняется этой простой логике.

При этом система компонентов создана на основе объектно-ориентированной платформы, что создает сложности для разработчиков при работе с кэшем и памятью развивающегося оборудования.

Компоненты и игровые объекты относятся к «тяжелым объектам C++». Все объекты GameObject имеют имя. Их компоненты представляют собой оболочки для C# поверх компонентов на C++. Это упрощает работу с ними, но может влиять на производительность, если они будут храниться в памяти без явной структуры. Объект C# может находиться на любом участке памяти. Объект C++ также может находиться в любом участке памяти. Группировка и последовательное размещение объектов в памяти отсутствуют. При каждой загрузке в центральный процессор для обработки объект приходится собирать по частям из разных участков памяти. Это может сильно замедлить загрузку, а оптимизация потребует много усилий.

Для решения этих проблем мы начали перерабатывать базовые системы Unity на основе высокопроизводительного, многопоточного стека информационно-ориентированных технологий или DOTS (в настоящее время в статусе предварительной версии).

DOTS позволяет вашей игре эффективно использовать все возможности новейших многоядерных процессоров. Стек состоит из следующих компонентов:

  • система задач C# для эффективного исполнения кода на многопоточных системах;
  • Entity Component System (ECS) для разработки высокопроизводительного кода по умолчанию;
  • компилятор Burst для компиляции скриптов в оптимизированный нативный код.

ECS — это новая система компонентов в составе DOTS; все традиционные объектно-ориентированные манипуляции над GameObject отражаются на экземпляре в новой системе. Название «Компонент» никак не изменилось. Важнейшее отличие — в структуре данных. Подробнее об этом можно узнать из статьи «О DOTS: Entity Component System».

Демофильм Unity Megacity создан на основе DOTS

Используйте все возможности современного оборудования

Помимо того, что это улучшенный подход к написанию кода игры с точки зрения дизайна, ECS позволяет вам использовать систему задач C# Unity и компилятор Burst и тем самым полностью использовать преимущества современного оборудования.

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

Некоторые из технологий DOTS все еще находятся в статусе предварительной версии, поэтому мы советуем разработчикам использовать стек для решения отдельных вопросов производительности проекта, не строить на базе DOTS весь проект. См. раздел «Дополнительные ресурсы» в конце этой страницы, где указаны ссылки на ключевые ресурсы DOTS.

Unity Profiler для оптимизации производительности

Отладка в Unity

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

Вот несколько полезных ресурсов по оптимизации в Unity:

Наилучшие методики для общих случаев (включая подробные советы по оптимизации системы интерфейса Unity)

Сенсорное управление игроком в unity

я начинающий разработчик игр, поэтому постоянно сталкиваюсь с проблемами, которые решаю, но вот с этой у меня загвоздка. В моей игре на андроид нужно двигать главный игровой объект пальцем, не отрывая его, только вправо или влево. То есть представьте, что есть какая-то полоса препятствий, и объекту надо её преодолеть, вот мне и надо чтобы, если палец влево, то он тоже влево, и наоборот. Я знаю про touch, но вот как согласовать передвижение, мне не понятно. Заранее спасибо!(желательно, чтобы работало на всём экране, как я понимаю глобальный тач)

Отслеживать
задан 8 апр 2021 в 12:30
Миша Тощенко Миша Тощенко
3 1 1 бронзовый знак

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

Вот равномерное передвижение за пальцем (без поворота)

 if (Input.touchCount > 0)

в moveSpeed загрузить скорость «1f»

Отслеживать
ответ дан 8 апр 2021 в 12:37
73 1 1 серебряный знак 8 8 бронзовых знаков

  • c#
  • unity3d
  • разработка-игр
    Важное на Мете
Похожие

Подписаться на ленту

Лента вопроса

Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.

Дизайн сайта / логотип © 2024 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2024.4.30.8420

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *