Passen Sie die Bildschirmsteuerung an, um das Steuerkreuz zu implementieren

Diese Seite wurde aktualisiert :
Erstellungsdatum der Seite :

Verifizierungsumgebung

Fenster
  • Windows 11
Unity-Editor
  • 2020.3.25f1
Eingabesystem-Paket
  • 1.2.0

Voraussetzungen für diesen Tipp

Die folgenden Einstellungen wurden im Vorfeld als Prämisse für die Beschreibung dieses Tipps vorgenommen.

Sie sollten auch mit den folgenden Tipps vertraut sein:

Der On-Screen Control Stick ist die Standardausrichtung

Der On-Screen-Stick ist als virtueller Stick implementiert und repliziert die Funktionsweise eines Sticks, ähnlich der eines physischen Controllers. Wenn Sie ihn beispielsweise nach rechts verschieben möchten, können Sie zuerst den Bildschirm berühren, um den Stick zu berühren, und ihn dann nach rechts schieben, um den Stick nach unten zu drücken.

Es ist leicht als Stick-Operation vorzustellen, aber im Gegenteil, wenn Sie es sofort nach rechts bewegen möchten, (1) berühren, (2) nach rechts schieben, Da ein zweistufiger Vorgang erforderlich ist, verzögert sich die Reaktion zwangsläufig ein wenig. Dies gilt insbesondere, wenn Sie einen schnellen Richtungswechsel hintereinander vornehmen müssen.

Steuerkreuz, das die Richtung im Moment der Berührung bestimmt (nicht standardmäßig)

Die beste Eingabemethode für die schnelle Richtungseingabe ist eine, die die Richtung im Moment der Berührung bestimmen kann, indem sie etwas wie ein Steuerkreuz oder eine Pfeiltaste platziert. Es ist nicht von Unity, aber in meinem Spiel Little Saber platziere ich die Pfeiltasten so, dass Sie sich schnell in die Richtung bewegen können, die Sie berühren. Natürlich können Sie auch beim Berühren nach oben oder links schieben, um die Bewegungen zu wechseln.

Der On-Screen-Control-Standard ist jedoch nicht einfach zu platzieren und zu implementieren, da es nur On-Screen-Sticks und On-Screen-Buttons gibt.

Sie können auch ein Pseudo-D-Pad erstellen, indem Sie vier Tasten anordnen, wie in der Abbildung unten gezeigt, aber es ist unpraktisch, weil Sie nicht diagonal eingeben können. Wenn Sie 8 Tasten platzieren, ist eine diagonale Bedienung möglich, eine Fließrichtungsbedienung wie z.B. "← ↙ ↓" ist jedoch weiterhin nicht möglich.

Erstellen Sie ein Steuerkreuz mit der Anpassung der Bildschirmsteuerung

Wie Sie sehen können, wird die On-Screen-Steuerung standardmäßig nur mit Stick und Button geliefert, aber Sie können die fehlenden Funktionen mit Ihren eigenen Skripten anpassen. Hier möchte ich also ein Steuerkreuz mit On-Screen-Control-Anpassung erstellen.

Aktions-Karte

Wir werden die Aktionskarte verwenden, aber wir werden die in den vorherigen Tipps erstellte so verwenden, wie sie ist, sodass das Verfahren weggelassen wird.

Sie haben auch Code geschrieben.

Positionieren von Objekten

Platzieren Sie einen Textbereich, in dem Ihre Eingabe angezeigt wird, und eine Schaltfläche, die das Steuerkreuz ersetzt. In diesem Fall sind die Schaltflächen angeordnet, aber Sie können sie durch ein Bild ersetzen, das leichter zu verstehen ist.

Skript zum Anzeigen von Eingaben

Da die Bildschirmsteuerung die Berührung durch die physische Controller-Interaktion ersetzt, Erstellen Sie ein Skript, das Ihre Eingaben im Text anzeigt, während die Aktionskarte funktioniert.

Der Inhalt ist derselbe wie zuvor, daher lasse ich die Erklärung weg.

using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;

public class InputActionScript : MonoBehaviour
{
  /// <summary>情報を表示させるテキストオブジェクト。</summary>
  [SerializeField] private Text TextObject;

  /// <summary>アクションマップから自動生成されたクラス。</summary>
  private InputActionSample _actionMap;

  private void Awake()
  {
    // 各操作を行ったときに呼ばれるイベントを設定する
    _actionMap = new InputActionSample();
    _actionMap.Action2D.Move.performed += context => OnMove(context);
    _actionMap.Action2D.Attack.performed += context => OnAttack(context);
    _actionMap.Action2D.Move.canceled += context => OnMove(context);
    _actionMap.Action2D.Attack.canceled += context => OnAttack(context);
  }

  private void OnEnable()
  {
    // このオブジェクトが有効になったときにアクションマップを有効にする
    _actionMap.Enable();
  }

  private void OnDisable()
  {
    // このオブジェクトが無効になったときにアクションマップが余計な動作を起こさないように無効にする
    _actionMap.Disable();
  }

  /// <summary>
  /// Move 操作をした時に呼ばれるメソッドです。
  /// </summary>
  /// <param name="context">コールバックパラメータ。</param>
  public void OnMove(InputAction.CallbackContext context)
  {
    // Move の入力量を取得
    var vec = context.ReadValue<Vector2>();
    TextObject.text = $"Move:({vec.x:f2}, {vec.y:f2})\n{TextObject.text}";
  }

  /// <summary>
  /// Attack 操作をした時に呼ばれるメソッドです。
  /// </summary>
  /// <param name="context">コールバックパラメータ。</param>
  public void OnAttack(InputAction.CallbackContext context)
  {
    // Attack ボタンの状態を取得
    var value = context.ReadValueAsButton();
    TextObject.text = $"Attack:{value}\n{TextObject.text}";
  }
}

Überprüfen Sie nach dem Einrichten zunächst, ob es mit Ihrer Tastatur oder Ihrem Gamepad funktioniert.

Anpassen von Steuerelementen auf dem Bildschirm

Das bringt uns zum Hauptthema dieser Tipps. Das Anpassen der Bildschirmsteuerung ist ein Skript, erstellen Sie also zuerst ein Skript. Der Name ist willkürlich, aber in diesem Fall OnScreenDpad ist es .

Das Skript sieht wie folgt aus:

using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem.Layouts;
using UnityEngine.InputSystem.OnScreen;

public class OnScreenDpad
  : OnScreenControl, IPointerDownHandler, IPointerUpHandler, IDragHandler, IInitializePotentialDragHandler
{
  [InputControl(layout = "Vector2")]
  [SerializeField]
  private string _controlPath;
  /// <summary><see cref="OnScreenControl"/> で定義された値。</summary>
  protected override string controlPathInternal { get => _controlPath; set => _controlPath = value; }

  /// <summary>オブジェクトの位置。</summary>
  private Vector2 _objectPosition;

  /// <summary>オブジェクトのサイズの半分 (スケールも含む)。</summary>
  private Vector2 _objectSizeHalf;


  /// <summary>
  /// オブジェクトが動作する最初のタイミングで1回だけ呼ばれます。
  /// </summary>
  private void Start()
  {
    var rectTransform = (RectTransform)base.transform;

    // オブジェクトの位置を取得
    _objectPosition = rectTransform.anchoredPosition;

    // オブジェクトのサイズの半分を取得 (スケールサイズも考慮)
    _objectSizeHalf = rectTransform.sizeDelta * rectTransform.localScale / 2f;
  }

  /// <summary>ドラッグの初期化処理として呼ばれます。</summary>
  /// <param name="eventData">タッチ情報。</param>
  public void OnInitializePotentialDrag(PointerEventData eventData)
  {
    // タッチのスライド操作を即座に発生させたいのでドラッグ開始までの閾値を無効にします
    eventData.useDragThreshold = false;
  }

  /// <summary>タッチしたタイミングで呼ばれます。</summary>
  /// <param name="eventData">タッチ情報。</param>
  public void OnPointerDown(PointerEventData eventData)
  {
    Operate(eventData);
  }

  /// <summary>タッチした後ドラッグするたびに呼ばれます。</summary>
  /// <param name="eventData">タッチ情報。</param>
  public void OnDrag(PointerEventData eventData)
  {
    Operate(eventData);
  }

  /// <summary>タッチを離したときに呼ばれます。</summary>
  /// <param name="eventData">タッチ情報。</param>
  public void OnPointerUp(PointerEventData eventData)
  {
    // 入力をやめた扱いにしたいので zero を渡します
    SendValueToControl(Vector2.zero);
  }

  /// <summary>
  /// 方向パッドの入力処理を行います。
  /// </summary>
  /// <param name="eventData">タッチ情報。</param>
  private void Operate(PointerEventData eventData)
  {
    // タッチ位置を Canvas 上の位置に変換します
    RectTransformUtility.ScreenPointToLocalPointInRectangle(
      transform.parent.GetComponentInParent<RectTransform>(),
      eventData.position,
      eventData.pressEventCamera,
      out Vector2 localPoint);

    // Dpad の中心を原点としたタッチ位置
    Vector2 positionInDpad = localPoint - _objectPosition;

    // タッチ位置をオブジェクトサイズの半分で割り 0~1 の範囲に収めます
    Vector2 positionRate = Vector2.ClampMagnitude(positionInDpad / _objectSizeHalf, 1);

    // 入力値を OnScreenControl に渡してその後の処理を任せます。
    SendValueToControl(positionRate);
  }
}

Sie erstellen eine OnScreenControl Anpassungsklasse für Bildschirmsteuerelemente, indem Sie von der Customize-Klasse erben. Um verschiedene Touch-Ereignisse zu empfangen, erben Sie außerdem die Zielschnittstelle. Hier werden "beim Berühren", "beim Bewegen beim Berühren", "beim Loslassen der Berührung" und "vor dem Ziehen" verarbeitet, so dass auch die folgenden Schnittstellen jeweils beschrieben werden.

public class OnScreenDpad
  : OnScreenControl, IPointerDownHandler, IPointerUpHandler, IDragHandler, IInitializePotentialDragHandler
Inhalt der Benutzeroberfläche
IPointerDownHandler Bei Berührung
IPointerUpHandler Wenn Sie die Berührung loslassen
IDragHandler Wenn du dich bewegst, während du berührst
IInitializePotentialDragHandler Bevor Sie mit dem Ziehen beginnen

Die folgenden Felder werden deklariert:

controlPathInternalOnScreenControl ist erforderlich, wenn Sie von einer Klasse erben. Es enthält eine Zeichenfolge, welcher Taste des Eingabegeräts zugeordnet werden soll, aber im Grunde können Sie es so schreiben, wie es ist. InputControl Das Attribut sollte jedoch den Wert enthalten, der beibehalten werden soll (in diesem Fall Vector2).

_objectPosition_objectSizeHalf und halten Sie die halbe Position und Größe des Buttons im Voraus gedrückt und verwenden Sie ihn später für Berechnungen.

[InputControl(layout = "Vector2")]
[SerializeField]
private string _controlPath;
/// <summary><see cref="OnScreenControl"/> で定義された値。</summary>
protected override string controlPathInternal { get => _controlPath; set => _controlPath = value; }

/// <summary>オブジェクトの位置。</summary>
private Vector2 _objectPosition;

/// <summary>オブジェクトのサイズの半分 (スケールも含む)。</summary>
private Vector2 _objectSizeHalf;

Die Methode, die nach der Initialisierung des Objekts aufgerufen Start wird, erhält die Hälfte der Position und Größe der Schaltfläche auf der Leinwand. Die Größe berücksichtigt auch den Maßstab. Start Es wird von einer Methode verarbeitet, aber wenn es am Ende richtig in der Berechnung verwendet werden kann, kann der Erfassungszeitpunkt überall sein.

// <summary>
// オブジェクトが動作する最初のタイミングで1回だけ呼ばれます。
// </summary>
private void Start()
{
  var rectTransform = (RectTransform)base.transform;

  // オブジェクトの位置を取得
  _objectPosition = rectTransform.anchoredPosition;

  // オブジェクトのサイズの半分を取得 (スケールサイズも考慮)
  _objectSizeHalf = rectTransform.sizeDelta * rectTransform.localScale / 2f;
}

OnInitializePotentialDrag wird aufgerufen, wenn Sie mit dem Ziehen nach der Berührung beginnen möchten. Beim Ziehen OnDrag wird die Methode aufgerufen. Es wird ein Schwellenwert festgelegt, um die Ziehbeurteilung bis zu einem gewissen Grad zu verhindern, so dass sich der Finger nicht wenig bewegt und die Ziehbeurteilung nicht durch einfaches Berühren erfolgt.

Da es sich diesmal um eine Eingabe handelt, die davon ausgeht, dass Sie einen Feinabstimmungsvorgang durchführen möchten, deaktivieren Sie diese Schwellenwerteinstellung und treffen Sie sofort eine Drag-Beurteilung. eventData.useDragThreshold false Sie können den Schwellenwert überschreiben, indem Sie den Wert auf festlegen.

/// <summary>ドラッグの初期化処理として呼ばれます。</summary>
/// <param name="eventData">タッチ情報。</param>
public void OnInitializePotentialDrag(PointerEventData eventData)
{
  // タッチのスライド操作を即座に発生させたいのでドラッグ開始までの閾値を無効にします
  eventData.useDragThreshold = false;
}

Nachfolgend sind die Ereignisse aufgeführt, die beim Berühren, Ziehen bzw. Loslassen aufgerufen werden. OnPointerDown OnDrag Da und , führt jeder die gleiche Eingabeverarbeitung durch Operate , also erstellen wir eine separate Methode und rufen sie auf. OnPointerUp Übergeben Sie es nun an die Methode, um das Steuerelement darüber SendValueToControl Vector2.zero zu informieren, dass die Eingabe beendet wurde.

/// <summary>タッチしたタイミングで呼ばれます。</summary>
/// <param name="eventData">タッチ情報。</param>
public void OnPointerDown(PointerEventData eventData)
{
  Operate(eventData);
}

/// <summary>タッチした後ドラッグするたびに呼ばれます。</summary>
/// <param name="eventData">タッチ情報。</param>
public void OnDrag(PointerEventData eventData)
{
  Operate(eventData);
}

/// <summary>タッチを離したときに呼ばれます。</summary>
/// <param name="eventData">タッチ情報。</param>
public void OnPointerUp(PointerEventData eventData)
{
  // 入力をやめた扱いにしたいので zero を渡します
  SendValueToControl(Vector2.zero);
}

Operate Die Methode ist der Kern der D-Pad-Eingabeoperation.

Zunächst einmal kann die Touch-Position mit erhalten werden, aber da diese Koordinate die Koordinate des eventData.position Spielbildschirms ist, RectTransformUtility.ScreenPointToLocalPointInRectangle -Methode zum Konvertieren in Canvas-Koordinaten. Die zu übergebenden Werte sind "canvas", "touch position", "camera" und " RectTransformreceiving variable".

Nachdem Sie die "Touch-Position auf der Leinwand" erhalten haben, konvertieren Sie sie in die Position der Schaltfläche als Ursprung. Subtrahieren Sie einfach die Position () des_objectPosition Objekts.

Da die Touch-Position immer noch eine Zahl auf der Leinwand ist, konvertieren Sie diesen Wert in ein Verhältnis von 0~1. Wenn Sie durch die halbe Größe der Schaltfläche dividieren, beträgt die Touch-Position innerhalb des Bereichs der Schaltfläche 0~1. Wenn Sie mit der Toucheingabe ziehen, ist der Wert 1 oder mehr, da Vorgänge auch außerhalb der Schaltfläche akzeptiert werden. Vector2.ClampMagnitude Tun Sie dies in der Methode, damit sie 1 nicht überschreitet.

Übergeben Sie abschließend den in 0~1 konvertierten Eingabewert SendValueToControl an die Methode. Die On-Screen-Steuerung erledigt den Rest für Sie.

/// <summary>
/// 方向パッドの入力処理を行います。
/// </summary>
/// <param name="eventData">タッチ情報。</param>
private void Operate(PointerEventData eventData)
{
  // タッチ位置を Canvas 上の位置に変換します
  RectTransformUtility.ScreenPointToLocalPointInRectangle(
    transform.parent.GetComponentInParent<RectTransform>(),
    eventData.position,
    eventData.pressEventCamera,
    out Vector2 localPoint);

  // Dpad の中心を原点としたタッチ位置
  Vector2 positionInDpad = localPoint - _objectPosition;

  // タッチ位置をオブジェクトサイズの半分で割り 0~1 の範囲に収めます
  Vector2 positionRate = Vector2.ClampMagnitude(positionInDpad / _objectSizeHalf, 1);

  // 入力値を OnScreenControl に渡してその後の処理を任せます。
  SendValueToControl(positionRate);
}

Hängen Sie das Skript, das Sie erstellt haben, an die Schaltfläche an. Diese Aktion ist so eingestellt, dass sie als Bedienung des linken Sticks des Gamepads behandelt wird.

Versuchen Sie, das Spiel zu verschieben und die Tasten zu berühren. Ich denke, Sie können sehen, dass sich der erhaltene Wert je nach Touch-Position ändert. Außerdem können Sie sehen, dass sich der Wert je nach Ziehposition ändert, selbst wenn Sie während des Berührens ziehen.