Как заставить Power Up длиться определенное время после столкновения? - PullRequest
0 голосов
/ 22 марта 2019

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

using UnityEngine;

public class PlayerCollision : MonoBehaviour {

public PlayerMovement movement;
public GameObject PowerUp;
public float jumpUpForce = 5000f;
public float jumpBackForce = 1000f;
public Rigidbody rb;


void OnCollisionEnter(Collision collisionInfo)
{
    if (collisionInfo.collider.tag == "Obstacle")
    {
        movement.enabled = false;
    }

    if (collisionInfo.collider.tag == "PowerUp")
    {
        PowerUp.SetActive(false);
        JumpPower();
    }
}

void JumpPower()
{
    if (transform.position.y < 2)
    {
        if (Input.GetKey("left shift"))
        {
            rb.AddForce(0, jumpUpForce * Time.deltaTime, -jumpBackForce * Time.deltaTime);
        }
    }
}

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

Любая помощь приветствуется.

Ответы [ 3 ]

2 голосов
/ 22 марта 2019

Вы можете использовать сопрограммы. Каждый раз, когда вы включаете питание, вы отменяете уже существующую сопрограмму (если она существует) и запускаете новую, которая будет обрабатывать время. Вот как это было бы сделано на моем пути:

public PlayerMovement movement;
public GameObject PowerUp;
public float jumpUpForce = 5000f;
public float jumpBackForce = 1000f;
public Rigidbody rb;

bool doWeHaveJumpPowerUp;
Coroutine cor;
public float timer;

// Use this for initialization
void Start()
{
    doWeHaveJumpPowerUp = false;
    timer = 10.0f;
}


void OnCollisionEnter(Collision collisionInfo)
{
    if (collisionInfo.collider.tag == "Obstacle")
        movement.enabled = false;

    if (collisionInfo.collider.tag == "PowerUp")
    {
        PowerUp.SetActive(false);
        if(cor != null)
        {
            StopCoroutine(cor);
            cor = null;
        }
        cor = StartCoroutine(JumpPower());
    }
}

IEnumerator JumpPower()
{
    doWeHaveJumpPowerUp = true;
    yield return new WaitForSeconds(timer);
    doWeHaveJumpPowerUp = false;
}

// Update is called once per frame
void Update()
{
    if (doWeHaveJumpPowerUp)
        if (transform.position.y < 2)
            if (Input.GetKey("left shift"))
                rb.AddForce(0, jumpUpForce * Time.deltaTime, -jumpBackForce * Time.deltaTime);
}

РЕДАКТИРОВАТЬ: если вы хотите больше типов бонусов, вот как вы хотите добавить их:

public PlayerMovement movement;
public GameObject PowerUp;
public float jumpUpForce = 5000f;
public float jumpBackForce = 1000f;
public Rigidbody rb;

bool doWeHaveJumpPowerUp;
Coroutine cor;
public float timer;

// 2nd power up
bool doWeHaveFlyPowerUp;

// Use this for initialization
void Start()
{
    doWeHaveJumpPowerUp = false;
    timer = 10.0f;
}


void OnCollisionEnter(Collision collisionInfo)
{
    if (collisionInfo.collider.tag == "Obstacle")
        movement.enabled = false;

    if (collisionInfo.collider.tag == "PowerUpJump")
    {
        PowerUp.SetActive(false);
        if (cor != null)
        {
            StopCoroutine(cor);
            cor = null;
        }
        cor = StartCoroutine(JumpPower());
    }

    if (collisionInfo.collider.tag == "PowerUpFly")
    {
        PowerUp.SetActive(false);
        if (cor != null)
        {
            StopCoroutine(cor);
            cor = null;
        }
        cor = StartCoroutine(FlyPower());
    }
}

IEnumerator JumpPower()
{
    doWeHaveJumpPowerUp = true;
    yield return new WaitForSeconds(timer);
    doWeHaveJumpPowerUp = false;
}

IEnumerator FlyPower()
{
    doWeHaveFlyPowerUp = true;
    yield return new WaitForSeconds(timer);
    doWeHaveFlyPowerUp = false;
}


// Update is called once per frame
void Update()
{
    if (doWeHaveJumpPowerUp)
        if (transform.position.y < 2)
            if (Input.GetKey("left shift"))
                rb.AddForce(0, jumpUpForce * Time.deltaTime, -jumpBackForce * Time.deltaTime);
    if (doWeHaveFlyPowerUp)
    {
        //Fly power up logic
    }
}

В обоих примерах включения питания отменяют уже существующее включение. Вы должны спланировать, как вы хотите, чтобы бонусы работали:

  • если персонаж сможет получить много бонусов одновременно.
  • Если вновь включенное питание того же типа, что у вас уже есть, увеличило продолжительность или обновило его.

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

0 голосов
/ 22 марта 2019

Вы также можете запустить сопрограмму!

// action is just a function or a method
// if you need that with arguments it would be System.Action< T > action
    IEnumerator TimerRoutine(int seconds, System.Action action)
    {
        int sec = 0;
        float delta = 0;
        while (true)
        {
            delta += Time.deltaTime;
            Debug.Log(delta);
            if(delta >= 1f)
            {
                sec += 1;
                delta = 0;
            }
            if (sec == seconds)
                break;
            else
                yield return null;
        }

        // this will start your function at the end of the timer
        action();
    }

Вы можете вызвать StartCoroutine (TimerRoutine (args)), чтобы запустить таймер из любого MonoBehaviour.

0 голосов
/ 22 марта 2019

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

Обычно я помещаю следующий код в Form.Load (), но, поскольку это не настоящее приложение winforms, вам, вероятно, будет лучше знать, где его разместить во время выполнения.

int t = 0; // Add this as a variable within the class to provide sufficient scope
Timer power_up_timer = new Timer();
power_up_timer.Interval = 1000; // 1000 ms = 1 second
power_up_timer.Tick += power_up_timer_Tick;

Затем добавьте событие Tick в любом месте класса:

private void power_up_timer_Tick(object sender, EventArgs e)
{
    if (t == 10) { /* End the power-up */ t = 0; power_up_timer.Stop(); }
    else { t++; }
}

Затем в своем блоке инициализации при включении добавьте:

power_up_timer.Start();

Однако вы можете заставить это работать в коде, это в значительной степени так и делается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...