Unity3D学习之C#的代理和事件

2020最新版C/C++学习路线图--游戏服务器开发重点 黑马程序员C/C++学习路线图大纲中第六阶段的学习是游戏服务器开发的学习:主要介绍了C/C++学习路线图的游戏服务器开发的学习目标,C/C++学习路线图的游戏服务器开发的市场价值,C/C++学习路线图的游戏服务器开发的重点知识。C/C++学习路线图中的游戏服务器开发学习视频在黑马程序员视频库中找到自学教程。 C/C++学习路线图中游戏服务器开发的技术要点:zinx并发框架;docker;Nginx... 阅读详情

欢迎来到狗刨学习网,这里有很多U3D资源、U3D培训视频、U3D常见问题、U3D项目源码,我们致力于打造业内unity3d培训、学习第一品牌 

代理 (Delegate)
       大多数情况下,当调用函数时我们会指定要直接调用的函数。比如类 MyClass 如具有一个名为 Process 的函数,我们通常会按如下方法进行调用: 

MyClass myClass = new MyClass();
myClass.Process(); 

 

       这种调用在大多数情况下都是可行的。但是有些时候,我们不想直接调用函数,而希望能够将它传递给其他人,让他们进行调用。在以事件驱动的系统(如图形用户 界面)中,这种方法尤为有用。例如当我需要在用户单击某个按钮即可执行一些代码时,或者当我要记录一些信息但却无法指定记录方式时。
考虑以下示例: 

public class MyClass
{
public void Process()
{
Console.WriteLine(“Process() begin”);
// 这里还有其他东西…
Console.WriteLine(“Process() end”);
}
} 

 

       在此类中,我们进行一些记录,以了解函数的开始时间和结束时间。但是,我们的记录仅限于发送到控制台,这可能不是我们所需要的。我们真正需要的是能够控制从函数外部记录信息的位置,同时不必使函数代码变得复杂。 

 

       在这种情况下,代理便是理想的解决方法。代理使我们可以指定将要调用的函数,看起来好像不需要指定哪个函数一样。对代理的声明类似于对函数的声明,不同的是在这种情况下,我们所声明的是此代理可引用的函数签名。 

 

       我们的例子将声明一个带有单个字符串参数且没有返回类型的代理。修改该类如下: 

public class MyClass
{
public delegate void LogHandler(string message);
public void Process(LogHandler logHandler)
{
if (logHandler != null)
logHandler(“Process() begin”);
// 这里还有其他东西
if (logHandler != null)
logHandler (“Process() end”);
}
} 

 

       使用代理与直接调用函数相似。只是在调用函数前,我们需要检查代理是否为空(即不指向一个函数)。 

 

       要调用 Process() 函数,我们需要声明一个与代理相匹配的记录函数,然后创建代理的实例,以指向该函数。然后,将此代理传递给 Process() 函数。 

 

class Test
{
static void Logger(string s) 

{
Console.WriteLine(s);
} 

public static void Main()
{
MyClass myClass = new MyClass(); 

MyClass.LogHandler lh = new MyClass.LogHandler(Logger); 

myClass.Process(lh);
}
} 

 

       Logger() 函数是一个我们要从 Process() 函数中调用的函数,我们对它进行了声明,使其与代理相匹配。在 Main() 中,我们创建代理的一个实例,然后将该函数传递给代理构造函数,使其指向该函数。最后,我们将代理传递给 Process() 函数,该函数接着调用 Logger() 函数。 

 

       如果您习惯于使用 C++ 语言,您可能会认为代理很像函数指针,这种想法非常接近于事实。但是,代理并不“仅仅”是函数指针,它还提供了其它多种功能。 

 

传递状态 (Passing State) 

 

       在上面的简单示例中,Logger() 函数仅仅是输出些字符串。一个不同的函数可能把信息记录到文件中,但是要进行这种操作,该函数需要知道把信息写道什么文件中。 

 

       对于 Win32® 而言,当您传递函数指针时,可随之传递状态。但是对于 C#,这就没有必要了,因为代理既可指向静态函数,“也”可指向成员函数。以下是一个有关如何指向成员函数的示例: 

class FileLogger
{
FileStream fileStream;
StreamWriter streamWriter; 

public FileLogger(string filename)
{
fileStream = new FileStream(filename, FileMode.Create);
streamWriter = new StreamWriter(fileStream);
} 

public void Logger(string s)
{
streamWriter.WriteLine(s);
} 

public void Close()
{
streamWriter.Close();
fileStream.Close();
}
} 

class Test
{
public static void Main()
{
FileLogger fl = new FileLogger(“process.log”); 

MyClass myClass = new MyClass(); 

MyClass.LogHandler lh = new MyClass.LogHandler(fl.Logger); 

myClass.Process(lh);
fl.Close();
}
} 

 

       FileLogger 类仅封装文件。我们修改了Main()以使代理指向 FileLogger 的 fl 实例的 Logger() 函数。当从 Process() 中激活此代理时,将会调用成员函数并把字符串记录到相应的文件中。 

 

       其优点在于,我们不必更改 Process() 函数 -对代理来说代码都是相同的,无论引用的是静态函数还是成员函数。 



多播 (Multicasting) 


       虽然指向成员函数的功能已让人感到满意,但利用代理,您还可以巧妙地完成其它一些任务。在 C# 中,代理是“多播”的,这表示它们可同时指向一个以上的函数(即基于 System.MulticastDelegate 类型)。多播代理将维护一个函数列表。当调用该代理时,将会调用列表中的所有函数。我们可以添加第一个示例中的记录函数,然后调用这两个代理。要将两个代 理组合起来,可使用 Delegate.Combine() 函数。其代码如下: 

MyClass.LogHandler lh = (MyClass.LogHandler)
Delegate.Combine(new Delegate[]
{new MyClass.LogHandler(Logger),
new MyClass.LogHandler(fl.Logger)}); 

 

       啊呀,真的是很难看!幸好 C# 提供了一种更好的语法,而不用将以上语法强加给用户。无需调用 Delegate.Combine(),仅使用 += 即可组合这两个代理: 

MyClass.LogHandler lh = null;
lh += new MyClass.LogHandler(Logger);
lh += new MyClass.LogHandler(fl.Logger); 

 

       这样就简洁多了。要从多播代理中删除一个代理,可调用 Delegate.Remove() 或使用 -= 运算符(我知道自己会用哪一个)。 


       当你调用多播代理时,就会按出现顺序对调用列表中的代理进行同步调用。如果此过程中出现了错误,执行过程即被中断。 


       如果您想更严格地控制调用顺序(例如要进行万无一失的调用),则可以从代理中获取调用列表,然后自行调用这些函数。以下是一个示例: 

foreach (LogHandler logHandler in lh.GetInvocationList())
{
try
{
logHandler(message);
}
catch (Exception e)
{
// 在这里处理异常情况吗?
}
} 

 

       代码只是将每次调用包装在一个 try-catch 对中,这样在一个调用处理(handler)中引发的异常就不会妨碍对其它调用处理(handler)的激活,文章出处【狗刨学习网】。 

 

事件 (Events) 

 

       我们已经对代理进行了较长时间的讨论,现在该谈一谈事件了。一个显而易见的问题就是:“既然我们已经有了代理,为什么还需要事件?” 

 

       回答这个问题的最好方法就是考虑用户界面对象所发生的事件。例如,一个按钮可能有公共的“Click”代理。我们可将一个函数挂接到该代理上,这样当单击此按钮时,就可以调用该代理。例如: 

Button.Click = new Button.ClickHandler(ClickFunction); 

它表示当单击此按钮时,将调用 ClickFunction()。 

 

小测验:上述代码是否存在问题?我们忘记了什么? 


       答案是,我们忘记使用 += 而直接分配了代理。这表示其它任何挂接到“Button.Click”的代理现在都将解除挂接。“Button.Click”应该是公共的,以便其它对象 可以对其进行访问,因此上述情况将无法避免。同样,要删除代理,用户可能会编写以下代码:
Button.Click = null;
这将删除所有代理。 

 

       这些情形极其糟糕,因为在许多情况下只挂接了一个代理,问题不会明显地表现为bug。随后,当挂接了另一个代理时,事情就糟了! 

 

       事件在代理模型上添加了一层保护。这里有一个支持事件的对象例子: 

public class MyObject
{
public delegate void ClickHandler(object sender, EventArgs e);
public event ClickHandler Click; 

protected void OnClick()
{
if (Click != null)
Click(this, null);
}
} 

 

       ClickHandler 代理使用事件代理的标准模式来定义事件的签名。它以handler的名字结尾,带有两个参数。第一个参数是发送此事件的对象,第二个参数用于传递伴随事件 发生的信息。本例中没有要传递的信息,因此直接使用 EventArgs;但是如果有数据要传递,则使用从 EventArgs 派生的类(例如 MouseEventArgs)。 

 

       “Click”事件的声明做两件事情:首先,它声明一个名为“Click”的代理成员变量,在类的内部使用。其次,它声明一个名为“Click”的事件,该事件可按照常规访问规则从类的外部进行使用(在此例中,事件为公共事件)。 


       一个像OnClick()这样的函数通常包含进去以便该类型或从该类型的派生类型可以触发事件。由于“Click”是代理,您将会注意到,用来触发事件的代码与代理的代码相同。 

 

       与代理类似,我们使用 += 和 -= 来挂接或解除事件挂接,但与代理不同的是,仅可对事件执行这些操作。这可确保不会发生先前所讨论的两种错误。 

 

       使用事件是很简单的事情。 

class Test
{
static void ClickFunction(object sender, EventArgs args)
{
// process the event here.
}
public static void Main()
{
MyObject myObject = new MyObject(); 

myObject.Click += new MyObject.ClickHandler(ClickFunction);
}
} 

 

       我们创建一个与代理签名相匹配的静态函数或成员函数,然后用 += 向事件中添加代理的一个新实例。 

 

 

【ROS】usb_cam相机标定 1. 唠叨两句 当我们要用相机做测量用途时,就需要做相机标定了,不然得到的计算结果会有很大误差,标定的内容包括三部分:内参,外参还有畸变参数。所以标定的过程就是要求得上面这些参数。 以前弄这个事估计挺麻烦,需要做实验和计算才能得到,现在通过ros的开源包几分钟就能完成相机标定,感激! 具体的内外参和畸变系数的说明,可以看看Reference里面的第一个链接,写得很详细。 2. 准备工作 要准备三样东西: usb_cam的ROS启动包 相机标定的ROS包 还有一个用于标定的棋盘格 1)usb_cam启动包 阅读详情

相关推荐

【阿里云大模型高级工程师ACP习题集】2.5 优化RAG应用提升问答准确度(⭐️⭐️⭐️ 重点章节!!!)

【摘要】这是我精心整理出对应的习题集,里面足足有 30 道题目,从基础概念到深度拓展,全方位覆盖章节重点、难点。不管你是想检验自己的学习成果,还是想针对薄弱环节进行强化训练,它都能完美适配!

davidkorhenn的博客 1107

Unity 代理模式(实例详解)

在Unity游戏开发中,代理模式(Proxy Design Pattern)用于为另一个对象提供一个代理以控制对这个对象的访问。这些例子展示了如何在Unity中使用代理模式来解决资源管理、网络请求、性能优化、权限控制以及热更新等场景下的问题。每个代理类都封装了一个真实对象,并提供了额外的功能或控制层。

qqrrjj2011的博客 2287

Nuclei漏洞扫描:从零到精通的Windows实战指南

本文详细介绍了Nuclei漏洞扫描工具在Windows平台上的安装与使用教程,从基础安装到高级实战技巧全面覆盖。通过具体案例展示如何利用Nuclei的模板库快速检测常见漏洞,并提供自定义POC开发指南,帮助安全从业者高效开展漏洞扫描工作。

weixin_28683689的博客 250

Unity/C#------委托与事件(一篇文章彻底搞懂...)

从委托开始介绍到事件 从完整Event声明格式 到简洁的声明格式 到UnityEvent...

leikang111的博客 3290

海康视觉脚本开发全流程解析

本文详细解析了海康机器视觉平台(VM)中脚本模块的开发全流程。从创建第一个脚本模块入手,深入讲解了输入参数、输出参数与内部变量的定义与区别,并提供了C#脚本编写、公用函数调用、代码结构组织以及编译调试的实用指南。旨在帮助开发者掌握海康视觉脚本开发的核心技巧,高效实现复杂的自定义视觉逻辑处理。

beer8的博客 602

图像算法中的 Blob 分析

在计算机视觉中,Blob 可以理解为在图像中具有相似性质(如颜色、亮度等)的像素群体。Blob 通常用作基本单元,在图像分析和处理任务中能够提取出有意义的特征。

m0_44975814的博客 2483

Unity委托,事件(抄录)

委托,事件

Evan8的博客 2209

PLSQL Developer安装详细步骤

一、下载安装PLSQL Developer(plsql安装百度也有步骤) 官网下载地址:https://www.allroundautomations.com/registered-plsqldev/ 1、网上自己下载适合自己电脑的安装包(32或64),并解压。 2、打开解压的文件夹,得到以下三个文件(分别是汉化工具,PLSQL安装包、激活码),双击安装,如下图: 3、安装界面,点击next,进入下一步,如图: 4、安装协议界面,此处必须选择“I accept the terms in

Gorden的博客 11万+

Unity---委托与事件

快速掌握 unity委托+事件

学海无涯 3499

6-2 GPU GART 绑定机制与 TLB 失效

本文详细解析了AMD GPU的GART(Graphics Address Remapping Table)绑定机制实现。主要内容包括: 绑定流程:从ttm_tt_bind()到硬件PTE更新的完整调用链,重点分析amdgpu_gart_bind()函数实现。 关键函数: amdgpu_gart_bind():执行安全检查、记录映射关系、更新页表等操作 amdgpu_gart_map():将CPU页映射为多个GPU页并填充PTE amdgpu_gmc_set_pte_pde():处理硬件特定的PTE格式 内存

图形/计算GPU的驱动与虚拟化技术分享园地 2655

华为OD机试真题-国际移动用户识别码(IMSI)匹配

华为OD机试双机位C卷 国际移动用户识别码(IMSI)匹配 , 提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解。华为OD机试 - 国际移动用户识别码(IMSI)匹配

qq_45776114的博客 4927

Unity3d C# 广播消息 事件代理与委托

广播与消息 函数原型: public void ReceiveBroadcastMessage (string methodName, object value); public void SendMessage (string methodName, object value) public void SendMessageUpwards (string method

he_wen_jian的专栏 7765

杰理可视化SDK开发-杰理AC1123N芯片SDK开发笔记合集

该文档主要描述 AC112N开发相关的使用说明和注意事项,收集并持续更新开发调试过程中的相关疑问和解答,对SDK介绍文档做一个补充说明。写作人:李永奉,参考项目MD-026H; AC112N-SDK项目帮助文档在杰理开发者平台(JL DP)'帮助'处进入,如本文档有与后续帮助文档或工具注释说明冲突,以后者为标准。

李永奉的博客 182

unity3d学习笔记(十八)--利用C#的代理和事件结合NGUI的按钮实现施放

本系列文章由Aimar_Johnny编写,欢迎转载,转载请标明出处,谢谢。 http://blog.youkuaiyun.com/lzhq1982/article/details/12999381 对C#还不是很熟,在学习的过程中了解到C#有种代理和事件的机制很方便,之前用cocos2d的时候也用过代理,虽然此代理非彼代理,但他们的作用有相似之处,都是触发者只是告知事件,并不调用相

MoMo_KUA_1的专栏 1103

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

unity3d学习笔记(十八)--利用C#的代理和事件结合NGUI的按钮实现施放技能

对C#还不是很熟,在学习的过程中了解到C#有种代理和事件的机制很方便,之前用cocos2d的时候也用过代理,虽然此代理非彼代理,但他们的作用有相似之处,都是触发者只是告知事件,并不调用相关类和方法实现,而是由代理方法实现,可能有些难懂,下面我用之前的demo中英雄施放技能这里做个试验。 本篇涉及三个知识点,一个是最重要的代理,一个是NGUI的按钮,一个是施放技能特效。 1、NGUI制作

lzhq1982的专栏 8566

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Unity3D学习之如何利用C#实现代理模式

欢迎来到unity学习、unity培训、unity企业培训教育专区,这里有很多U3D资源、U3D培训视频、U3D教程、U3D常见问题、U3D项目源码,我们致力于打造业内unity3d培训、学习第一品牌。         C#语言是支持代理的,并且代理是非常的好用的一种方式。简单的来说就是 你委托朋友帮你做一件事情,当你的朋友做完以后会告诉你。 代码中一般A、B、C、D若干类同时委托E类来做一件事

Qst_Baron的专栏 627

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

Unity3D学习笔记(三) C#代码(1)

Unity3D开发常见的代码要求规范

daining424的博客 912

Unity3D AI C# Scripting 學習筆記-2 ( 玩家, NPC 探索代理)

初學 Unity 引擎, 将 Udemy 的 Visual Scripting 課程內容以 C# 的編程方式重現

m0_66934693的博客 229

学习|Unity3d的导航实现循环线路移动

本文长度为2703字,预计阅读7分钟前言前阵子用Unity3d做的那个模拟收费的动画,主要是模拟了一个项目中的场景,让人看到更直观一些,最主要的目的还是最近在学习Unity3d,直接以实...

Vaccae的博客 2242

Unity3D ARPG C# Scripting 學習筆記-2 ( NPC 巡逻, 自制编辑器 )

【【白嫖.可商用】Vroid模型分享第八期!之前的方式也是先设置地标, 但是NPC的抵达该点后的下一个点是随机定的。各有各的优点, 之后正式开发的游戏应该会试著结合两者的功能。然后再透过转向和提前抵达的速度来造成与目标点的偏移距离。也设置了两种移动动画, 同样是抵达地点后再随机变更。第三章节主要是设置NPC闲晃的路径和动作AI,除了先前提到的随机变更动画速度和类型以外,也设置了 NPC 随机往反方向移动的功能。

m0_66934693的博客 299

Unity C# 脚本教程

欢迎来到Unity3D C#脚本教程系列。在这个系列中,您将学习通过C#和unity创建游戏。编写脚本是创造unity3d游戏引擎游戏中最重要的过程之一。 如果从底层开始学习C#,您就可以在unity创建完美的游戏。 C#代码给你很多对unity的控制,你可以使用它在游戏中获得任何想要的。 如果你正着手于unity的游戏开发的脚本,你应该开始学习C#而非JavaScript。 C#允许你以更有组织

编辑编辑器 6270

转入Unity3D开发 一些记忆

这个月转入Unity3D的开发,兼顾客服端和服务器的开发所以现在需要熟悉客户端尤其是Unity3D利器的开发过程,就以现在的感觉做以下的总结:   1.首先Unity3D开发主要是用的c#的脚本,至少我们是这样用的,当然也可以用js其他之类的。 2.之前对c#一无所知,有c++的经验所以学习起来还是很快的,在Unity3D里面它帮我们管理了很多游戏资源,特别是UI之类的它会直接提供给我们使用

gumingyaotangwei 的专栏 2837

C# 和 Unity 2021 游戏开发学习手册(一)

原文:zh.annas-archive.org/md5/D5230158773728FED97C67760D6D7EA0 译者:飞龙 协议:CC BY-NC-SA 4.0 前言 Unity 是世界上最受欢迎的游戏引擎之一,迎合业余爱好者、专业 AAA 工作室和电影制作公司。虽然以其用作 3D 工具而闻名,但 Unity 拥有一系列专门功能,支持从 2D 游戏和虚拟现实到后期制作和跨平台发布的一切。 开发人员喜欢它的拖放界面和内置功能,但正是编写自定义 C#脚本以实现行为和游戏机制的能力真正使 Unity

龙哥盟 1900

Unity3d学习日记 (2)C#脚本编写优化以及全自动敌人脚本实现实战

需求分析

weixin_50340097的博客 3376

Android游戏开发常见知识合集(Unity3D)

Android游戏开发常见知识合集(Unity3D)

我与岁月的森林的博客 1508
上一篇: 摄像机属性及妙用详解
下一篇: Unity3D学习之如何利用C#实现代理模式
Qst_Baron
博客等级 码龄12年 15粉丝 2原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值