【问题标题】:Coin Counter with Events带事件的硬币计数器
【发布时间】:2021-06-26 23:55:05
【问题描述】:

在 Unity 中,如何将事件发送到单个游戏对象?或者,我还能如何解决这个问题?

场景:假设一个场景中有六个玩家。还有一堆硬币供他们收集。

每个硬币都有一个CoinCollectable 脚本。当它检测到与玩家发生碰撞时,它会调用其OnCollected 事件。

public class CoinCollectable : MonoBehaviour
{
    // The action to invoke when this coin is collected by a player
    public static event Action<GameObject, int> OnCollected;

    // When a coin is touched
    private void OnTriggerEnter2D(Collider2D other) {

        // If not a player, abort
        if (!other.gameObject.CompareTag("Player")) return;

        // Invoke the coin collected event
        OnCollected?.Invoke(other.gameObject, coinValue);
    }
}

所有玩家都在他们的PlayerCoinCounter 脚本中收听此事件。

public class PlayerCoinCounter : MonoBehaviour
{
    private void OnEnable()
    {
        // Subscribe to events
        CoinCollectable.OnCollected += IncreaseCoins;
    }

    private void OnDisable()
    {
        // Un-subscribe from events
        CoinCollectable.OnCollected -= IncreaseCoins;
    }

    private void IncreaseCoins(GameObject player, int coinsToAdd)
    {
        // If this is not the player who collected the coin, abort
        if(player != this.gameObject) return;

        // (Increase the current coin counter value)       
    }
}

问题在于,使用这种设置,每个玩家都必须在他们的事件处理方法中检查“我是收集硬币的人吗?”。这感觉很麻烦,也不是很优雅。

您将如何解决这个问题?我想知道:

  • 有没有办法只将事件发送给实际收集硬币的玩家? (为了避免每个玩家都必须检查他们是否收集了它)
  • 如果不是,那么在OnTriggerEnter2D 中,我应该改为使用other.GameObject.GetComponent&lt;PlayerCoinCounter&gt;().IncreaseCoins(...) 吗?这感觉不太理想,因为我会假设玩家有这样的组件。所以我会失去事件方法提供的解耦。

PS:我正在使用事件来最小化耦合。

【问题讨论】:

    标签: c# unity3d events event-handling


    【解决方案1】:

    硬币不必做任何事情。我会反过来:

    把这个放在你的硬币上

    public class Coin : MonoBehaviour
    {
        public int value;
    }
    

    然后检查玩家是否与硬币发生碰撞并增加自己的计数器。

    类似

    public class PlayerCoinCounter : MonoBehaviour
    {
        public int coins;
    
        private void OnTriggerEnter2D(Collider2D other) {
    
            // If not a player, abort
            if (!other.TryGetComponent<Coin>(out var coin)) return;
    
            coins += coin.value;
        }
    }
    

    根本不需要任何事件。

    如果你对某个标签或某个组件有“依赖”,在我看来没什么区别。

    但我想说硬币不是增加玩家积分的责任,而是玩家本身;)

    【讨论】:

      【解决方案2】:

      您可以使用一些 IoC 容器(例如 Zenject)来处理耦合。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-05-03
        • 1970-01-01
        • 1970-01-01
        • 2011-05-11
        • 2021-03-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多