如果我放置多个电源,我的PowerUp将无法正常工作

时间:2018-12-13 11:23:42

标签: c# unity3d

嘿,我为游戏制作了开机脚本。它旨在增强播放器,但确实可以,但是当我放置多个通电时,播放器可能会与之发生碰撞,这是行不通的。我什至重写了整个脚本,所以我没有使用静态变量,因为我认为这是问题所在,但显然不是。当我在地图上有一个通电时,它可以完美工作,但是当我放置两个或多个通电时,它不起作用,但仍将我的debug.log打印到控制台。

代码:

    using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PowerUp : MonoBehaviour {

    public bool boosting = false;
    public GameObject effect;
    public AudioSource clip;


    private void OnTriggerEnter(Collider other)
    {
        if (other.gameObject.CompareTag("Player"))
        {
            if (!boosting)
            {
                //Audio play
                clip.Play();
                //Start effect at powerups position
                GameObject explosion = Instantiate(effect, transform.position, transform.rotation);
                Destroy(explosion, 2);

                //disable collider and meshrender
                GetComponent<MeshRenderer>().enabled = false;
                GetComponent<Collider>().enabled = false;

                //Get the tankmovementscript via the collider and increase the speed
                TankMovement collidedMovement = other.gameObject.GetComponent<TankMovement>();
                collidedMovement.m_Speed = 20f;

                boosting = true;
                Debug.Log(boosting);
                StartCoroutine(coolDown());
            }
        }
        else if(other.gameObject.CompareTag("Player1"))
        {
            if(!boosting)
            {
            //Audio play
            clip.Play();

            //Start effect at powerups position
            GameObject explosion =Instantiate(effect, transform.position, transform.rotation);
            Destroy(explosion, 2);

            //disable collider and meshrender
            GetComponent<MeshRenderer>().enabled = false;
            GetComponent<Collider>().enabled = false;

            //Get the tankmovementscript via the collider and increase the speed
            TankMovement1 collidedMovement = other.gameObject.GetComponent<TankMovement1>();
            collidedMovement.m_Speed1 = 20f;

            boosting = true;
            Debug.Log(boosting);
            StartCoroutine(coolDown());
            }
        }
    }

    private IEnumerator coolDown()
    {
        if (boosting == true)
        {
            yield return new WaitForSeconds(4);
            {
                boosting = false;

                //wait 4 seconds enable the powerup again
                GetComponent<MeshRenderer>().enabled = true;
                GetComponent<Collider>().enabled = true;
                Debug.Log(boosting);


            }
        }
    }

     void reset()
     {
        //again find both tanks with name and get their movement script variable and change it back to normal
        GameObject.Find("Tank(Clone)").GetComponent<TankMovement>().m_Speed = 12f;
        GameObject.Find("Tank1(Clone)").GetComponent<TankMovement1>().m_Speed1 = 12f;

    }

    private void Update()
    {  //checking to see if the player is not boosting set speed to normal
        if (!boosting)
        {
            reset();
        }

    }   

}

1 个答案:

答案 0 :(得分:1)

您提到的行为仅是由于您具有两次以上通电时的“重置”功能,而其他通电则关闭了增强功能并将播放器速度设置为零。

有多种方法可以解决此问题,其中一种是将“声明”字段声明为静态字段,以使其成为所有加电程序之间的共享属性,但是会产生副作用,例如效果不会按预期叠加。

因此您必须为玩家实现一个简单的效果系统,以堆叠能量道具的效果,能量道具的责任只是提供这些效果,而不是激活/停用它们。

一个简单的实现可能是这样的:

效果:

public interface IEffect
{
    float Duration { get; set; }
    void Do(Player p);
    void Undo(Player p);
}

public class ActiveEffect
{
    public IEffect Effect { get; private set; }
    public float LeftTime;
    public ActiveEffect(IEffect effect)
    {
        Effect = effect;
        LeftTime = effect.Duration;
    }
}

public class SpeedBoost : IEffect
{
    public float Duration { get; set; }

    public SpeedBoost()
    {
        Duration = 4;
    }
    public void Do(Player p)
    {
        p.speed = 40f;
    }

    public void Undo(Player p)
    {
        p.speed = 20f;
    }
}

您的效果经理:

public class EffectManager
{
    Dictionary<Type, ActiveEffect> _activeEffects = new Dictionary<Type, ActiveEffect>();
    public void AddEffect(IEffect effect)
    {
        var type = effect.GetType();
        if (_activeEffects.ContainsKey(type))
        {
            //reseting effect duration to max
            _activeEffects[type].LeftTime = effect.Duration;
        }
        else
        {
            var activeEffect = new ActiveEffect(effect);
            _activeEffects.Add(type, activeEffect);
            StartCoroutine(activeEffect);
        }
    }

    private IEnumerator Apply(ActiveEffect effect)
    {
        effect.Effect.Do(player);
        while (effect.LeftTime > 0)
        {
            yield return new WaitForEndOfFrame();
            effect.LeftTime -= Time.deltaTime;
        }
        effect.Effect.Undo(player);
        _activeEffects.Remove(effect.Effect.GetType());
    }
}