Обработка сенсорного ввода с помощью Event Trigger

Я написал простой скрипт для управления моим объектом «Player»:

using UnityEngine;
 using System.Collections;

 public class PlayerMovement : MonoBehaviour {

     public float jumpVelocity = 10;

     private Transform groundCheck;
     private Animator anim;
     private Rigidbody2D rigidbody2D;
     private bool grounded;
     private Physics2D gravity;

     [SerializeField] private LayerMask whatIsGround;

     const float groundedRadius = .2f;


     void Awake () {

         // Setting up references.
         groundCheck = transform.Find("GroundCheck");
         anim = GetComponent<Animator>();
         rigidbody2D = GetComponent<Rigidbody2D>();

     }

     // Use it for Graphic & Input
     void Update () {

     }

     //Physics and ground check
     void FixedUpdate () {

         grounded = false;

         Collider2D[] colliders = Physics2D.OverlapCircleAll(groundCheck.position, groundedRadius, whatIsGround);
         for (int i = 0; i < colliders.Length; i++)
         {
             if (colliders[i].gameObject != gameObject)
                 grounded = true;
         }

     }

     //Jump function
     public void Jump () {

         if (grounded) 
             rigidbody2D.velocity = jumpVelocity * Vector2.up;    
     }

     //Gliding function
     public void GlideON () {

         rigidbody2D.gravityScale = 1;
         Debug.Log ("Graviti is on");
     }

     public void GlideOFF () {

         rigidbody2D.gravityScale = 0;
         Debug.Log ("Graviti is off");

         if (!grounded) {
             rigidbody2D.velocity = ( -jumpVelocity / 10 ) * Vector2.up;
         }
     }

 }

Для работы с сенсорным экраном я использовал функцию GUI следующим образом:

введите описание изображения здесь

Что я хочу достичь:

  • Один клик - прыжок игрока
  • Кнопка удержания - игрок начинает скользить.
  • Игрок не может скользить, когда он заземлен.
  • Неважно, начинаю ли я с «PointerClick» или «PointerDown». Если игрок заземлен, первым действием должно быть «Jump» всегда.
  • Если мы начнем с «PointerDown», игрок должен прыгнуть, а после достижения максимальной высоты он начнет скользить.
  • Если мы начинаем с «PointerClick», игрок должен прыгать.
  • Если игрок не заземлен, и мы хотим начать скольжение - нам нужно коснуться экрана и удерживать его.

Где проблема:

  • Когда я начинаю с «PointerDown», мой игрок начинает бесконечный прыжок до «PointerUp».

Буду признателен за вашу помощь и предложения.

3 голоса | спросил MaD 18 Maypm15 2015, 22:41:16

2 ответа


1

Одним из лучших решений для управления подобным образом является шаблон состояния . Проблема с простое добавление bool для «может прыгать» - это может быстро превратиться в беспорядок, поскольку вы добавляете все больше и больше поведения и механики и все больше и больше разных комбинаций того, что игрок может и чего не может сделать. Ты раскачиваешься до центральной ошибки!

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

public abstract class PlayerState
{
   public virtual void handleInput( ref PlayerMovement player);
   public virtual void update( ref PlayerMovement player);
}

, и тогда каждое из ваших состояний предоставит специальное переопределение для особого удовольствия, которое оно получает:

public class PlayerStateJumping : PlayerState
{
   [SerializeField] private LayerMask whatIsGround;

   private Transform groundCheck;
   private Physics2D gravity;

   private float jumpVelocity;
   private float groundedRadius;

   public PlayerStateJumping()
   {
      groundedRadius = .2f;
      groundCheck = transform.Find("GroundCheck");
      player.setRigidBody2D(jumpVelocity * Vector2.up); 
      // Perform other necessary setup here 
   }

   public override void handleInput(PlayerMovement player)
   {
      if ( Input.getButtonDown("Glide") )
      {
         player.setState( new PlayerStateGliding() );
      }
   }

   public override void update(PlayerMovement player)
   {

     Collider2D[] colliders = Physics2D.OverlapCircleAll(groundCheck.position, groundedRadius, whatIsGround);
     for (int i = 0; i < colliders.Length; i++)
     {
         if (colliders[i].gameObject != gameObject)
         {
             player.setState(new PlayerStateIdle());
         }        
     }

   }
}

Теперь вы не можете прыгать снова в состоянии перехода, вы можете перейти только в состояние скольжения или вернуться в режим ожидания, когда вы достигнете земли. Вся информация, относящаяся к прыжкам, остается изолированной, так как она не должна запутывать остальные государства.

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

Затем он освободит PlayerMovement. Чтобы иметь более элегантный класс без шансов на замешательство:

public class PlayerMovement : Monobehaviour 
{
    private Animator anim;
    private Rigidbody2D rigidbody2D;

    private PlayerState currentState; 

    void Awake()
    {
      anim = GetComponent<Animator>();
      rigidbody2D = GetComponent<Rigidbody2D>();
      currentState = PlayerStateIdle();
    }

    void Update() 
    {

    }

    void FixedUpdate()
    {
       currentState.Update();
    }

    void setState( ref PlayerState playerState )
    {
       this.currentState = playerState;
    }

}

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

Если вы хотите добавить функциональность, не связанную с движением игрока (например, возможность стрелять в противника), чтобы остановить удвоение состояний, вы, вероятно, будете создавать класс PlayerShooting и иметь состояние там.

ответил Huxellberger 26 PM00000040000004331 2016, 16:01:43
0

Вы можете исправить это, добавив еще один bool canJump:

public void Jump () {
       if(canJump) {
         if (grounded) 
             rigidbody2D.velocity = jumpVelocity * Vector2.up;
       canJump = false;    
    }
 }

Итак, когда вы нажимаете, метод Jump () будет запускать цикл jumping один раз. После этого кода вам нужно будет установить canJump boolean к true, как только он снова ударит по земле.

EDIT: Кстати, использование обработчиков событий - это не самый эффективный способ, с помощью которого можно обрабатывать события касания Android /iOs. Вы можете просто добавить код в свой скрипт, используя Input.GetTouch , который предлагает не только 2 фазы (Down, Up), но 4- (5) фазы « касание ".

ответил Zee 19 Mayam15 2015, 00:25:07

Похожие вопросы

0
Как процедурно создать конус направленного света с холстом HTML? Вызов метода андроида из Unity3D с плагином JAR. Как сделать паузу на одной кости с позвоночником? Прозрачный диффузный не удается отобразить со всех углов обзора. Константа буфера не обновляется. vs. Stage sizeUnity 3d 4.6b Новая система с графическим интерфейсом не соприкасается, когда уже происходит событие касания в 3d-сцене. Можно ли сместить горизонтальный флип в SpriteEffects XNA? Редактировать расположение спавна в соответствии с поведением направления directionSteering с использованием узлов. Система в неравномерных средах. Информирование объектов в определенном состоянии мира. Повышение времени использования ресурсов для браузерной игры. [Duplicate] Реализация моторизованного шарнира направление jointChanging после создания объекта collisionDynamic с помощью HashMap2d. только соотношение входных данных и структуры distributionMouse в JS [закрыто] Влияет ли масштабирование на Форманс в OpenGL? [закрыто] Как реализовать панорамирование камеры, как в Maya? Обеспокоенность по поводу безопасности Google Play GamesКак сдвинуться к точке в 2D, останавливаясь на препятствияхПротиворечивое пространственное гравитационное моделирование Какой самый эффективный способ работать с игровыми сообщениями в Allegro 5? инициировать событие каждый раз, когда вращение моего solidbody2D находится на заданном значении? (XNA) Можно ли скрывать, сжимать или переименовывать файлы .XNB? Использование A * Навигация по местности, созданной сценариями? Статистика для тестирования средства визуализации [закрыто] Как создать карту нормалей из рельефной карты во время выполнения? Не работает индексированный чертеж в OpenGL. Добавить объекты в LWJGL без использования glTranslationf functionSpritekit - постепенно применять вектор силы в другом направлении (поворот космического корабля)

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132