﻿WEBVTT

00:00:00.865 --> 00:00:05.215
大家好，欢迎来到本期艺术家的脚本的教程视频

00:00:05.215 --> 00:00:06.850
我的名字是Sybren

00:00:06.850 --> 00:00:09.395
这一集的内容是关于Blenderer集合

00:00:10.005 --> 00:00:14.910
这些是Blenderer 2.8中引入的，取代了编号的场景层和组

00:00:17.062 --> 00:00:20.202
我没有象往常一样在Blenderer研究所录制

00:00:20.423 --> 00:00:23.408
但我现在和你们很多人一样，都在家

00:00:23.951 --> 00:00:26.776
因此，这段视频的脚本会比较少

00:00:27.505 --> 00:00:29.895
我不会有任何幻灯片展示

00:00:30.951 --> 00:00:35.061
我们将直接进入Blender，我将在那里展示一些东西

00:00:36.082 --> 00:00:40.532
所以在这里的Outliner中你可以看到我们有一个scene collection

00:00:40.801 --> 00:00:42.296
里面有一个Suzanne

00:00:42.981 --> 00:00:44.611
就象一个对象一样

00:00:44.611 --> 00:00:47.046
它有默认的集合，Collection 1

00:00:47.981 --> 00:00:51.631
所以鉴于此，这里的这个东西叫做场景集合

00:00:53.314 --> 00:00:58.174
我们来看看这个场景对象，看看能不能找到一个集合属性

00:01:02.012 --> 00:01:03.492
这里我们有Suzanne

00:01:04.327 --> 00:01:07.007
提醒一下，这里我们有方便变量

00:01:08.512 --> 00:01:14.027
所以大写的C代表bpy.context，大写的D代表bpy.data

00:01:16.156 --> 00:01:19.271
你不能在你自己的脚本中使用这些变量

00:01:19.356 --> 00:01:22.776
但你可以在控制台中使用它们来解决问题

00:01:23.706 --> 00:01:26.461
我们来看一下，输入C.scene.coll

00:01:29.551 --> 00:01:31.926
然后按Tab键，你可以看到

00:01:32.227 --> 00:01:34.587
它已经有一个collection属性了

00:01:35.755 --> 00:01:38.970
我们可以得到它的名字，叫(主集合)master collection

00:01:40.988 --> 00:01:45.258
因为它是主场景集合，它有一个属性叫objects

00:01:52.928 --> 00:01:56.823
如果你把它转换为列表，只要按向上的箭头

00:01:57.518 --> 00:02:01.068
然后输入list，并把前面的放在括号里

00:02:02.981 --> 00:02:04.811
在那里你可以看到

00:02:04.811 --> 00:02:07.491
有一个对象，Suzanne，就是这个

00:02:08.788 --> 00:02:13.098
collection.objects给出所有直接链接到集合中的对象

00:02:16.976 --> 00:02:21.111
看看当我们把Suzanne移到Collection 1中会发生什麽

00:02:22.010 --> 00:02:24.910
它仍然是间接地在场景集合里面

00:02:25.133 --> 00:02:27.373
因为它是在Collection 1里面

00:02:27.649 --> 00:02:30.519
而Collection one是在场景集合里面

00:02:30.931 --> 00:02:34.381
但是它已经不在"scene.collection.object"里面了

00:02:37.495 --> 00:02:41.105
如果你想真的什麽都有，那就看"all_objects"

00:02:44.305 --> 00:02:48.880
这就象一个神奇的视图，可以让你看到集合本身的一切

00:02:51.115 --> 00:02:54.045
所以它包含了那个对象也包含的一切

00:02:55.546 --> 00:03:00.286
但随后它也包含了集合里面的集合和集合里面的集合和

00:03:05.000 --> 00:03:07.160
而你可以看到我们有Suzanne

00:03:09.519 --> 00:03:13.924
所以像Blender集合中的很多东西都要有一个唯一的名字

00:03:14.417 --> 00:03:17.057
因为它们是以数据的形式存储的

00:03:17.945 --> 00:03:20.195
所以我们有"bpy.data"

00:03:20.735 --> 00:03:23.230
或者在控制台中的D.collection

00:03:26.033 --> 00:03:28.013
这就给了我们collection 1

00:03:28.413 --> 00:03:30.533
它不包含场景主集合

00:03:31.367 --> 00:03:33.782
但它包含了其他所有的集合

00:03:35.705 --> 00:03:36.890
所以在这里

00:03:36.890 --> 00:03:39.640
我们也可以得到D.collection['Collection 1'].objects"

00:03:42.724 --> 00:03:46.429
并将其转换为列表，看看里面都有什麽

00:03:47.583 --> 00:03:50.333
同样的，当然也有Suzanne在里面

00:03:50.373 --> 00:03:52.643
所以这已经给了你一个方法

00:03:52.643 --> 00:03:54.543
给定了一个集合的名称

00:03:55.765 --> 00:03:58.465
就可以迭代该集合中的所有对象

00:03:59.950 --> 00:04:02.610
所以，也许你想写一个输出器

00:04:02.610 --> 00:04:05.280
输出一个特定集合中的所有对象

00:04:06.596 --> 00:04:08.801
现在你知道如何访问它了

00:04:11.892 --> 00:04:13.957
我的意思是迭代这些对象

00:04:15.545 --> 00:04:19.930
让我们看看这是如何发生的，只是为了唤醒你们的记忆

00:04:20.878 --> 00:04:23.758
假设我们有一段波希米亚狂想曲

00:04:27.212 --> 00:04:30.092
在这个系列中有四首苏珊娜的作品

00:04:31.219 --> 00:04:36.179
如果我们用list.collection.object，
那麽我们就会得到所有的四个

00:04:37.537 --> 00:04:41.572
让我们看看在更复杂一点的代码中会是什麽样子

00:04:44.963 --> 00:04:47.783
你基本上会用coll=D.collection['collection 1']

00:04:56.531 --> 00:04:59.501
然后我可以输入for ob in coll.object:

00:05:05.050 --> 00:05:05.725
print(f'08 name is:{ob.name}')

00:05:13.205 --> 00:05:15.045
这是一个格式字符串

00:05:17.051 --> 00:05:18.111
真的很有用

00:05:18.777 --> 00:05:21.582
你可以在开头的引号前输入一个F

00:05:22.264 --> 00:05:26.929
然后在大括号内，你可以写出像"ob.name"这样的表达式

00:05:31.603 --> 00:05:35.963
而你在这里可以看到的是，它列出了所有对象的名字

00:05:40.578 --> 00:05:43.043
所以，它用For循环来循环

00:05:43.043 --> 00:05:47.418
循环到集合中的所有对象，然后对其做一些事情

00:05:47.418 --> 00:05:49.588
这可能是调用一个导出器

00:05:49.626 --> 00:05:51.666
也可能是设置一个材质

00:05:53.072 --> 00:05:54.842
也可能是更改名称

00:05:55.822 --> 00:05:58.617
当然也可能是你想做的任何事情

00:05:58.617 --> 00:06:02.052
在我们的例子中，它只是打印出了名称

00:06:04.936 --> 00:06:08.306
所以我们来看看从Python中创建一个集合

00:06:09.613 --> 00:06:12.508
这也是通过data.collections来完成的

00:06:15.849 --> 00:06:17.354
那麽D.collections

00:06:20.176 --> 00:06:22.826
我们来看看，我们有什麽 new函数

00:06:25.946 --> 00:06:27.411
所以我们输入new{

00:06:28.846 --> 00:06:30.981
你可以看到你可以输入"name"

00:06:34.647 --> 00:06:37.857
现在我们有了一个新的集合，叫做"demo"

00:06:39.519 --> 00:06:42.934
你想使用这个集合，因为它是给你的

00:06:42.934 --> 00:06:46.839
因为现在可以在bpy.data.collections(‘demo’) 找到它。

00:06:54.167 --> 00:06:57.642
这种情况会发生在我们中的每个人身上

00:06:58.077 --> 00:07:00.892
每个人都会有错别字，不用担心

00:07:03.492 --> 00:07:06.887
鉴于demo这个名字，我们可以得到这个集合

00:07:08.333 --> 00:07:12.203
而这是一个很大的陷井，你可能会陷入其中

00:07:13.349 --> 00:07:18.054
因为你可能认为您刚刚创建的名为 DEMO 的集合名为 DEMO

00:07:21.827 --> 00:07:25.422
我们再来看看当我们再做一次会发生什麽

00:07:26.094 --> 00:07:28.019
完全一样的函数调用

00:07:28.145 --> 00:07:31.845
只是告诉Blender给我做一个新的集合叫Demo

00:07:33.396 --> 00:07:37.191
但是这一次，我们已经有一个叫Demo的集合了

00:07:37.212 --> 00:07:40.472
正如我所说，集合必须有一个唯一的名字

00:07:41.740 --> 00:07:43.200
那麽会发生什麽

00:07:43.365 --> 00:07:48.260
它调用一个"Demo.001"，实际上是从Blender中使用的

00:07:49.359 --> 00:07:52.789
但是现在我们要求Blender给这个集合起的名字

00:07:53.281 --> 00:07:56.156
和当初给这个集合起的名字不一样

00:07:57.712 --> 00:08:01.692
所以如果你现在使用bpy.data.collection['demo']

00:08:06.626 --> 00:08:11.181
你会看到你得到的当然是demo，而不是"demo.001"

00:08:12.944 --> 00:08:14.534
所以我想说的是

00:08:14.540 --> 00:08:19.000
当你创建一个新的集合时，一定要给它分配一个名字

00:08:21.987 --> 00:08:22.832
象这样

00:08:26.250 --> 00:08:28.810
这样你就确定你的集合是正确的

00:08:31.346 --> 00:08:33.291
之后你可以更改名称

00:08:39.135 --> 00:08:43.720
比如"collections.name="sfa"，它就会有新的名称

00:08:50.096 --> 00:08:53.081
在Outliner中你可能会注意到一件事

00:08:55.224 --> 00:08:59.889
那就是，这个名字不在那里，就象集合还不存在一样

00:09:02.454 --> 00:09:06.494
所以它存在于Blender文档中，它存在于内存中

00:09:06.885 --> 00:09:09.425
但还没有链接到场景主集合

00:09:12.596 --> 00:09:13.956
那我们怎麽做呢？

00:09:16.527 --> 00:09:17.912
你去到主集合

00:09:20.385 --> 00:09:25.340
然后输入"."并按tab键，就可以得到里面所有的东西的列表

00:09:26.685 --> 00:09:30.800
你会注意到一件事，那就是这个叫做Children的属性

00:09:36.378 --> 00:09:38.633
那包含了所有的Child集合

00:09:41.137 --> 00:09:44.277
这就是所有被链接到这个集合中的集合

00:09:46.667 --> 00:09:48.762
所以，我们来看看那里

00:09:53.301 --> 00:09:56.291
在那里，你会发现一个叫Link的函数

00:09:59.647 --> 00:10:03.647
在这个集合作为这个集合的子集，它有点隐晦

00:10:05.129 --> 00:10:07.854
两次这个集合指的是不同的东西

00:10:07.919 --> 00:10:10.059
但是我想你应该明白了吧

00:10:10.135 --> 00:10:13.200
我们在Collection这个名字里有了我们的集合

00:10:16.891 --> 00:10:21.201
所以在我按回车键的时候，你的眼睛要盯着Outliner

00:10:22.590 --> 00:10:23.350
就有了

00:10:23.613 --> 00:10:26.268
现在，它是场景集合的一部分

00:10:28.974 --> 00:10:31.494
将对象链接到这个新的集合中

00:10:31.764 --> 00:10:35.529
和将其他集合链接到这个新的集合是一样的

00:10:35.867 --> 00:10:39.747
你用的是".children.link"，而不是用".object.link"

00:10:42.595 --> 00:10:44.600
所以，让我们来看看

00:10:44.600 --> 00:10:46.285
我们有了我们的集合

00:10:49.135 --> 00:10:51.065
它有一个空的对象集

00:10:54.712 --> 00:10:56.212
里面什麽也没有

00:11:01.218 --> 00:11:05.443
我们可以使用"collection.object.link"来链接一个对象

00:11:13.109 --> 00:11:17.359
就这样，我们可以把Suzanne.003添加到里面

00:11:18.654 --> 00:11:21.929
让我们把这个放到一个有点象脚本的地方

00:11:23.462 --> 00:11:25.927
所以我要在这里把窗口分开

00:11:27.276 --> 00:11:30.056
改成文本编辑器，创建你的脚本

00:11:33.397 --> 00:11:37.412
把它叫做move_stuff.py，总是以"bpy"开头

00:11:45.705 --> 00:11:47.035
现在我们假设

00:11:47.035 --> 00:11:51.600
我们想把一个集合里面的东西都搬到另一个集合里面去

00:11:53.728 --> 00:11:55.583
所以我们必须有一个

00:11:55.583 --> 00:11:58.478
coll_from=bpy.data.collection['collection
1']

00:12:05.615 --> 00:12:07.890
然后我们有一个类似的东西

00:12:08.241 --> 00:12:11.081
coll_to=bpy.data.collection['SFA']

00:12:17.442 --> 00:12:19.877
所以现在我们有了两个集合

00:12:19.990 --> 00:12:21.950
让我们对1进行循环

00:12:21.950 --> 00:12:25.845
然后把所有找到的对象添加到另一个集合中

00:12:26.763 --> 00:12:29.403
所以，for ob in coll_from.object:

00:12:33.706 --> 00:12:35.591
coll_to.objects.Link(ob)

00:12:40.353 --> 00:12:45.263
这样就已经把一个集合中的所有对象都链接到了另一个集合中

00:12:48.301 --> 00:12:52.726
剩下的是要移动的，就是要从其他集合中解开链接

00:12:54.455 --> 00:12:57.385
所以我们需要从"coll_from"中解开链接

00:12:57.737 --> 00:13:01.902
但这也意味着要从"coll_from.objects"中删除这个对象

00:13:04.650 --> 00:13:06.425
所以，这就意味着

00:13:06.425 --> 00:13:11.075
通过解除链接，我们就改变了当前正在循环的那个东西

00:13:11.442 --> 00:13:13.152
这不是一个好主意

00:13:13.247 --> 00:13:14.787
你不应该这样做

00:13:15.627 --> 00:13:19.092
在最好的情况下，它将是不可预测的

00:13:19.483 --> 00:13:20.978
最坏的情况下

00:13:21.341 --> 00:13:24.156
它会让Blender崩溃，你会失去数据

00:13:25.279 --> 00:13:28.294
对此，最简单的解决办法，有很多

00:13:30.941 --> 00:13:34.861
但最简单的办法就是记录你要解开链接的对象

00:13:35.929 --> 00:13:39.149
所以说要解开链接的对象是一个空列表

00:13:41.186 --> 00:13:45.666
而在这个列表中，我们要记录下我们以后要解绑的对象

00:13:46.891 --> 00:13:49.536
所以我们可以说，to_unlink.append(ob)

00:13:54.540 --> 00:13:56.725
而一旦这个For循环完成

00:13:57.576 --> 00:14:01.956
我们就可以在这个上面解开循环，解开所有的东西

00:14:03.155 --> 00:14:05.085
所以 for ob in to_unlink:

00:14:09.483 --> 00:14:11.543
coll_from.objects.unlink(ob)

00:14:16.763 --> 00:14:17.928
这样就可以了

00:14:18.978 --> 00:14:20.263
我们来试一试

00:14:27.660 --> 00:14:29.990
当然，我的脚本运行失败了

00:14:32.247 --> 00:14:34.002
我们来看看控制台

00:14:36.058 --> 00:14:38.888
如果我们看看从我启动Blender的终端

00:14:40.000 --> 00:14:42.885
你可以看到它给了我一个运行时错误

00:14:43.610 --> 00:14:47.790
对象Suzanne.003已经在集合SFA中

00:14:49.026 --> 00:14:49.871
有道理

00:14:51.897 --> 00:14:55.102
它不喜欢我们链接一个已经在里面的对象

00:14:57.051 --> 00:15:01.976
基本上有两种方法可以避免你的脚本因为这样的错误而崩溃

00:15:05.288 --> 00:15:07.573
一种是一开始就避免错误

00:15:08.817 --> 00:15:11.642
另一种是在错误发生时处理错误

00:15:13.412 --> 00:15:15.382
我认为在这种情况下

00:15:15.382 --> 00:15:17.847
最简单的方法就是修正错误

00:15:18.013 --> 00:15:21.188
确保我们的脚本在发生错误时继续运行

00:15:22.546 --> 00:15:25.296
错误说的是第8行是问题所在

00:15:27.469 --> 00:15:29.664
所以我们来看看第8行

00:15:31.058 --> 00:15:33.633
所以第8行是代码中的这一行

00:15:35.160 --> 00:15:36.130
它delinking了

00:15:37.212 --> 00:15:39.272
当然，这当然会出错

00:15:40.062 --> 00:15:44.017
你可以告诉 Python 试试这一行，看看会发生什麽

00:15:47.774 --> 00:15:49.989
从字面上看，你说try

00:15:51.303 --> 00:15:55.183
然后用一个冒号，就象我们看到的For循环

00:15:55.183 --> 00:15:57.253
和"If"和其他的东西一样

00:15:57.253 --> 00:16:00.478
在一个列中，你必须缩进其余的部分

00:16:01.359 --> 00:16:03.419
这表明它需要尝试什麽

00:16:06.827 --> 00:16:09.077
然后当我们看终端的时候

00:16:09.376 --> 00:16:11.981
我们看到运行时的错误就在这里

00:16:17.147 --> 00:16:18.847
这就是异常的类型

00:16:20.160 --> 00:16:23.475
我就不细说了，至於这一切意味着什麽

00:16:24.295 --> 00:16:27.215
只要知道你必须在这里输入就可以了

00:16:29.199 --> 00:16:32.574
所以说，如果在这个try脚本中出现异常

00:16:38.471 --> 00:16:42.321
这个类型的异常，那麽就在这里运行这段代码

00:16:46.101 --> 00:16:48.656
而在我们的例子中，这就很好

00:16:48.973 --> 00:16:51.188
当这个对象已经在集合中

00:16:54.038 --> 00:16:55.818
这意味着我们很高兴

00:16:56.446 --> 00:17:00.366
因为我们想把它链接到那里，它已经在那里了

00:17:00.366 --> 00:17:03.661
所以一切都很好，所以我们可以让这个"pass"

00:17:03.661 --> 00:17:07.686
也就是字面上的意思，只要在那里键入"pass"就可以了

00:17:07.686 --> 00:17:08.951
这就告诉Python

00:17:08.951 --> 00:17:12.136
这里不要做任何事情，不要理会这个错误

00:17:12.136 --> 00:17:13.606
什麽都没有发生

00:17:14.840 --> 00:17:17.910
当然，接下来的这一行还是很重要的

00:17:19.680 --> 00:17:23.105
因为我们还是要处理这个，虽然对象移动了

00:17:25.227 --> 00:17:28.297
链接出了问题，因为它已经在那里了

00:17:28.695 --> 00:17:31.775
它仍然需要从原来的集合中解开链接

00:17:31.775 --> 00:17:34.295
所以我们就可以继续往前走了

00:17:34.295 --> 00:17:37.255
而这个应该就能解决我们的代码问题了

00:17:38.782 --> 00:17:40.137
让我们试一试

00:17:42.692 --> 00:17:46.657
就这样，所有的对象都已经搬到了SFA中

00:17:48.871 --> 00:17:51.151
已经从Collection 1中拿走了

00:17:52.606 --> 00:17:55.391
当然，我们还可以做相反的事情

00:17:55.653 --> 00:17:59.908
我们可以说，把名字翻转一下，再运行一次脚本

00:18:04.596 --> 00:18:07.056
然后它们又回到了开始的地方

00:18:09.519 --> 00:18:13.059
所以，这就是你如何在Collection之间移动对象

00:18:14.404 --> 00:18:18.284
最后我们还可以做一件事，这可能有点没用

00:18:22.273 --> 00:18:24.438
但只是给大家做个演示

00:18:24.438 --> 00:18:26.988
我们还可以删除我们移动的集合

00:18:28.509 --> 00:18:31.629
那就是bpy.data.collections.remove(coll_from)

00:18:45.847 --> 00:18:47.547
让我们再翻转一下

00:18:49.022 --> 00:18:53.112
我们将所有的对象从collection 1中移动到SFA

00:18:53.288 --> 00:18:56.433
然后一旦完成后，我们删除Collection 1

00:18:58.294 --> 00:19:00.369
就这样，我们就这样做了

00:19:00.369 --> 00:19:02.754
现在，Collection 1已经消失了

00:19:02.947 --> 00:19:05.232
所有的对象都被再次移动了

00:19:05.327 --> 00:19:07.982
这就是Python中的集合的工作方式

00:19:08.855 --> 00:19:12.240
为了结束这一集，让我们再来看看 Outliner

00:19:16.240 --> 00:19:19.700
有一些你可以设置的toggles，比如显示toggles

00:19:21.027 --> 00:19:22.572
让我们来看一看

00:19:22.572 --> 00:19:25.457
如果我想改变这个集合的窗口喧染

00:19:29.367 --> 00:19:33.977
可以看到在用户首选项中的点和工具提示中可以激活

00:19:35.787 --> 00:19:40.207
可以看到bpy.data.collection.SFA.hide_viewport

00:19:41.671 --> 00:19:43.676
就是我们要切换的东西

00:19:43.676 --> 00:19:45.601
下面我们来看看那里

00:19:47.465 --> 00:19:49.615
我们取D.collections['SFA'].hide_

00:19:53.318 --> 00:19:54.468
那里已经有了

00:19:55.003 --> 00:19:57.523
Hide Render、Hide Select、Hide Viewport

00:20:01.646 --> 00:20:03.566
你可以把它们设置为"True"

00:20:05.708 --> 00:20:09.093
再设置为"False"，然后你就可以玩这个了

00:20:12.418 --> 00:20:16.343
它几乎可以实现你所期望的点击图标的功能

00:20:18.691 --> 00:20:19.571
就这样了

00:20:19.841 --> 00:20:22.651
如果你有什麽问题，请留下评论

00:20:22.651 --> 00:20:24.216
我们下期视频再见