Delegates, Events and Singletons with Unity3D – C#



在这里我将演示怎样创建代表、 事件和Singletons 在一起工作。

本教程为 Unity3D 编写。


我想知道这为什么?
作为一个年轻的自学程序猿,我常常发现自己写tons 和布尔的语句,以确定是否发生了某些event 或action 。我听这些events 事件通过Coroutines 协同程序和其它方法来返回值。

假设你发现自己这做得一样好,停下来 !

欢迎光临Events事件......

介绍
近期。我一直要改善我的 C# 编程技能,以及发现自己缺乏知识,了解Events事件基础。所以,尽管通过很多教程在 MSDN 和其它博客上看着,发现了大多数的教程要复杂和茂盛用令人费解的代码不相关的核心概念。我不希望这发生在你身上 !

这样说过我会试着解释Events 事件和在项目中怎样使用它们的基础......

Singleton?
假设你不知道什么Singleton。。单身人士是不能 — 或反复的脚本。

嗯......

我推荐使用Singleton不须要复制多次在game中的东西。如Inventory System库存系统。通常情况下,玩家仅仅须要一个库存,我们仅仅想要一个。

当我们调用它时,我们想要确保它不会得到复制。

有很多方法能够创建Singletons。但这样的方法常常使用,由于它非常easy......

// This class sits on my camera and handles all the clicks I send with a Raycast 
public class Clicker : MonoBehaviour 
{   
     // Singleton 
     private static Clicker instance;   

     // Construct 
     private Clicker() {}    

     // Instance 
     public static Clicker Instance 
     {     
         get     
         {       
             if (instance == null)
 instance = GameObject.FindObjectOfType(typeof(Clicker)) as Clicker;      
                 return instance;    
         }   

         // Do something here, make sure this is public so we can access it through our Instance. 
         public void DoSomething() { }  
         ...  

在这里。'Clicker’ '类附加到我的Camera上。

此类处理点击 在3D 空间Raycast 的 。

若要从还有一个脚本訪问我 'DoSomething’  的方法。我仅仅能...

Clicker.Instance.DoSomething(); 

这消除了须要使用大量的静态方法和变量的调用,再加上仅仅给了我们一个实例 。


托付和事件?
托付能够看作是对对象的引用指针。

当它被调用时,它会通知全部引用该托付的方法。

所以。第一件事......

定义一个托付和获取调用时它触发的方法......

public class Clicker : MonoBehaviour 
{
   // Event Handler
   public delegate void OnClickEvent(GameObject g);
   public event OnClickEvent OnClick;

代理调用 'OnClickEvent' 通过一个‘GameObject’,我们能够使用来定义它来自什么游戏物体。然后。我们定义了 'event’  OnClick 获取调用时调用的托付。

如今。在同样的脚本中,我们须要调用托付。并将其传递我们的游戏对象。通过 Raycast......

public class Clicker : MonoBehaviour 
{
   // Event Handler
   public delegate void OnClickEvent(GameObject g);
   public event OnClickEvent OnClick;
   
   // Handle our Ray and Hit
   void Update () 
   {
     // Ray
 Ray ray = Camera.mainCamera.ScreenPointToRay(Input.mousePosition);
     
     // Raycast Hit
 RaycastHit hit;
     
     if (Physics.Raycast(ray, out hit, 100))
     {
       // If we click it
       if (Input.GetMouseButtonUp(0))
       {
         // Notify of the event!
 OnClick(hit.transform.gameObject);
       }
     }
   }
}

如你所见的,假设Ray 已联系 ,我们左鼠标单击对象,我们调用该事件并传递游戏物体。

我们必须做的最后一件事是从我们正在听call 的其它脚本引用托付。为此我创建了一个名为 GoldPile 类。


public class GoldPile : MonoBehaviour 
{
   // Awake
   void Awake ()
   {
     // Start the event listener
 Clicker.Instance.OnClick += OnClick;
   }
   
   // The event that gets called
   void OnClick(GameObject g)
   {
     // If g is THIS gameObject
     if (g == gameObject)
     {
 Debug.Log("Hide and give us money!");
       
       // Hide
 gameObject.active = false;
     }
   }
}

在我们的 Awake() 方法中,我们定义我们listening 的事件并分配一个获取调用 OnClick 的本地方法。'OnClick' 不须要我们托付方法同样,但它能够。

注:在曾经的帖子我们加入一个单例到我们Clicker 类。这使我们能够使用 Clicker.Instance

正如你所示我们还创建了传递我们点击我们游戏的 OnClick() 方法。

注:假设您必须使用 if (g == gameObject)。否则,它将隐藏该方法以及场景中的其它实例...这就是为什么我们通过GameObject 供參考 !

如今你有空。假设须要将此方法加入到您的游戏中的不论什么其它脚本。别忘了定义的方法,并在你的 Awake() 委派。


Yes, best way is to use OnEnable/OnDisable:

void OnEnable
{
Clicker.Instance.OnClick += OnClick;
}

void OnDisable
{
Clicker.Instance.OnClick -= OnClick;
}

posted on 2017-06-14 12:08  yjbjingcha  阅读(139)  评论(0编辑  收藏  举报

导航