初中化学。第20题,只有第一个小空。求详解!!!!

这是我看到的一片比较完整的讲自定义窗口,自定义组件的教程,讲的比较详细,特意转过来给大家分享一下

原文出处:微信公众号克森空间

利用学到的东西制作自己的工具(自定义的窗口、Inspector、菜单等等)。

关于 Unity 内置属性可以从到官方文档中查询,本篇文章只介绍一些常用的内置属性,如下图所示:
接下来进行项目设置,创建一个空的 Unity 工程,名字由你来定,文件夹的层级关系如下:
目前还不需要Editor文件夹,但是先创建,往后的教程中会用到。然后再 Scripts 文件夹中创建一个新的 C# 脚本,命名为“People”,双击打开该脚本。

AddComponentMenu 属性允许将一个脚本添加到 Component 菜单中,然后你便可以通过 Component ->(你设置的名字)为一个选中的游戏对象创建该脚本,如下所示:

RequireComponent()属性会自动帮你添加你需要的组件,如果已经存在则不再重复添加,且不能移除,如下所示:
提示:经过测试,我发现一个问题,如果脚本已经挂在物体身上,然后再修改脚本,为添加 RequireComponent 属性的话,完全不起作用,因此建议大家在用此属性的时候要注意。

ContextMenu()属性允许添加一个命令到该组件上,你可以通过右键或者点击设置图标来调用到它(一般用于函数),且是在非运行状态下执行该函数,如下所示:

HelpURL()提供一个自定义的文档链接,点击组件上的文档图标既能打开到你指定的链接,如下所示:
提示:填写链接时,一定要写上 http:// 或者 https://,否则将无任何反应。

    用于将一个值指定在一定的范围内,并在Inspector面板中为其添加滑块;

2.第10行,我们使用了 [Multiline(5)] 为其 name 属性添加了5行输入,如上图所示,明显输入框变大了。

3.第12行,我们使用了 [Range(-2,2)] 为其 age 属性指定了一个(-2,2)的范围,并且为其添加了一个滑块,如上图所示。

Tooptip()属性用于在 Inspector 面板中,当鼠标停留在设置了Tooptip()的属性添加指定的提示;Space()用于为在 Inspector 面板两属性之间添加指定的距离,如下所示:


还是使用上一篇的 Unity 工程,然后在 Scripts 文件夹里创建一个新的 C# 脚本,命名为“Player”,然后双击打开脚本,然后为其添加如下代码:
Player 类记录了 Player 的一些基础信息,例如:ID、名字、背景故事、生命值、伤害等等。

自定义 Inspector 属性面板的一些基础知识,和注意事项如下图所示:

接下来开始制作的我们自己的 Inpector,对于自定义 Inpector 面板可参考下图的API:

常用的自定义 Inspector 界面布局属性

现在,请你在 Editor 文件夹中创建一个新的 C# 脚本,双击就打开该脚本,并为其添加如下代码:
Okey,接下来一一分析一下

默认的界面布局就是垂直布局,但是为了节目效果,我们还是把它写上比较好,设置元素为垂直布局需使用这对兄弟来声明:

在这对兄弟里面做的布局都是以垂直方向来排列的。
如上图所示,整个页面元素都是以垂直方向来布局的。

设置元素为水平布局需使用这对兄弟来声明:

在这对兄弟里面做的布局都是以水平方向来排列的。
由于我们在上图圈选的地方使用了 Horizontal 这对兄弟,因此在这对兄弟里的元素全是以水平方向排列。

绘制字段用到以下几个方法:

它们的规律就是方法名都是以 Field 结尾,大伙们可以根据绘制的类型选择相对应的方法。

一般括号里面的参数,第一个为绘制该字段的名字(string 类型),第二个为绘制该字段的值,如下所示:

第一个参数是滑块的名字
第二个参数是滑块要改变的值
第三和第四个参数是滑块的范围

第一个参数是设置进度条的大小,类型是一个 Rect。
第二个参数是设置显示的值,
第三个参数是设置进度条的名字

1.第一个参数,我们使用了 GUILayoutUtility.GetRect() 工具类的 GetRect()方法返回一个设置好的矩形框,在案例里我们设置了一个 50*50 大小的矩形框。

2.第二个参数,我们使用 player.health / 100.0f。那是因为进度条的最大值为1,如果不除100的话,当滑块的值为1时,进度条便填满了,因此我们想让值与进度条的比例同步,那就除100吧(语文不好,不知道解释得如何)。

EditorGUILayout.HelpBox()用于绘制一个盒子(也可以看作矩形框),然后再盒子的里面显示提示信息,从上图可知:

第一个参数是传入提示信息
第二个参数是提示信息的类型


基础篇(三):自定义窗口

在之前的项目中,找到 Editor 文件夹,然后创建一个新的 C# 脚本,命名为“MyFirstWindow”,然后双击打开脚本,添加如下代码:

以上是我们这个案例中主要用到的几个类。

如代码注释所示,利用构造函数来设置窗口的名字。比较陌生的是 titleContent属性 和 GUIContent 类,简单了解如下图所示:
这个构造函数所产生的作用如下图所示:

添加菜单栏选项 - 打开窗口


这个函数用于在菜单栏上添加一个打开该窗口的的菜单选项。比较陌生的是 [MenuItem()] 属性 和 GetWindow()函数,简单了解如下图所示:
[MenuItem()] 属性需要注意的两点(上图也有提示):
2.调用的函数必须是静态函数(static)
该函数就是用于返回一个窗口对象(就是打开一个窗口)。

绘制窗口元素需要在 OnGUI() 函数里面设计,接下来我们一一分解。
1.GUILayout.Space(10),这个有说过,让两个元素之间空十个像素之间的距离

整个代码的效果如下图所示:


好吧,似曾相识,因此不在赘述,效果如下所示:

显示当前正在编辑的场景


其实就是返回当前编辑的场景信息(也就是返回 Scene 类型参数),然后利用 name 属性获取场景的名字,效果如下:

1.第一个参数用于设置卡槽的标题名字
2.第二个参数用于设置字段显示的物体
3.第三个参数用于设置显示的类型
4.第四个参数用于设置是否允许指定场景中的物件


好的,这段代码我们也介绍过了,直接上效果图:


其实很简单,不外乎就是添加一个按钮呗。在我们的代码中,用了一个 if 判断语句来判断,当我们点击该按钮时所触发的事件(该函数的返回值是一个 bolol 类型),在代码中克森也上好备注了,因此也没有什么难的,直接上效果图:
其实这个函数所做的事情也很简单,就是把我们设置好的一些参数保存到一个文本文件(.txt文件)上,仅此而已。

3.然后把设置好的各个参数写入文件中

还不了解 C# 文件操作的朋友,是时候返回去补补了,API 链接如下:


然后你便能在 Assets 文件夹看到如下图所示信息:


其实这个函数所做的事情跟上面那个函数做的事情一样一样的,不外乎就对了一行代码,而这行代码便是获得游戏屏幕截图,仅此而已,通过下面 API 去了解:
具体操作和上面一样一样的,只不过多了一样图片,仅此而已,如下图所示:
好吧,至此我们的这篇文章就结束了。


由于太久不更新,之前的项目不知道跑哪儿去了。让我们重新创建一个新的项目,命名为“MyHandles”。然后创建三个文件夹,如下图所示:
接下来在Scripts文件夹中,创建一个C#脚本,并命名为“MyHandles”;然后在Editor文件夹中再创建一个C#脚本,命名为“HandlesInspector”;然后在将下面的小图标保存到Img文件夹中:
好了准备工作就绪,开始码了个码。

在这篇教程中,我们主要用到 Handles 这个类,一下是该类的基本介绍,克森会挑出几个比较常用的属性和方法来制作一下简单的东西,其它属性和方法大伙们可以自行去尝试尝试:

首先打开我们的 MyHandles.cs 脚本,为其添加一个变量:
将这两个脚本保存,回到Unity中创建一个空物体,并为其添加 MyHandles.cs 脚本:
此时我们观察场景,除了场景中出了 “MyHandles” 几个字外,似乎啥事儿也没发生,不急,让我们来调整调整 Area Radius 参数的值,便能看到如下效果:
代码很简单,注释也给大家弄上了,相信大家都能看懂吧。还是不太懂的可以多看看API:
作用:这个东西是不是有点类型于碰撞体的那个框框啊,这玩意多用于制作AI,用于判断和指定UI影响范围用的。

这段代码呢也不难于理解,就是参数多了点
PS:由于中文版的介绍不全,所以补了一张官方的API。

作用:多用于绘制一些自定义的操作,比如Unity的粒子系统就用到了好多自定义的操作柄,比如粒子系统的Shape参数就用到了该函数的第五个参数来绘制:

回到场景中,此时大伙们会碰到这样的问题:
别担心,那是因为你没有设置 nodePoints 属性,所有该函数访问到一个空的数组,因此便报出了老司机错误。如下图所示便OK:
这段代码简单了吧,也就两个参数,如果还是不清楚的小伙伴可以多尝试尝试。
作用:这个可以用在AI上面,然后为每一个AI添加一个位置操作柄,这样好像看上去方便不少吧?

同样的,会出现上面类似的错误,甚至更加严重,Scene视图直接白屏!!使用同样的解决方法即可,如下所示:

这段代码同样很简单了吧,也是两个参数,如果还是不清楚的小伙伴可以多尝试尝试。
做一个操作,看看大伙们能不能看懂我想表达的意思:
是不是感觉像是静止一般,一动不动的呢?下面修改一下代码:


此时,你会看到如下的错误,不要慌张,我们只有越到错误,解决多了,那以后越到错误就不是什么可怕的事情了:
相信很多人都知道这个是什么错误吧,那是因为由三维向量转为四元素W的值不能为0,因此我们只要把W设置为1即可,如下所示:
这个操作呢,主要是帮大家找出一些开发过程中容易遗漏的错误,还有一个目的就是让坐标轴跟随着旋转而旋转(因为第二个参数是位置操作柄的旋转方向嘛,我把它改为了我们设置好的旋转方向,因此位置操作柄便能跟随着我们的旋转而旋转了)。

此时回到场景中便能看到如下所示:
这段代码呢,也很简单,可能有点不明白的也就是 Mathf.Repeat()函数,这个简单,看下图便能明白:
其实这样做的原因大伙们都知道,就是为了防止下标越界。

其实也很容易理解,就是当showNodeHandles为false时便不执行 if 代码块里的代码,因此便无法绘制出位置操作柄和旋转操作柄咯,最终的效果如下:

回到场景便能看到如下图所示的界面:
这段代码呢,其实也很简单,不过是运用了两对函数。

里面的逻辑代码也很简单,那就是绘制一个按钮,当我点击时让 MyHandles.shoNodeHandles的值取反(也就是原来为true,点击后取反,便为false)。

补充:在第一对函数里得操作和自定义窗口里得操作几乎相同,大家可以参考下面得API去尝试尝试:


这个插件就用到了今天我们学到的东西制作而成的:
好了,差不多就介绍到这里吧


在之前的项目或者新建的项目中创建如下目录结构:


如果是新的项目,只需创建Scripts和Gizmos就好。


由上图可知,Gizmos是用于在场景视图可视化调试或辅助设置用的。

需要注意的是所以Gizmos的绘制必须在脚本的OnDrawGizmos或OnDrawGizmosSelected里编写,因此我们的第一步便是在脚本中添加这两个函数。

在Scripts文件夹中创建一个C#脚本,命名为:“MyGizmos”,双击打开脚本,码入如下代码:
咦,感觉不对啊,感觉不是每一帧都在调用啊!克森做了个测试,如果你在Scene视图下不做任何错误(鼠标滑动也不能调用这两个函数),这两个函数都没有调用(看来官方文档说得不完全啊!!)。

不管了,总之大伙们知道是这么一回事儿就行了。

PS:必须于Scene视图下,于Game视图下不起作用。

接下来为“MyGizmos.cs”脚本添加如下代码:
好,现在回到场景视图下,如下图所示操作:
哦豁,我们的线框球体便出来了,是不是很简单啊。

该函数的第一个参数是该线框球体的中心点位置,它是一个Vector3类型。

第二个参数是该线框球体的半径大小,它是一个float类型。

接下为我们的脚本添加如下代码:
好,现在回到场景视图下,如下图所示操作:
哦豁,我们的线条便出来了,是不是很简单啊。

上图已经解释得非常清楚,两个参数表示:从from起点到to位置绘制一条线。

因此第一个参数就是起点的位置,第二个参数就是指定的位置。
上面代码的意思就是当前的位置朝 Z-轴 正方向根据 size 的值扩大。

接下来为我们的脚本“MyGizmos.cs”添加如下代码:
好,现在回到场景视图下,如下图所示操作:
如上图所示,我们通过for循环调用Gizmos.绘制出了5个实心球体。

由上图可知。第一个参数是绘制该球体的中心点的位置,第二个参数是该球体的半径。

因此在我们的代码中,利用for循环依据nodePoints参数创建多个球体,在上面的案例中克森创建了5个球体,设置它们的半径为0.5(大伙们也可以添加一个参数,进行动态操作半径值)。

由于绘制的东西都是一个色,不好辨别,大伙们可以添加如下代码:
我们的球体变成了蓝色,我们的线条编程了红色,未设置的线框球体还是默认的白色。

PS:Gizmos.color = Color.blue,如果后续没有重新指定绘制的颜色,则使用最后一次设置的颜色。

接下来为我们的脚本“MyGizmos.cs”添加如下代码:
回到场景中看看有什么效果:
好了,从上图中大家也知道我们添加的这段代码的意思了吧。很简单,就是将这些球体给连接起来。


尴尬了,发现最后要将的东西已经在前面暴露出来了。。。就是下图的这个东西:
相信这个东西大伙们都知道怎么设置吧,不过为了该文章的完整性,我们还是来操作一遍:


好了,这个是手动设置的,那么代码中又是如何设置的呢?

回到场景中,看看有什么效果发生。

咦,没有什么事情发生啊!!!
哦,原来是找不到图片资源。如上图所示,这就是为什么文章的开头让大伙们创建 Gizmos 文件夹的原因。现在将一张你喜欢的图标,命名为:“icon.jpg”放入Gizmos文件夹中。

PS:图片的命名一定要与代码中的第二个参数的名字一样。



创建一个新的工程或者用上一篇的工程都可以(克森是新建的工程),然后在Scripts文件夹中创建两个C#脚本,分别命名为:“Persion.cs”和“ShowPersionInfo.cs”,如下图所示:

首先,打开我们得“Persion.cs”脚本,为其添加如下代码:
这段代码不用解释了吧,就是一个普通得类和枚举。接下来为我们的“ShowPersionInfo.cs”脚本添加如下代码:
为什么要这样呢?相信大伙们都知道,要想给一个游戏对象挂上脚本,那么该脚本就必须继承自 MonoBehaviour 。大伙们可以将“Persion.cs”挂到游戏对象上,便会出现如下图所示:


所以“ShowPersionInfo.cs”仅仅就是一个辅助类,作用就是将我们的“Persion.cs”能挂到游戏对象上。

好了,接下来让我们创建一个空的游戏对象,并且命名为“Persion”,然后为其添加“ShowPersionInfo.cs”脚本:
这什么都没有啊!!原来,我们漏掉了一段代码,接下来让我们为其补上:
原来呀,要想将一个普通的类里的属性在Inspector面板中显示出来,那么必须将这个普通的类序列化。

好了,让我们回到 Unity 中,看看发生了什么变化。

好,让我们简单的了解一下,什么是序列化,如下图所示:
(图片来源于百度百科)
简单的理解就是,序列化类的时候是从属性读取值以某种格式保存下来,将其传输到另一个地方去。那么呢,这个过程是交给Unity引擎来实现的,简单的了解就行了(也就是会用就行了)。

接下来就是本篇教程的核心了!!!

接下来让我们来测试一下这些方法传入的参数都是做什么的,为我们的脚本添加如下代码:
好,现在回到Unity看看测试的数据:
从上面的数据可以看出如下几点:

3.position参数指的是需要在Inspector面板中绘制的区域信息,可以从下面两张图中简单的了解一下:


PS:为了测试,注释了一些代码,并且添加了一个2D刚体组件。

对了还有一个地方遗漏掉了,那就是在Inspector面板中的一行高度为 16 。我们可以从下图中得知。
好了,接下来就让我们来绘制我们Persion的属性吧。我们的目标如下图所示:
下面看一看我们的分析图:
好了,接下来就开始码我们的代码,打开“PersionPropertiesDrawer.cs”,为其添加如下代码:
上面的代码呢,都有分析过了。也许会有一些小伙伴在两个地方上头晕,也就是【获取对应的序列化属性】和【绘制属性】这两个地方上弄不明白。其实很简单,从下面两张图中便可理解:
好了,让我们回到Unity中,看看我们的效果实现了没:
好的,非常完美的实现了。

至此,该篇文章就已经弄完了。


创建一个新的工程或者用上一篇的工程都可以(克森用的是原来的工程),然后在Scripts文件夹中创建两个C#脚本,分别命名为:“ReadOnlyAttribute.cs”和“Test.cs”,如下图所示:

上图的代码在上一篇都有讲解过,因此这里不再做过多的赘述。

在上面的代码中,我们使用到了一个名为“SerializedPropertyType”的枚举,它存放的是序列化属性的类型,它包含的类型很多,但是在该篇文章中我们只使用到了这几个,感兴趣的同学看可以去尝试其它类型。

我们使用该枚举为value获取相对应类型的值,然后使用一个Label在Inspector面板中绘制出来(\t为制表符,为了美化显示)。

好了,接下来打开我们的“Test.cs”脚本,添加如下代码:


现在,让我们回到Unity中查看一下效果:
这个。。。是不是很简单呀。接下来让我们制作一个带有参数的。

好了,接下来开始测试,让我们为我们的“Test.cs”脚本添加如下代码:
从上图可知,其实[ReadOnly(参数)] 传入的参数对应的就是我们ReadOnlyAttribute类的构造函数需要传入的参数。

好了,接下来让我们回到Unity中查看一下效果:
好了,大伙们可以看到,值已经完美的传入了,效果并不是完美期望的那样。但是我们的 My Int 的 Apha 值起作用了。

克森对于这个Bug弄了一个晚上,最后发现原来是Unity5.x出的BUG,总之克森今晚把Unity5.x版本都试得差不多了,还是一个鸟样,最后Unity4.6版本妥妥得实现了我们想要得效果,下面有两张图,一张是克森试过得版本,一张是Unity4.6实现得效果图:

好了,今天的教程就到这里吧


创建一个新的工程或者用上一篇的工程都可以(克森用的是原来的工程,因为这一篇的内容和上一篇的内容很类似),然后在Scripts文件夹中创建两个C#脚本,分别命名为:“DrawerImageAttribute.cs”和“Test.cs”,如下图所示:


上图的代码除了红色框框里的东西,其它的在上一篇都有讲解过,因此这里不再做过多的赘述。

好了,让我们来分析分析 DecoratorDrawer 类是个什么东西,首先从字面上的意思就是:装饰绘制者。意味着它是用于装饰的。接下来让我们看看它的源码:


从源码中我们知道,它其实和上一篇的PropertyDrawer类差不多,都是继承自 GUIDrawer。只不过他的 OnGUI 方法的参数比 PropertyDrawer 的 OnGUI 方法的参数好了两个,仅此而已。


上面的代码应该不难理解吧,就是判断图片是否存在,如果不存在就去Resources文件夹里读取对应的图片,然后调用 GUI.DrawTexture(position, image); 在Inspector面板中绘制该图片。

因此,接下来的操作相信大伙们都知道了吧。那就是创建Resources文件夹,然后将图片放入该文件夹中,修改相对应的名字,搞定!
接下来,让我们回到Unity中查看效果:
咦,怎么回事儿,怎么那么难看?看到这里,相信看过上一篇文教的伙计们应该知道怎么做了吧?那就是修改我们 GetHeight() 方法的返回值就行了呀。

好了,接下来打开我们的“Test.cs”脚本,添加如下代码:
现在,让我们回到Unity中查看一下效果:


这…你坑我?不急不急,克森是故意这么做的,错误见多了那就不是错误了。

好,让我们来解决这个错误。接下来为我们的“DrawerImageAttributeDrawer.cs”脚本添加如下代码:
然后回到Unity中,看看测试的数据,分析出错原因:
从上图中,我们可以看出,该脚本先调用的是 GetHeight() 方法,因此当我们在 GetHeight() 方法中使用 _attribute.height 的时候便会报空指针的错误,因为此时的 _attribute 还没有初始化,因此让我们添加如下代码:
好了,接下来回到Unity中查看效果:
Perfect,漂亮的完成了。

好了,《Unity Editor 基础篇》系列结束了!!!太棒了

}

左下角界面(0,0,0.8,0.8);左上角界面(0,0.8,0.8,0.2);右上角界面(0.8,0.8,0.2,0.2);右下角界面(0.8,0,0.2,0.8)

 效果图是在左上角、右上角、右下角界面放置了分别对应的Canvas

到这里多屏设置完成,要完成示例图的效果请继续......

其中Text即为信息,Image为背景图,注意顺序

Image里可以设置背景图

注意事项以及常见问题:

1.关于图片引入,首先将图片复制到Unity项目文件夹Assets对应的文件夹里

3.关于多页面乱入,如果相机里设置层无效,可以尝试直接暴力托动

}

我要回帖

更多关于 化学理综第一题总结 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信