Mukauta näytön ohjaus suuntaohjaimen toteuttamiseksi
Varmennusympäristö
- Windows
-
- Windows 11
- Unity-editori
-
- 2020.3.25F1
- Syöttöjärjestelmän paketti
-
- 1.2.0
Tämän vinkin edellytykset
Seuraavat asetukset on tehty etukäteen tämän vinkin kuvauksen lähtökohtana.
Sinun tulisi myös tuntea seuraavat vinkit:
- Toimintokarttojen avulla voit määrittää painikkeita pelin toiminnalle
- Käytä kosketusoptimoituja syöttösäätimiä näyttöohjauksella
Näytön ohjaussauva on vakiosuuntatoiminto
On-Screen Stick on toteutettu virtuaalisena sauvana, joka toistaa samanlaisen sauvan toiminnan kuin fyysisessä ohjaimessa. Jos esimerkiksi haluat siirtää sitä oikealle, voit ensin koskettaa tikkua koskettamalla näyttöä ja liu'uttaa sitä sitten oikealle lyödäksesi sauvan alas.
Se on helppo kuvitella tikkuoperaatioksi, mutta päinvastoin, kun haluat siirtää sitä heti oikealle, (1) kosketa, (2) liu'uta oikealle, Koska se vaatii kaksivaiheista toimintaa, vastaus viivästyy väistämättä hieman. Tämä pätee erityisesti silloin, kun sinun on tehtävä nopea suunnanmuutos peräkkäin.
D-pad, joka määrittää suunnan kosketushetkellä (epätyypillinen)
Paras syöttötapa nopeaan suunnansyöttöön on sellainen, joka voi määrittää suunnan kosketushetkellä asettamalla jotain suuntaohjainta tai nuolinäppäintä. Se ei ole Unityn tekemä, mutta pelissäni Little Saber asetan nuolinäppäimet, jotta voit liikkua nopeasti koskettamaasi suuntaan. Voit tietysti myös liu'uttaa ylös tai vasemmalle koskettaessasi vaihtaaksesi liikkeitä.
On-Screen Control -standardia ei kuitenkaan ole helppo sijoittaa ja toteuttaa, koska siinä on vain näytön tikkuja ja näytön painikkeita.
Voit myös luoda pseudo-D-padin järjestämällä neljä painiketta alla olevan kuvan mukaisesti, mutta se on hankalaa, koska et voi syöttää vinosti. Jos asetat 8 painiketta, diagonaalinen toiminta on mahdollista, mutta virtaussuunnan käyttö, kuten "← ↙ ↓", ei silti ole mahdollista.
Luo suuntatyyny näytön ohjauksen mukauttamisella
Kuten näette, näytön ohjaus on vakiona vain sauvan ja painikkeen kanssa, mutta voit mukauttaa puuttuvia ominaisuuksia omilla skripteilläsi. Joten tässä haluaisin luoda suuntatyynyn, jossa on näytön ohjauksen mukauttaminen.
Toimintakartta
Käytämme toimintakarttaa, mutta käytämme edellisissä vinkeissä luotua sellaisenaan, joten menettely jätetään pois.
Olet myös kirjoittanut koodia.
Objektien sijoittaminen
Aseta tekstialue syötteen näyttämistä varten ja suuntaohjaimen korvaava painike. Tässä tapauksessa painikkeet on järjestetty, mutta voit korvata ne helpommin ymmärrettävällä kuvalla.
Komentosarja syötteen näyttämiseksi
Koska näytön hallinta korvaa kosketuksen ohjaimen fyysisellä vuorovaikutuksella, Luo komentosarja, joka näyttää syötteesi tekstinä, kun toimintokartta toimii.
Sisältö on sama kuin aiemmin, joten jätän selityksen pois.
- Toimintokarttojen avulla voit määrittää painikkeita pelin toiminnalle
- Käytä kosketusoptimoituja syöttösäätimiä näyttöohjauksella
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}";
}
}
Kun olet asentanut sen, tarkista ensin, toimiiko se näppäimistön tai peliohjaimen kanssa.
Näytön ohjausobjektien mukauttaminen
Tämä vie meidät näiden vinkkien pääaiheeseen.
Näyttöohjaimen mukauttaminen on komentosarja, joten luo ensin komentosarja.
Nimi on mielivaltainen, mutta tässä tapauksessa OnScreenDpad
se on .
Skripti näyttää tältä:
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);
}
}
Voit luoda näyttöohjauksen OnScreenControl
mukautusluokan perimällä sen Mukauta-luokasta.
Lisäksi, jos haluat vastaanottaa erilaisia kosketustapahtumia, peri kohdeliittymä.
Tässä käsitellään "kosketettaessa", "liikuttaessa koskettaessa", "kun kosketus vapautetaan" ja "ennen vetämistä", joten myös seuraavat rajapinnat kuvataan.
public class OnScreenDpad
: OnScreenControl, IPointerDownHandler, IPointerUpHandler, IDragHandler, IInitializePotentialDragHandler
Käyttöliittymän | sisältö |
---|---|
IPointerDownHandler | Kun kosketat |
IPointerUpHandler | Kun vapautat kosketuksen |
IDragHandler | Kun liikut koskettaessasi |
IInitializePotentialDragHandler | Ennen vetämisen aloittamista |
Seuraavat kentät ilmoitetaan:
controlPathInternal
OnScreenControl
vaaditaan, jos perit luokasta.
Siinä on merkkijono siitä, mihin syöttölaitteen painikkeeseen kartoitetaan, mutta periaatteessa voit kirjoittaa sen sellaisenaan.
InputControl
Määritteen tulisi kuitenkin sisältää säilytettävä arvo (tässä tapauksessa Vector2).
_objectPosition
_objectSizeHalf
ja pidä puolet painikkeen asennosta ja koosta etukäteen ja käytä sitä myöhemmin laskelmiin.
[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;
Menetelmä, jota kutsutaan Start
objektin alustuksen jälkeen, saa puolet kankaalle olevan painikkeen sijainnista ja koosta.
Koko ottaa huomioon myös mittakaavan.
Start
Se käsitellään menetelmällä, mutta jos sitä voidaan lopulta käyttää oikein laskennassa, hankinnan ajoitus voi olla mikä tahansa.
// <summary>
// オブジェクトが動作する最初のタイミングで1回だけ呼ばれます。
// </summary>
private void Start()
{
var rectTransform = (RectTransform)base.transform;
// オブジェクトの位置を取得
_objectPosition = rectTransform.anchoredPosition;
// オブジェクトのサイズの半分を取得 (スケールサイズも考慮)
_objectSizeHalf = rectTransform.sizeDelta * rectTransform.localScale / 2f;
}
OnInitializePotentialDrag
kutsutaan, kun haluat aloittaa vetämisen kosketuksen jälkeen.
Vetämisen OnDrag
aikana menetelmää kutsutaan.
Kynnys on asetettu estämään vetotuomio jossain määrin, jotta sormi ei liiku hieman ja vetotuomio ei tapahdu pelkän kosketuksen vuoksi.
Tällä kertaa, koska se on tulo, joka olettaa, että haluat suorittaa hienosäätötoiminnon, poista tämä kynnysasetus käytöstä ja tee välittömästi vetotuomio.
eventData.useDragThreshold
false
Voit ohittaa kynnyksen määrittämällä arvoksi .
<summary>ドラッグの初期化処理として呼ばれます。</summary>
<param name="eventData">タッチ情報。</param>
public void OnInitializePotentialDrag(PointerEventData eventData)
{
// タッチのスライド操作を即座に発生させたいのでドラッグ開始までの閾値を無効にします
eventData.useDragThreshold = false;
}
Alla on tapahtumat, joita kutsutaan kosketettaessa, vedettäessä ja vapautettaessa.
OnPointerDown
OnDrag
Koska ja , kukin suorittaa Operate
saman syötteen käsittelyn, joten luomme erillisen menetelmän ja kutsumme sitä.
OnPointerUp
Siirrä se nyt menetelmään ilmoittaaksesi SendValueToControl
Vector2.zero
ohjausobjektille, että se on lopettanut kirjoittamisen.
<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
Menetelmä on ydinsuuntaohjaimen syöttötoiminto.
Ensinnäkin kosketusasento voidaan saada , mutta koska tämä koordinaatti on pelinäytön koordinaatti eventData.position
,
RectTransformUtility.ScreenPointToLocalPointInRectangle
menetelmä muuntaa kankaalle koordinaateiksi.
Välitettävät arvot ovat "canvas", "touch position", "camera" ja " RectTransform
receiving variable".
Kun olet saanut "kosketusasennon kankaalle", muunna se painikkeen sijaintiin alkuperänä.
Vähennä vain objektin_objectPosition
sijainti ().
Seuraavaksi, koska kosketussijainti on edelleen numero kankaalla, muunna tämä arvo suhteeksi 0 ~ 1.
Jos jaat puoleen painikkeen koosta, kosketusasento painikkeen alueella on 0~1.
Jos vedät koskettamalla, arvo on 1 tai enemmän, koska se hyväksyy toiminnot myös painikkeen ulkopuolella.
Vector2.ClampMagnitude
Tee tämä menetelmällä niin, että se ei ylitä 1.
Lopuksi siirrä menetelmälle 0 ~ 1: ksi muunnettu syöttöarvo SendValueToControl
.
Näyttöohjaus tekee loput puolestasi.
<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);
}
Liitä luomasi komentosarja painikkeeseen. Tätä toimintoa käsitellään peliohjaimen vasemman sauvan toimintana.
Kokeile siirtää peliä ja koskettaa painikkeita. Mielestäni voit nähdä, että saatu arvo muuttuu kosketusasennon mukaan. Voit myös nähdä, että vaikka vedät koskettaessasi, arvo muuttuu vetoasennon mukaan.