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);
}
} 

 

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

 

 

手机移动端-纯js浏览器h5调用摄像头扫描识别解析 条形码+二维码 一、场景 h5原生js 浏览器端解决识别二维码条形码功能; 不借助Hbuilder.需要自己打包成APP,比如用Hbuilder打包,浏览器端项目h5无打包成app部署X不采用 不借助微信扫一扫,调用微信js-jdk有多麻烦,还要认证服务号,也不适用其它浏览器打开X不采用 二、思路 1.思路一:input(相机拍照)+条形码或二维码识别js支持库 通过h5-input[camera]调用相机进行拍照成图片,通过条形码等识别库解析出数据; <input @cha... 阅读详情

相关推荐

Lenovo 拯救者15ISK硬件升级实战:从内存到固态硬盘的全面优化

本文详细介绍了为联想拯救者15ISK笔记本电脑进行硬件升级的完整实战指南。通过评估升级可行性,指导如何挑选兼容的内存条与NVMe固态硬盘,并提供详细的拆机安装步骤与系统安装避坑技巧。升级后,笔记本的开机速度、软件加载及多任务处理能力获得飞跃式提升,让老旧设备重获新生。

weixin_29310631的博客 557

Unity 代理模式(实例详解)

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

qqrrjj2011的博客 2287

车载测试实战:adb logcat日志高效抓取与问题定位技巧

本文详细介绍了车载测试中adb logcat日志的高效抓取与问题定位技巧。作为车载测试的“第一现场”,adb logcat能实时、精准地抓取系统与应用日志,是定位应用崩溃、ANR及功能异常等问题的关键工具。文章从环境搭建、核心命令组合拳到实战分析与自动化脚本,提供了完整的操作指南,帮助测试人员快速掌握这一必备技能,大幅提升问题排查效率。

ii567的博客 1039

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

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

leikang111的博客 3290

HAL库移植实战:解决‘HAL_StatusTypeDef‘未定义报错的3个关键步骤

本文针对STM32开发中从标准库向HAL库移植时常见的'HAL_StatusTypeDef'未定义报错,提供了三个关键解决步骤:首先确保正确包含头文件入口,其次检查并配置模块使能宏,最后注意避免与标准库的同名结构体混用。文章通过实战案例解析了HAL库的模块化设计理念,帮助开发者高效解决混合编程中的编译问题。

book8的博客 207

ubuntu打实时内核补丁教程以及安装后显卡驱动问题解决方法

在ubuntu20.04上安装成功,亲测有效 目录ubuntu打实时内核补丁教程1、下载实时内核2、解压和打补丁(patch)3、安装依赖和编译安装4、修改一些文件,便于之后切换内核5、重启电脑实时内核版本下安装nvidia显卡驱动的问题1、先切换回之前的内核(非实时)版本2、重装之前内核(非实时)版本下的显卡驱动3、切换回实时内核(按照上面的步骤)4、在实时内核下安装显卡驱动 ubuntu打实时内核补丁教程 安装目标系统:ubuntu20.04 电脑配置:i9,2080ti 1、下载实时内核 打开终端,输

weixin_39275295的博客 7996

Unity委托,事件(抄录)

委托,事件

Evan8的博客 2209

Labview数据存储与读取——TDMS文件的创建与写入

Labview数据存储与读取——TDMS文件的创建与写入 你好,这是我在自学Labview编写软件过程中使用的一些功能。我在存储采集卡数据时,通过阅读大量他人的程序,发现TDM及TDMS文件十分适合波形数据的记录,TDMS文件比TDM文件在存储动态类型数据时读写速度更快,而且TDMS 文件没有容量限制,适合存储数据量庞大的测试数据。 前言少叙,书归正传 这一篇博客,说明一下如何使用基本的TDMS功能实现数据文件的存储。 所需要的控件如上图所示,在程序框图——编程——文件I\O——TDMS 中,写入TDMS

滑板小帅程序开发 2万+

Unity---委托与事件

快速掌握 unity委托+事件

学海无涯 3499

【知识图谱】neo4j安装与配置_社区版_2025(附完整安装软件包)

(经历过各种版本NEO4J,遇见杂七杂八的各种问题,也看过非常多很好的教程,特此来分享一下,为大家排排坑。

知识靠谱的博客 2万+

④ Django创建用户中心应用users,扩展用户信息

本章配套视频教程 Django创建用户中心应用users,扩展用户数据 在settings.py文件中配置项目 1、语言配置:LANGUAGE_CODE = 'zh-hans’ 2、时区配置:TIME_ZONE = 'Asia\Shanghai’ 3、模板路径配置:‘DIRS’: [os.path.join(BASE_DIR, ‘templates’)], 并创建templates文件

轻编程的博客 673

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

2024年11月架构设计师案例分析真题回顾,附参考答案、解析及所涉知识点(二)

软考高级系统架构设计师考试包含三个科目:信息系统综合知识、案例分析和系统架构设计论文。考试形式为机考。本文主要回顾2024年下半年(2024-11-10)系统架构设计师考试上午第二科案例分析的题目,同时附带参考解答、解析和所涉知识点。

一几文的编程学习笔记。 1661

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

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

MoMo_KUA_1的专栏 1103

STM32F407中文手册

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

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

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

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

lzhq1982的专栏 8566

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

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

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

Qst_Baron的专栏 627

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、付费专栏及课程。

余额充值