Не может заставить работать перезарядку, выдает ошибки и не работает должным образом - PullRequest
0 голосов
/ 15 января 2020

Итак, я делаю VR-игру, и я хочу, чтобы, как только я нажал на спусковой крючок на джойстике, «меч» активировался и мог оставаться активным в течение 1 секунды, после этого он имеет время восстановления 1 второй также, в котором он не может быть активирован, а затем он сбрасывается. Я думал, что это будет просто, но я не могу на всю жизнь заставить это работать.

Вот код:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Valve.VR;

public class Sword : MonoBehaviour
{
    public SteamVR_Action_Boolean ActivateSword;
    public SteamVR_Input_Sources handType;
    private bool IsSwordActivated = false;
    private bool canSwordGetActivated = true;
    private bool cooldownStart = false;
    public Material activatedSword;
    public Material defaultSword;
    public float timeStamp;
    public float timer = 0;
    public float cooldown = 2;

    void Start()
    {
        ActivateSword.AddOnStateDownListener(TriggerDown, handType);
        ActivateSword.AddOnStateUpListener(TriggerUp, handType);
        timeStamp = Time.time;
    }

    public void TriggerUp(SteamVR_Action_Boolean fromAction, SteamVR_Input_Sources fromSource)
    {

            Debug.Log("Trigger is up");
            IsSwordActivated = false;
            this.GetComponent<MeshRenderer>().material = defaultSword;

    }
    public void TriggerDown(SteamVR_Action_Boolean fromAction, SteamVR_Input_Sources fromSource)
    {
        if (canSwordGetActivated == true)
        {
            Debug.Log("Trigger is down");
            IsSwordActivated = true;
            cooldownStart = true;
            this.GetComponent<MeshRenderer>().material = activatedSword;
        }


    }



    private void OnCollisionEnter(Collision collision)
    {
        if (collision.gameObject.CompareTag("Enemy"))
        {
            if (IsSwordActivated == true)
            {
                Destroy(collision.gameObject);
            }
        }

    }
    private void Update()
    {
        //if (timeStamp <= Time.time)
        //{
        //    if (IsSwordActivated == true)
        //    {
        //        timeStamp += 2;
        //        canSwordGetActivated = false;
        //        Debug.Log("test");
        //    }
        //}
        if (cooldownStart == true)
        {
            timer += Time.deltaTime;
            cooldown -= Time.deltaTime;
            if (timer >= 1f)
            {
                this.GetComponent<MeshRenderer>().material = defaultSword;
                IsSwordActivated = false;
                timer = 0;
            }
            if (timer == 0)
            {
                canSwordGetActivated = false;
            }
            if (cooldown <= 1f)
            {
                canSwordGetActivated = false;
            }
            if (cooldown <= 0)
            {
                cooldown = 2f;
                canSwordGetActivated = true;
                cooldownStart = false;
            }

        }

    }
}


Ответы [ 2 ]

2 голосов
/ 15 января 2020

Вы не должны использовать Update, но Coroutine для этого. Особенно «перезарядка» должна выполняться независимо от «таймера».

// Not needed
//private bool cooldownStart = false;
//public float timer = 0;

// reference this already via the Inspector if possible
[SerializeField] private MeshRenderer _meshRenderer;

[SerializeField] private float cooldownTime = 1;
[SerializeField] private float maxEnabledTime = 1;

// Otherwise get it only ONCE on runtime
private void Awake()
{
    if(!_meshRenderer) _meshRenderer = GetComponent<MeshRenderer>();
}

public void TriggerUp(SteamVR_Action_Boolean fromAction, SteamVR_Input_Sources fromSource)
{
    Debug.Log("Trigger is up");

    // stop the timeout
    StopAllCoroutines();

    // disable sword and start cooldown
    StartCoroutine(SwordCooldown());
}

public void TriggerDown(SteamVR_Action_Boolean fromAction, SteamVR_Input_Sources fromSource)
{
    if(IsSwordActivated) return;
    if (!canSwordGetActivated) return;

    Debug.Log("Trigger is down");

    // start timeout
    StartCoroutine(SwordEnabledTimer());
}

///<summary>
/// Disables sword and Runs cooldown before sword can be enabled again
///<summary>
private IEnumerator SwordCooldown()
{
    canSwordGetActivated = false;

    IsSwordActivated = false;
    _meshRenderer.material = defaultSword;

    yield return new WaitForSeconds(cooldownTime);

    canSwordGetActivated = true;
}

///<summary>
/// Disables the sword and jumps to cooldown after it was enabled for too long
///<summary>
private IEnumerator SwordEnabledTimer()
{
    canSwordGetActivated = false;

    yield return new WaitForSeconds(maxEnabledTime);

    StartCoroutine(SwordCooldown());
}

См. WaitForSeconds


Побочный эффект / Преимущество:

Сопрограммы часто лучше читаемы и удобны в обслуживании и более гибки, чем состояния опроса в Update!

Например, теперь вы можете очень просто расширить обе подпрограммы и добавить отображение прогресса для обеих, например,

private IEnumerator SwordCooldown()
{
    canSwordGetActivated = false;

    IsSwordActivated = false;
    _meshRenderer.material = defaultSword;

    var timePassed = 0f;
    while(timePassed < cooldownTime)
    {
        var cooldownProgress = timePassed / cooldownTime;

        // do something with the cooldownProgress value 0-1

        timePassed += Mathf.Min(Time.deltaTime, cooldownTime - timePassed);
        yield return null;
    }

    canSwordGetActivated = true;
}
0 голосов
/ 15 января 2020

Одним из простых способов сделать это будет сопрограмма:

class Sword {
   private bool isCoolingDown;

   public void Swing() {
       if (isCoolingDown) {
           Debug.Log("Sorry, cooling down right now");
           return;
       }

       StartCoroutine(DoSwingSword());

   }

   private IEnumerator DoSwingSword() {
       isCoolingDown = true;
       yield return new WaitForSeconds(1);
       isCoolingDown = false;
   }
}

При этом будет использоваться bool для отслеживания, если вы находитесь в охлажденном состоянии, и автоматический сброс этого bool через одну секунду, без вас, чтобы отслеживать Time.deltaTime. Затем вы можете обернуть остальную часть вашей логики c вокруг этой bool.

...