Unity - C# - усилить выстрел перед стрельбой - PullRequest
0 голосов
/ 12 апреля 2020

Я пытаюсь запустить снаряд, который достаточно прост, используя свойство onClick кнопки пользовательского интерфейса, но я также хочу разрешить игроку заряжать его выстрел. Он работает на клавиатуре с помощью Input.GetButton («Огонь»), затем я добавляю Fire в менеджер ввода и для клавиши выбираю пробел. Но сейчас я пытаюсь добавить ту же функциональность к виртуальной кнопке для игроков с сенсорным экраном. Проблема в том, что щелчок не может проверить, постоянно ли нажата кнопка, ее можно вызвать только один раз. Поэтому для этого я пытаюсь использовать обработчики IPointer Up и Down в скрипте кнопки следующим образом:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;

public class FireButton : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
{
    public bool buttonPressed;

    public void OnPointerDown(PointerEventData eventData)
    {
        buttonPressed = true;
    }

    public void OnPointerUp(PointerEventData eventData)
    {
        buttonPressed = false;
    }

    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {

    }
}

Проблема в том, что в моих логах c, кажется, бесконечное l oop для сценария танка. Как только вызывается функция Update () и приведенный ниже оператор if для fire button.buttonPressed по какой-то причине становится истинным, он зацикливается и не продолжается. Вот следующий код (я закомментировал логи c для ввода с клавиатуры):

    using UnityEngine;
using UnityEngine.UI;

public class TankShooting : MonoBehaviour
{
    public int m_PlayerNumber = 1;              // Used to identify the different players.
    public Rigidbody m_Shell;                   // Prefab of the shell.
    public Transform m_FireTransform;           // A child of the tank where the shells are spawned.
    public Slider m_AimSlider;                  // A child of the tank that displays the current launch force.
    public AudioSource m_ShootingAudio;         // Reference to the audio source used to play the shooting audio. NB: different to the movement audio source.
    public AudioClip m_ChargingClip;            // Audio that plays when each shot is charging up.
    public AudioClip m_FireClip;                // Audio that plays when each shot is fired.
    public float m_MinLaunchForce = 15f;        // The force given to the shell if the fire button is not held.
    public float m_MaxLaunchForce = 30f;        // The force given to the shell if the fire button is held for the max charge time.
    public float m_MaxChargeTime = 0.75f;       // How long the shell can charge for before it is fired at max force.
    FireButton firebutton;

    private string m_FireButton;                // The input axis that is used for launching shells.
    private float m_CurrentLaunchForce;         // The force that will be given to the shell when the fire button is released.
    private float m_ChargeSpeed;                // How fast the launch force increases, based on the max charge time.
    private bool m_Fired;                       // Whether or not the shell has been launched with this button press.

    private void OnEnable()
    {
        // When the tank is turned on, reset the launch force and the UI
        m_CurrentLaunchForce = m_MinLaunchForce;
        m_AimSlider.value = m_MinLaunchForce;
    }


    public void Start()
    {
        firebutton = FindObjectOfType<FireButton>(); 
        // The fire axis is based on the player number.
        m_FireButton = "Fire" + m_PlayerNumber;
        // The rate that the launch force charges up is the range of possible forces by the max charge time.
        m_ChargeSpeed = (m_MaxLaunchForce - m_MinLaunchForce) / m_MaxChargeTime;
    }


    public void Update()
    {
        // The slider should have a default value of the minimum launch force.
        m_AimSlider.value = m_MinLaunchForce;

        // If the max force has been exceeded and the shell hasn't yet been launched...
        if(m_CurrentLaunchForce >= m_MaxLaunchForce && !m_Fired)
        {
            // ... use the max force and launch the shell.
            m_CurrentLaunchForce = m_MaxLaunchForce;
            Fire(); 
        }

        // Otherwise, if the fire button has just started being pressed...
        //else if(Input.GetButtonDown(m_FireButton))
        **//there is an infinite loop here needs fixing**
        else if (firebutton.buttonPressed)
        {
            Debug.Log("Test1 " + firebutton.buttonPressed);
            // ... reset the fired flag and reset the launch force.
            m_Fired = false;
            m_CurrentLaunchForce = m_MinLaunchForce;

            // Change the clip to the charging clip and start it playing.
            m_ShootingAudio.clip = m_ChargingClip;
            m_ShootingAudio.Play();
        }
        // Otherwise, if the fire button is being held and the shell hasn't been launched yet...
        //else if(Input.GetButton(m_FireButton) && !m_Fired)
        else if (firebutton.buttonPressed && !m_Fired)
        {
            Debug.Log("Test2 " + firebutton.buttonPressed);
            // Increment the launch force and update the slider.
            m_CurrentLaunchForce += m_ChargeSpeed * Time.deltaTime;

            m_AimSlider.value = m_CurrentLaunchForce;
        }
        // Otherwise, if the fire button is released and the shell hasn't been launched yet...
        //else if(Input.GetButtonUp(m_FireButton) && !m_Fired)
        else if (firebutton.buttonPressed && !m_Fired)
        {
            Debug.Log("Test3 " + firebutton.buttonPressed);
            // ... launch the shell.
            Fire();
        }
    }


    public void Fire()
    {
        // Set the fired flag so Fire is only called once.
        m_Fired = true;

        // Create an instance of the shell and store a reference to it's rigidbody.
        Rigidbody shellInstance =
            Instantiate(m_Shell, m_FireTransform.position, m_FireTransform.rotation) as Rigidbody;

        // Set the shell's velocity to the launch force in the fire position's forward direction.
        shellInstance.velocity = m_CurrentLaunchForce * m_FireTransform.forward; ;

        // Change the clip to the firing clip and play it.
        m_ShootingAudio.clip = m_FireClip;
        m_ShootingAudio.Play();

        // Reset the launch force.  This is a precaution in case of missing button events.
        m_CurrentLaunchForce = m_MinLaunchForce;
    }
}

Также, если вы считаете, что есть более простой способ сделать это с помощью диспетчера ввода или каким-либо другим способом, пожалуйста, почувствуйте бесплатно поделиться. Рад изменить всю эту логику c и попробовать что-то еще, работаю над этим уже 13 часов. Заранее спасибо!

Ответы [ 2 ]

1 голос
/ 13 апреля 2020

Я получил это работает! Отбросил весь подход UIButton и пошел с Input.touches

0 голосов
/ 12 апреля 2020

Я не мог видеть логику скорострельности c, которая останавливает бесконечные выстрелы. Вы можете определить скорость стрельбы, чтобы она не запускала бесконечные логики c может быть

float fireRate = 0.25f;
float lastFireTime; // Must be global

if(Time.time - lastFireTime> fireRate)
{
  Fire();
  lastFireTime = Time.time;
}

В конце вы можете использовать шаблон пула объектов вместо Instantiate для проблем с производительностью.

 Rigidbody shellInstance =
            Instantiate(m_Shell, m_FireTransform.position, m_FireTransform.rotation) as Rigidbody;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...