当前位置:   article > 正文

Unity 3D — 协程、事件和委托_unity3d委托

unity3d委托

Unity 3D — 协程、事件和委托

在这里插入图片描述

Unity 3D 为开发人员提供了无数工具来创建身临其境的交互式体验。在这些工具中,协程、事件和委托是实现高效且有组织的代码的基本概念。在本指南中,我们将深入了解 Unity 3D 协程、事件和委托的世界,探索它们的用途并提供实际示例。

了解 Unity 3D 协程

Unity 中的协程是处理异步任务的强大机制,例如动画、延迟或不一定需要阻塞主线程的复杂操作。它们允许开发人员通过将任务分解为更小的、可管理的单元来编写更有组织性和可读性的代码。

基本协程语法

在 Unity 中,协程是一个使用 yield return 语句暂停执行并稍后从中断处恢复的函数。这是一个基本的协程示例:
using UnityEngine;

public class CoroutineExample : MonoBehaviour
{
    void Start()
    {
        StartCoroutine(MyCoroutine());
    }

    IEnumerator MyCoroutine()
    {
        Debug.Log("Coroutine started");

        yield return new WaitForSeconds(2f);

        Debug.Log("Coroutine resumed after 2 seconds");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
在这个例子中, StartCoroutine 启动协程,并从 MyCoroutine 的开头开始执行。 yield return new WaitForSeconds(2f) 行将协程暂停 2 秒,而不阻塞主线程。

现实世界示例:平滑的相机移动

让我们考虑一个场景,您希望随着时间的推移将相机从当前位置平滑地移动到目标位置。协程可以帮助轻松实现这一目标:
using UnityEngine;

public class CameraController : MonoBehaviour
{
    public Transform target;
    public float smoothSpeed = 2f;

    void Update()
    {
        StartCoroutine(MoveCameraSmoothly(target.position, smoothSpeed));
    }

    IEnumerator MoveCameraSmoothly(Vector3 targetPosition, float speed)
    {
        while (Vector3.Distance(transform.position, targetPosition) > 0.1f)
        {
            transform.position = Vector3.Lerp(transform.position, targetPosition, speed * Time.deltaTime);
            yield return null;
        }

        Debug.Log("Camera reached the target position");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
在此示例中,相机随着时间的推移平滑地移向目标位置,提供视觉上令人愉悦的效果。

Unity 3D 事件

Unity 事件提供了一种实现观察者模式的方法,允许对象无需直接相互引用即可进行通信。事件通常用于解耦系统,使代码模块化且更易于维护。

基本事件语法

以下是 Unity 事件的基本示例:

using UnityEngine;
using UnityEngine.Events;

public class EventExample : MonoBehaviour
{
    // Declare an event
    public UnityEvent myEvent;

    void Start()
    {
        // Subscribe a method to the event
        myEvent.AddListener(MyEventHandler);

        // Invoke the event
        myEvent.Invoke();
    }

    void MyEventHandler()
    {
        Debug.Log("Event handled!");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
在此示例中, myEvent 是一个可以使用 AddListener 订阅的 Unity 事件。然后使用 myEvent.Invoke() 调用该事件,从而触发订阅的方法。

现实世界示例:玩家健康系统

考虑一个您想要实施玩家健康系统的场景。当玩家的健康状况发生变化时,可以使用 Unity 事件来通知各个组件:
using UnityEngine;
using UnityEngine.Events;

public class PlayerHealth : MonoBehaviour
{
    public int maxHealth = 100;
    private int currentHealth;

    // Declare a health change event
    public UnityEvent onHealthChanged;

    void Start()
    {
        currentHealth = maxHealth;
        // Subscribe the UpdateUI method to the health change event
        onHealthChanged.AddListener(UpdateUI);
    }

    void TakeDamage(int damage)
    {
        currentHealth -= damage;

        // Invoke the health change event
        onHealthChanged.Invoke();
    }

    void UpdateUI()
    {
        Debug.Log("Player health updated. Current health: " + currentHealth);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
在此示例中,只要玩家受到伤害,就会调用 onHealthChanged 事件。订阅的方法,例如 UpdateUI ,将收到通知并可以做出相应的反应。

Unity 3D Delegate 的灵活性

Unity 中的委托提供了一种创建和使用函数指针的方法,从而使代码具有更大的灵活性和可扩展性。它们对于实现回调和自定义事件特别有用。

基本委托语法

以下是 Unity 委托的基本示例:
using UnityEngine;

public class DelegateExample : MonoBehaviour
{
    // Declare a delegate
    public delegate void MyDelegate();

    // Declare an instance of the delegate
    public MyDelegate myDelegate;

    void Start()
    {
        // Assign a method to the delegate
        myDelegate = MyDelegateMethod;

        // Invoke the delegate
        myDelegate();
    }

    void MyDelegateMethod()
    {
        Debug.Log("Delegate method invoked!");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
在此示例中, MyDelegate 是委托类型, myDelegate 是该委托的实例。方法 MyDelegateMethod 被分配给委托,并且调用委托会调用分配的方法。
真实示例:自定义事件系统
让我们使用委托来实现一个自定义事件系统。考虑一个场景,您希望各种组件对游戏事件做出反应:
using UnityEngine;

public class CustomEventSystem : MonoBehaviour
{
    // Declare a delegate for the event
    public delegate void GameEventHandler();

    // Declare an event using the delegate
    public static event GameEventHandler OnGameEvent;

    void Start()
    {
        // Subscribe methods to the event
        OnGameEvent += PlaySound;
        OnGameEvent += SpawnParticles;

        // Invoke the event
        OnGameEvent?.Invoke();
    }

    void PlaySound()
    {
        Debug.Log("Sound played!");
    }

    void SpawnParticles()
    {
        Debug.Log("Particles spawned!");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
在此示例中,使用 GameEventHandler 委托声明 OnGameEvent 事件。多个方法(例如 PlaySound 和 SpawnParticles )订阅该事件。调用该事件会触发所有订阅的方法。

集成 Unity 3D 协程、事件和委托

虽然 Unity 3D 协程、事件和委托本身就很强大,但将它们组合起来可以形成高度模块化和可扩展的代码库。这种集成允许您创建复杂的系统,其中异步任务、事件驱动的行为和基于委托的回调无缝地协同工作。

高级示例:游戏计时器系统

让我们创建一个示例,其中游戏计时器系统使用协程来处理基于时间的事件、通知组件特定时刻的事件以及动态回调的委托。
using UnityEngine;
using UnityEngine.Events;
using System;

public class GameTimerSystem : MonoBehaviour
{
    // Unity event for notifying components when the game starts
    public UnityEvent onStartGame;

    // Unity event for notifying components when the game ends
    public UnityEvent onEndGame;

    // Custom delegate for dynamic callbacks during the game
    public delegate void GameUpdateDelegate(float timeRemaining);
    public static event GameUpdateDelegate onGameUpdate;

    private float gameDuration = 60f; // Game duration in seconds

    void Start()
    {
        StartCoroutine(StartGame());
    }

    IEnumerator StartGame()
    {
        Debug.Log("Game starting in 3 seconds...");

        // Wait for 3 seconds before starting the game
        yield return new WaitForSeconds(3f);

        Debug.Log("Game started!");

        // Notify components that the game has started
        onStartGame?.Invoke();

        // Run the game loop
        StartCoroutine(GameLoop());
    }

    IEnumerator GameLoop()
    {
        float currentTime = gameDuration;

        while (currentTime > 0)
        {
            // Update the game timer
            onGameUpdate?.Invoke(currentTime);

            // Wait for one second
            yield return new WaitForSeconds(1f);

            // Decrement the timer
            currentTime--;

            // Simulate events happening during the game (for example, spawning enemies)
            if (currentTime == gameDuration - 10)
            {
                Debug.Log("10 seconds remaining - spawning enemies!");
                SpawnEnemies();
            }
        }

        // Game over
        Debug.Log("Game over!");

        // Notify components that the game has ended
        onEndGame?.Invoke();
    }

    void SpawnEnemies()
    {
        Debug.Log("Enemies spawned!");
    }

    // Subscribe to the game update delegate
    void OnEnable()
    {
        onGameUpdate += DisplayTimeRemaining;
    }

    // Unsubscribe from the game update delegate
    void OnDisable()
    {
        onGameUpdate -= DisplayTimeRemaining;
    }

    // Method to be called when the game updates
    void DisplayTimeRemaining(float timeRemaining)
    {
        Debug.Log("Time remaining: " + timeRemaining + " seconds");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
在此示例中, GameTimerSystem 结合了协程、事件和委托来创建强大的游戏计时器系统。 onStartGame 和 onEndGame Unity 事件用于在游戏开始和结束时通知组件。 onGameUpdate 委托允许在游戏期间进行动态回调,并且组件可以根据需要订阅或取消订阅该委托。
通过组合这些元素,您可以实现一个结构良好的模块化系统,其中游戏的不同方面可以响应特定事件或在运行时动态更新。这种集成展示了通过在 Unity 3D 游戏开发中利用协程、事件和委托可以实现的协同作用。
总之,Unity 3D 协程管理异步任务,事件促进组件之间的通信,委托提供动态回调。组合这些概念会产生模块化、可扩展且可读的代码。游戏计时器系统的集成示例展示了协同作用,为高效的 Unity 游戏开发提供了强大的工具包。
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/626673
推荐阅读
相关标签
  

闽ICP备14008679号