簡體   English   中英

碰撞后如何在一定時間內持續通電?

[英]How to make a Power Up last for a certain amount of time after collision?

我正在制作一個怪異的小跑步游戲,並且嘗試添加一種加電功能,使玩家可以跳躍一小段時間(也許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()函數時,它僅調用一次,因此無法檢測到按下的左移行為(我認為)。

任何幫助表示贊賞。

您可以使用協程。 每次上電時,您都將取消已經存在的協程(如果存在)並開始新的協程,這將處理時間。 這是用我的方式來做的:

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
    }
}

在這兩個示例中,上電會取消已經存在的上電。 您應該計划上電的工作方式:

  • 角色應該能夠同時具有很多能量提升功能。
  • 應該重新啟動您已經具有的相同類型的加電功能,以延長持續時間或刷新它。

另外,此時您將只能進行一次通電。 如果您想要更多,則必須為它們編寫一個生成器(如果您希望它們是隨機的),或者如果您希望它們按某種順序排列,請手動放置它們。

我不熟悉Unity編碼,但是對於您要完成的工作,聽起來好像您需要運行一個Timer。

我通常將以下代碼放在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();

但是,您可以在代碼中得到解決,這幾乎就是它的完成方式。

您還可以運行協程!

// 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啟動計時器。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM