Oyun davranışlarına düğmeler atamak için eylem haritalarını kullanma

Sayfa güncel :
Sayfa oluşturma tarihi :

Doğrulama ortamı

Windows
  • Pencereler 11
Birlik Editörü
  • 2020.3.25f1
Giriş Sistemi Paketi
  • 1.2.0

Bu ipucu için önkoşullar

Aşağıdaki ayarlar, bu ipucunun açıklaması için bir öncül olarak önceden yapılmıştır.

Eylem Haritaları Hakkında

Klavyelerdeki, farelerdeki ve gamepad'lerdeki kullanıcı giriş programları temel olarak bir düğmeye basıldığında belirli bir eylemin gerçekleştirildiğini belirtti. Örneğin, eylem haritasında "atlama" eylemini tanımlayabilir ve denetleyici düğmeleri ve klavye tuşları atayabilirsiniz. Sonuç olarak, programın yalnızca belirli bir eylem gerçekleştirildiğinde süreci tanımlaması gerekir. Başka bir denetleyicideki bir düğmeyi sonradan düşünülmüş olarak atasanız bile, işletim programını değiştirmeden uygulayabilirsiniz.

Eylem Haritası Oluşturma

Burada bir aksiyon haritası oluşturmak ve kullanıcının giriş bilgilerini metinde görüntülemek istiyorum. Eylem Haritaları'nı kullanarak kullanıcı girdisi almanın birkaç yolu vardır.

Giriş Eylemi oluşturmak için projedeki herhangi bir klasörü sağ tıklatın. Oluşturulacak klasörün konumu isteğe bağlıdır, ancak lütfen projenize göre yönetin. Dosya adı da keyfidir, ancak işte burada InputActionSample .

Oluşturulan dosyayı çift tıklattığınızda, aşağıdaki pencere görüntülenir.

İlk olarak, bir eylem haritası oluşturmak için Eylem Haritaları'ndaki + düğmesini tıklatın. Bir oluşturma birimi olarak, operasyonun içeriği sahneye bağlı olarak değişirse, o birimde tanımlanacaktır. Örneğin, yandan kaydırmalı bir aksiyon oyunu söz konusu olduğunda, işlemin içeriği eylem sırasında ve menüde değişir, böylece her biri için bir eylem haritası oluşturursunuz.

Burada, örnek olarak, bir yandan kaydırma eylemi tanımlıyoruz ve buna "SideScrollActionMap" adını veriyoruz.

Ardından, Eylemler oluşturun. Bir örnek olduğu için, çoğunu yapmayacağım, ancak burada hareket için "Hareket" eylemleri ve saldırı için "Saldırı" eylemleri oluşturacağız. Zaten bir tane oluşturulduğundan, lütfen adı değiştirin veya yeni bir tane oluşturun, sağ üst köşedeki + düğmesine tıklayın ve girin.

İlk olarak, Taşıma yapılandırmasını yapılandırın. Oyun kumandası çubuk, yön düğmesi ve klavye imleç tuşlarını kullandığınızı varsayar. Yandan kaydırma eylemi durumunda, yalnızca sol ve sağın kullanıldığı durumlar vardır, ancak burada üst tuşla atlamayı ve aşağı tuşla çömelmeyi düşünerek dört yön kullandığınızı varsayıyoruz.

Taşı'yı seçtiğinizde, sağda bir Eylem Türü seçimi vardır, bu nedenle bunu "Değer" olarak ayarlayın.

Kontrol Tipini aşağıda göreceksiniz, bu nedenle Vektör2'yi seçin. Bunun nedeni, üst ve alt kısımların Y'ye, sol ve sağın da X'e atanmış olmasıdır.

Ardından bu olaya atamak istediğiniz anahtarı seçin. Ortada Bağlama Yok'u seçin ve sağdaki Yol'u seçin. Burada GamePad LeftStick'i seçiyoruz.

Bu, GamePad'in LeftStick'ini harekete bağlar.

Diğer oyun kumandalarını da bağlamak için Taşı'nın sağındaki + düğmesinden "Bağlama Ekle"yi seçin.

Artık Bağlama Yok eklendiğine göre, GamePad için bir Dpad atıyoruz.

Bu şekilde, desteklemek istediğiniz oyun kumandası türünü, tuşları ve çubukları ekleyebilirsiniz. Belirli bir oyun konsolu için özel olarak ayarlamak da mümkündür.

Çubuklar ve Dpad'ler yukarı, aşağı, sol ve sağ varsayan düğmelerdir, bu nedenle bununla eklenebilirler, ancak klavyeler söz konusu olduğunda, hepsi tek tuşlardır, bu nedenle yukarı, aşağı, sol ve sağ için bir tanım yoktur. Klavyeyi yukarı, aşağı, sola veya sağa ayarlamak için + düğmesinden Yukarı Aşağı Sol Sağ Bileşik Ekle'yi seçin.

Daha sonra bir 2B Vektör eklenecek ve aşağıdaki şekilde gösterildiği gibi her bir Yukarı Aşağı Sol Sağa atayabilirsiniz.

Örneğin, Yukarı kullanıyorsanız, klavyenizde "Yukarı Ok"u ayarlayın. Bu arada, bir anahtar bulmakta zorlanıyorsanız, "Dinle" düğmesini tıklatırken hedef tuşa basarak kolayca seçebilirsiniz.

Yukarı artık Yukarı Ok olarak ayarlanmıştır.

Benzer şekilde, Aşağı, Sol ve Sağ'ı ayarlayın ve işiniz bitti.

Tabii ki, sadece imleç tuşları değil, aynı zamanda WASD de ayarlanabilir.

Ardından, Saldırı'yı yapılandırın. Tek bir düğme olduğu için saldırının atanması kolaydır. İlk olarak, Saldırı'yı seçin ve Eylem Türü'nün bir düğme olduğundan emin olun.

Ardından Bağlama Yok'u seçin ve Yol'dan atamak istediğiniz düğmeyi seçin.

Daha fazla eklemek istiyorsanız, + düğmesinden "Bağlama Ekle" yi seçin.

İhtiyacınız olduğu kadar ekleyin. Bir düğme olarak kabul edildiğinden, klavye bir oyun denetleyicisi ile aynı şekilde ayarlanabilir.

Tüm ayarlar tamamlandığında, kaydetmek için "Varlığı Kaydet" i tıklayın. Bu pencereyi kapatabilirsiniz.

Son olarak, projenin inputactions dosyasıyla (bu durumda, daha önce oluşturduğunuz InputActionSample dosyası), denetçide "C# Sınıfı Oluştur" seçeneğini işaretleyin. Parametre eklenecektir, ancak olduğu gibi "Uygula" düğmesini tıklayın.

Bu, aynı ada sahip bir komut dosyası oluşturur. Programlardan eylem eşlemelerini kullanmak için yararlı olan sınıflar içerir.

Giriş bilgileri nasıl alınır

Bir eylem haritasına dayalı girdi almanın birkaç yolu vardır. Bu ipucu üç kalıbı açıklar, ancak aslında bir oyun yaparken bunlardan birine odaklanmak daha iyidir. Bunları ayrı ayrı kullanırsanız, yönetilmesi zahmetli olacaktır.

Ayrıca, tek bir sahnede birden çok giriş alma yöntemi kullanırsanız, işleme dahili olarak çakışabilir ve düzgün çalışmayabilir.

Mesaj Gönder'de giriş bilgilerini alma

Buradaki ilk yöntem, "Mesaj Gönder" de giriş bilgilerinin nasıl alınacağıdır.

Bu kez, girilen bilgileri metinde görüntülemek istiyorum, bu yüzden bir metin nesnesi yerleştireceğim.

Ayrıca, bu ipucu birden fazla giriş bilgisi almaya çalışacağından, bileşeni ayrı ayrı ayarlamak için boş bir nesne oluşturacağız. Adı herhangi bir şey olabilir.

Ardından, boş nesneye bir Player Girişi bileşeni ekleyin. Oyuncu Girişi, aksiyon haritalarını ve senaryoları bağlamak için önemli bir bileşendir.

"Bileşen Ekle" de, "Giriş" kategorisinde "Oyuncu Girişi" vardır, bu yüzden ekleyin.

Oynatıcı Girişi bileşeni eklendikten sonra, "İşlemler"de oluşturduğunuz eylem haritasını ayarlayın. Projeden bırakın veya sağdaki + simgesinden seçin.

Varsayılan Harita'nın, eylem haritasında oluşturduğunuz Harita olduğunu doğrulayın.

Davranışın "İleti Gönder" olduğunu doğrulayın.

Ardından, bir komut dosyası oluşturun. Dosya adı herhangi bir şey olabilir, ama işte burada InputSendMessage .

Komut dosyası şöyle görünür:

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

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

  /// <summary>
  /// Move アクションが実行されたときに呼ばれる。
  /// </summary>
  /// <param name="inputValue">入力量。</param>
  public void OnMove(InputValue inputValue)
  {
    var vec = inputValue.Get<Vector2>();
    TextObject.text = $"Move:({vec.x:f2}, {vec.y:f2})\n{TextObject.text}";
  }

  /// <summary>
  /// Attack アクションが実行されたときに呼ばれる。
  /// </summary>
  public void OnAttack(InputValue inputValue)
  {
    TextObject.text = $"Attack:{inputValue.isPressed}\n{TextObject.text}";
  }
}
  • Nesneye, İleti Gönder'i ayarlayan bir Yürütücü Girişi eklenmiştir
  • MonoBehaviour'dan Devralma

Koşullar karşılanıyorsa, "OnXXXXXXXX" adlı bir yöntem tanımlarsanız, Hedef yöntem, belirtilen eylem işlemi gerçekleştirildiğinde çağrılır. "XXXXXXXX", eylem haritasında oluşturulan Eylemlerin adıdır. Burada, "Move" ve "Attack" eylemleri oluşturduk, bu nedenle yöntem adları sırasıyla "OnMove" ve "OnAttack" dir.

OnMove Girilen tutarı 'nin argümanından InputValue alabilirsiniz. Kontrol Türü "Vektör 2" olarak ayarlandığından, giriş değeri InputValue.Get<Vector2> .

OnAttackInputValue.isPressed Ayrıca içeri girip girmediğinizi de öğrenebilirsiniz.

Komut dosyasını kaydettikten sonra, Player Girişi bileşeni olan bir nesneye ekleyin. Metin nesnesini de görüntülenmek üzere ayarlayın.

Oyunu çalıştırın ve bir göz atın. Bu kez, gamepad ve klavyenin tanımını ekledim, bu yüzden hangisini çalıştırırsanız çalıştırın çalışması gerekir.

Taşıdığınızda görebileceğiniz gibi, yöntemin yalnızca önceki durumdan değerde bir değişiklik olduğunda çağrıldığını görebilirsiniz. Örneğin, çubuğu sola hareket ettirirken, tek fikirli olarak adlandırılır, ancak sola değil (- OnMove 1,0). OnMove Saldırı düğmesi de yalnızca basıldığı anda yanıt verir ve basılıp tutulursa yöntem çağrılmaz.

Bu nedenle, ideal kullanımın OnXXXXXXXX çağrıldığında oyun işleme yapmak değil, sadece giriş içeriklerini tutmak ve bu değerleri oyunun güncelleme işleminde kullanmak olduğunu düşünüyorum.

Bu arada, mevcut durumda, düğme serbest bırakıldığında çağrılmaz, bu nedenle düğmenin ne zaman OnAttack serbest bırakılacağını belirlemek mümkün değildir. Buna yanıt vermek için, eylem haritası ayarlarında düğmeyi tanımlayan Saldırı eylemini seçin ve "Etkileşimler" den "Bas" ekleyin. Bundan sonra, eklenen Basının Tetikleme Davranışını "Basın ve Bırakın" olarak ayarlayın ve kaydedin.

Yürütüldüğünde, düğme bırakıldığında bile OnAttack çağrıldığını görebilirsiniz. isPressed false Olduğundan beri, serbest bırakma zamanlaması olup olmadığını belirlemek de mümkündür.

Bu arada, lütfen bu etkileşimi silin çünkü gelecekte kullanılmayacaktır.

Birlik Etkinliklerini Çağır ile girdi alın

Girdi almanın ikinci bir yolu Birlik Olaylarını Çağırmaktır, bu yüzden bunu deneyelim. Yukarıda belirtildiği gibi, birden fazla giriş yöntemi kullanmak çakışan işlemeye neden olabilir, bu nedenle başka bir işlem etkinse devre dışı bırakın.

İlk olarak, giriş bilgilerinin görüntülenebilmesi için metin nesnesini yerleştirin.

Unity Olaylarını Çağır, ilgili işlemleri gerçekleştiren boş bir nesne oluşturur.

Boş nesneye Input > Player Input ekleyin.

Eylemler için oluşturduğunuz eylem eşlemesi dosyasını (bu durumda, InputActionSample) ayarlayın ve oluşturduğunuz Eylem Eşlemesini (bu durumda, SideScrollActionMap) Varsayılan Eşleme olarak ayarlayın. Birlik olaylarını çağırmak için davranışı ayarlayın.

Bir komut dosyası oluşturun. Adı keyfidir, ancak bu durumda InputInvokeUnityEvents .

Komut dosyası şöyle görünür:

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

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

  /// <summary>
  /// Move 操作を行ったときに呼ばれる。
  /// </summary>
  /// <param name="context">コールバック内容。</param>
  public void OnMove(InputAction.CallbackContext context)
  {
    var vec = context.ReadValue<Vector2>();
    TextObject.text = $"Move:({vec.x:f2}, {vec.y:f2})\n{TextObject.text}";
  }

  /// <summary>
  /// Move 操作を行ったときに呼ばれる。
  /// </summary>
  /// <param name="context">コールバック内容。</param>
  public void OnAttack(InputAction.CallbackContext context)
  {
    var value = context.ReadValueAsButton();
    TextObject.text = $"Attack:{value}\n{TextObject.text}";
  }
}

Kullanıcı onunla etkileşime girdiğinde çağrılan yöntem adıOnMoveOnAttack, İleti Gönder'de olduğu gibi 'dir. Birlik Olaylarını Çağır'da, bu yöntem adını istediğiniz gibi ayarlayabilirsiniz.

Her biri çağrıldığında, bağımsız InputAction.CallbackContext değişken olarak geçirilir, böylece giriş durumunu oradan alabilirsiniz. Eylemde bir "değer" ayarlarsanız, yöntemde alabilirsiniz ve bir "düğme" ayarlarsanız ReadValue ReadValueAsButton , yöntemde alabilirsiniz.

Komut dosyasını kaydettikten sonra, Player Girişi'ni ayarladığınız nesneye ekleyin ve görüntüleme metni nesnesini ayarlayın.

Ardından, Oyuncu Girişinde "Etkinlik" ve "Eylem Haritası Adı (SideScrollActionMap)" seçeneğini genişletin ve oluşturduğunuz "Taşı" ve "Saldırı" eylemlerini görmelisiniz.

İlk olarak, eklemek için Taşı'daki + düğmesini tıklayın.

Sol alt köşedeki nesne kendi nesnenizdir ve İşlev az önce oluşturduğunuz OnMove yönteme ayarlanır.

Saldırı olayını da yapılandırın.

Nasıl çalıştığını görmek için oyunu çalıştırın.

Temel olarak, yalnızca Mesaj Gönder ile aynı değer değiştiğinde çağrılır, ancak bazı nedenlerden dolayı yöntem aynı anda iki kez çağrılabilir. Nedenini bilmiyorum, ama sanırım bunun nedeni muhtemelen başlangıç süreci ve sürekli sürecin aynı anda çalışıyor olmasıdır. Ancak Mesaj Gönder'de olduğu gibi sadece girilen değeri koruyup Güncelleme işleminde asıl oyun işlemesini ayrı ayrı gerçekleştirmenizde bir sorun olmadığını düşünüyorum.

Giriş bilgilerini almak için otomatik olarak oluşturulan bir komut dosyası kullanma

Üçüncü bölümde, eylem eşleme dosyasından oluşturulan bir komut dosyası kullanılarak giriş bilgilerinin nasıl elde edileceği açıklanmaktadır.

Diğer satın alma süreçleriyle çakışma olasılığı olduğundan, lütfen diğer satın alma süreçlerini devre dışı bırakın.

Giriş bilgilerini görüntülemek için bir metin nesnesi yerleştirin.

Ayrıca, giriş bilgilerini almak için boş bir nesne oluşturun. Bu makalede otomatik olarak oluşturulan bir komut dosyası kullanıldığından, Oynatıcı Girişi eklemeniz gerekmez.

Eylem haritasından otomatik olarak oluşturulan komut dosyası yalnızca bir kitaplıktır, bu nedenle ayrı bir kontrol komut dosyası oluşturun. Adı keyfidir, ancak bu durumda InputScript .

Komut dosyası şöyle görünür:

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

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

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

  private void Awake()
  {
    // 各操作を行ったときに呼ばれるイベントを設定する
    _actionMap = new InputActionSample();
    _actionMap.SideScrollActionMap.Move.performed += context => OnMove(context);
    _actionMap.SideScrollActionMap.Attack.performed += 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}";
  }
}

Alandaki eylem haritasından otomatik olarak oluşturulan bir sınıf InputActionSample tanımlayın. Bu sınıf, eylem haritasında ayarlanan her eylemi tanımlar ve bu eylemler gerçekleştirildiğinde çağrılan olayları ayarlayabilirsiniz.

Awake Yöntemde, InputActionSample bir örneği oluşturulur ve eylem sırasında çağrılan olay ayarlanır. Bu işlemleri gerçekleştirdiğinizde OnMove, , OnAttack yöntemi artık çağrılır.

Ancak, olayı yalnızca burada ayarladığımız için, eylem haritasını etkinleştirmek için çağrıldığında Enable yöntemi çağırmamız OnEnable gerekir.

Ayrıca, kullanıcının giriş davranışı genel bir işlem olarak ele alındığından, Bu nesne geçersiz kılındıktan sonra eylem haritasının fazladan bir şey yapmasını önlemek OnDisable için, onu devre dışı bırakmak için yöntemdeki Disable yöntemi çağırıyoruz.

Komut dosyasını kaydettikten sonra, oluşturduğunuz boş nesneye ekleyin ve metin nesnesini görüntülenmek üzere ayarlayın.

Nasıl çalıştığını görmek için oyunu çalıştırın.

Gördüğünüz gibi, Move işlemi (0, 0) olduğunda OnMove yöntem çağrılmaz. Neden olduğundan emin değilim, ancak gerçekleştirilen olayın yalnızca tuş vuruşlarının etkin olduğu olayı aldığı anlaşılıyor.

Bu arada, Saldırı için eylem haritasında Etkileşimler ayarlamadıysanız, düğmeyi bıraktığınızda çağrılmaz OnAttack .

Bunu halletmek canceled için bir etkinlik ayarlamanız gerekir. (0, 0) 'da özel işlem yapmak istemiyorsanız, yöntemi olduğu OnMove gibi çağırabilirsiniz. Aynı şey Saldırı için de geçerlidir.

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

Çalıştırın ve Move:(0, 0) veya Attack:False'un göründüğünü doğrulayın.