﻿WEBVTT

00:00:00.865 --> 00:00:05.380
大家好，歡迎來到本期藝術家的腳本的教程視頻

00:00:05.380 --> 00:00:06.975
我的名字是Sybren

00:00:06.975 --> 00:00:09.675
這一集的內容是關於Blenderer集合

00:00:10.005 --> 00:00:15.130
這些是Blenderer 2.8中引入的，取代了編號的場景層和組

00:00:17.062 --> 00:00:20.367
我沒有像往常一樣在Blenderer研究所錄製

00:00:20.423 --> 00:00:23.658
但我現在和你們很多人一樣，都在家

00:00:23.951 --> 00:00:27.031
因此，這段視頻的腳本會比較少

00:00:27.505 --> 00:00:29.760
我不會有任何幻燈片展示

00:00:30.951 --> 00:00:35.301
我們將直接進入Blender，我將在那裡展示一些東西

00:00:36.082 --> 00:00:40.642
所以在這裡的Outliner中你可以看到我們有一個scene collection

00:00:40.801 --> 00:00:42.251
裡面有一個Suzanne

00:00:42.981 --> 00:00:44.701
就像一個對像一樣

00:00:44.701 --> 00:00:47.086
它有默認的集合，Collection 1

00:00:47.981 --> 00:00:51.801
所以鑑於此，這裡的這個東西叫做場景集合

00:00:53.314 --> 00:00:58.569
我們來看看這個場景對象，看看能不能找到一個集合屬性

00:01:02.012 --> 00:01:03.522
這裡我們有Suzanne

00:01:04.327 --> 00:01:07.267
提醒一下，這裡我們有方便變量

00:01:08.512 --> 00:01:13.937
所以大寫的C代表bpy.context，大寫的D代表bpy.data

00:01:16.156 --> 00:01:19.396
你不能在你自己的腳本中使用這些變量

00:01:19.396 --> 00:01:22.946
但你可以在控制台中使用它們來解決問題

00:01:23.706 --> 00:01:26.551
我們來看一下，輸入C.scene.coll

00:01:29.551 --> 00:01:32.006
然後按Tab鍵，你可以看到

00:01:32.227 --> 00:01:34.597
它已經有一個collection屬性了

00:01:35.755 --> 00:01:39.065
我們可以得到它的名字，叫(主集合)master collection

00:01:40.988 --> 00:01:45.178
因為它是主場景集合，它有一個屬性叫objects

00:01:52.928 --> 00:01:56.998
如果你把它轉換為列表，只要按向上的箭頭

00:01:57.518 --> 00:02:01.243
然後輸入list，並把前面的放在括號裡

00:02:02.981 --> 00:02:04.746
在那裡你可以看到

00:02:04.746 --> 00:02:07.706
有一個對象，Suzanne，就是這個

00:02:08.788 --> 00:02:13.123
collection.objects給出所有直接鏈接到集合中的對象

00:02:16.976 --> 00:02:21.111
看看當我們把Suzanne移到Collection 1中會發生什麼

00:02:22.010 --> 00:02:24.985
它仍然是間接地在場景集合裡面

00:02:25.133 --> 00:02:27.358
因為它是在Collection 1裡面

00:02:27.649 --> 00:02:30.259
而Collection one是在場景集合裡面

00:02:30.931 --> 00:02:34.621
但是它已經不在"scene.collection.object"裡面了

00:02:37.495 --> 00:02:41.265
如果你想真的什麼都有，那就看"all_objects"

00:02:44.305 --> 00:02:49.135
這就像一個神奇的視圖，可以讓你看到集合本身的一切

00:02:51.115 --> 00:02:54.170
所以它包含了那個對像也包含的一切

00:02:55.546 --> 00:03:00.201
但隨後它也包含了集合裡面的集合和集合裡面的集合和

00:03:05.000 --> 00:03:07.285
而你可以看到我們有Suzanne

00:03:09.519 --> 00:03:13.974
所以像Blender集合中的很多東西都要有一個唯一的名字

00:03:14.417 --> 00:03:17.152
因為它們是以數據的形式存儲的

00:03:17.945 --> 00:03:20.110
所以我們有"bpy.data"

00:03:20.735 --> 00:03:23.105
或者在控制台中的D.collection

00:03:26.033 --> 00:03:28.023
這就給了我們collection 1

00:03:28.413 --> 00:03:30.398
它不包含場景主集合

00:03:31.367 --> 00:03:33.757
但它包含了其他所有的集合

00:03:35.705 --> 00:03:36.890
所以在這裡

00:03:36.890 --> 00:03:39.560
我們也可以得到D.collection['Collection 1'].objects"

00:03:42.724 --> 00:03:46.569
並將其轉換為列表，看看裡面都有什麼

00:03:47.583 --> 00:03:50.418
同樣的，當然也有Suzanne在裡面

00:03:50.418 --> 00:03:52.708
所以這已經給了你一個方法

00:03:52.708 --> 00:03:54.663
給定了一個集合的名稱

00:03:55.765 --> 00:03:58.425
就可以迭代該集合中的所有對象

00:03:59.950 --> 00:04:02.775
所以，也許你想寫一個輸出器

00:04:02.775 --> 00:04:05.410
輸出一個特定集合中的所有對象

00:04:06.596 --> 00:04:08.841
現在你知道如何訪問它了

00:04:11.892 --> 00:04:14.117
我的意思是迭代這些對象

00:04:15.545 --> 00:04:20.465
讓我們看看這是如何發生的，只是為了喚醒你們的記憶

00:04:20.878 --> 00:04:23.698
假設我們有一段波希米亞狂想曲

00:04:27.212 --> 00:04:30.132
在這個系列中有四首蘇珊娜的作品

00:04:31.219 --> 00:04:36.254
如果我們用list.collection.object，
那麼我們就會得到所有的四個

00:04:37.537 --> 00:04:41.932
讓我們看看在更複雜一點的代碼中會是什麼樣子

00:04:44.963 --> 00:04:47.708
你基本上會用coll=D.collection['collection 1']

00:04:56.531 --> 00:04:59.221
然後我可以輸入for ob in coll.object:

00:05:05.050 --> 00:05:05.655
print(f'08 name is:{ob.name}')

00:05:13.205 --> 00:05:15.150
這是一個格式字符串

00:05:17.051 --> 00:05:18.206
真的很有用

00:05:18.777 --> 00:05:21.627
你可以在開頭的引號前輸入一個F

00:05:22.264 --> 00:05:27.049
然後在大括號內，你可以寫出像"ob.name"這樣的表達式

00:05:31.603 --> 00:05:36.193
而你在這裡可以看到的是，它列出了所有對象的名字

00:05:40.578 --> 00:05:43.268
所以，它用For循環來循環

00:05:43.268 --> 00:05:47.718
循環到集合中的所有對象，然後對其做一些事情

00:05:47.718 --> 00:05:49.863
這可能是調用一個導出器

00:05:49.863 --> 00:05:51.853
也可能是設置一個材質

00:05:53.072 --> 00:05:54.887
也可能是更改名稱

00:05:55.822 --> 00:05:58.642
當然也可能是你想做的任何事情

00:05:58.642 --> 00:06:02.437
在我們的例子中，它只是打印出了名稱

00:06:04.936 --> 00:06:08.246
所以我們來看看從Python中創建一個集合

00:06:09.613 --> 00:06:12.603
這也是通過data.collections來完成的

00:06:15.849 --> 00:06:17.084
那麼D.collections

00:06:20.176 --> 00:06:23.291
我們來看看，我們有什麼 new函數

00:06:25.946 --> 00:06:27.456
所以我們輸入new{

00:06:28.846 --> 00:06:31.076
你可以看到你可以輸入"name"

00:06:34.647 --> 00:06:38.007
現在我們有了一個新的集合，叫做"demo"

00:06:39.519 --> 00:06:42.984
你想使用這個集合，因為它是給你的

00:06:42.984 --> 00:06:46.869
因為現在可以在bpy.data.collections(‘demo’) 找到它。

00:06:54.167 --> 00:06:57.902
這種情況會發生在我們中的每個人身上

00:06:58.077 --> 00:07:00.962
每個人都會有錯別字，不用擔心

00:07:03.492 --> 00:07:07.062
鑑於demo這個名字，我們可以得到這個集合

00:07:08.333 --> 00:07:12.328
而這是一個很大的陷阱，你可能會陷入其中

00:07:13.349 --> 00:07:18.009
因為你可能認為您剛剛創建的名為 DEMO 的集合名為 DEMO

00:07:21.827 --> 00:07:25.337
我們再來看看當我們再做一次會發生什麼

00:07:26.094 --> 00:07:28.139
完全一樣的函數調用

00:07:28.145 --> 00:07:31.840
只是告訴Blender給我做一個新的集合叫Demo

00:07:33.396 --> 00:07:37.541
但是這一次，我們已經有一個叫Demo的集合了

00:07:37.541 --> 00:07:41.281
正如我所說，集合必須有一個唯一的名字

00:07:41.740 --> 00:07:43.185
那麼會發生什麼

00:07:43.365 --> 00:07:48.275
它調用一個"Demo.001"，實際上是從Blender中使用的

00:07:49.359 --> 00:07:52.999
但是現在我們要求Blender給這個集合起的名字

00:07:53.281 --> 00:07:56.116
和當初給這個集合起的名字不一樣

00:07:57.712 --> 00:08:01.612
所以如果你現在使用bpy.data.collection['demo']

00:08:06.626 --> 00:08:11.371
你會看到你得到的當然是demo，而不是"demo.001"

00:08:12.944 --> 00:08:14.534
所以我想說的是

00:08:14.540 --> 00:08:19.195
當你創建一個新的集合時，一定要給它分配一個名字

00:08:21.987 --> 00:08:22.907
像這樣

00:08:26.250 --> 00:08:28.880
這樣你就確定你的集合是正確的

00:08:31.346 --> 00:08:33.226
之後你可以更改名稱

00:08:39.135 --> 00:08:43.510
比如"collections.name="sfa"，它就會有新的名稱

00:08:50.096 --> 00:08:52.906
在Outliner中你可能會注意到一件事

00:08:55.224 --> 00:09:00.334
那就是，這個名字不在那裡，就像集合還不存在一樣

00:09:02.454 --> 00:09:06.789
所以它存在於Blender文件中，它存在於內存中

00:09:06.885 --> 00:09:09.385
但還沒有鏈接到場景主集合

00:09:12.596 --> 00:09:14.046
那我們怎麼做呢？

00:09:16.527 --> 00:09:17.752
你去到主集合

00:09:20.385 --> 00:09:25.475
然後輸入"."並按tab鍵，就可以得到裡面所有的東西的列表

00:09:26.685 --> 00:09:31.060
你會注意到一件事，那就是這個叫做Children的屬性

00:09:36.378 --> 00:09:38.508
那包含了所有的Child集合

00:09:41.137 --> 00:09:44.252
這就是所有被鏈接到這個集合中的集合

00:09:46.667 --> 00:09:49.072
所以，我們來看看那裡

00:09:53.301 --> 00:09:56.456
在那裡，你會發現一個叫Link的函數

00:09:59.647 --> 00:10:03.867
在這個集合作為這個集合的子集，它有點隱晦

00:10:05.129 --> 00:10:07.809
兩次這個集合指的是不同的東西

00:10:07.919 --> 00:10:10.179
但是我想你應該明白了吧

00:10:10.179 --> 00:10:13.449
我們在Collection這個名字裡有了我們的集合

00:10:16.891 --> 00:10:21.461
所以在我按回車鍵的時候，你的眼睛要盯著Outliner

00:10:22.590 --> 00:10:23.405
就有了

00:10:23.613 --> 00:10:26.468
現在，它是場景集合的一部分

00:10:28.974 --> 00:10:31.539
將對象鏈接到這個新的集合中

00:10:31.764 --> 00:10:35.534
和將其他集合鏈接到這個新的集合是一樣的

00:10:35.867 --> 00:10:40.102
你用的是".children.link"，而不是用".object.link"

00:10:42.595 --> 00:10:44.895
所以，讓我們來看看

00:10:44.895 --> 00:10:46.655
我們有了我們的集合

00:10:49.135 --> 00:10:51.015
它有一個空的對象集

00:10:54.712 --> 00:10:56.127
裡面什麼也沒有

00:11:01.218 --> 00:11:05.678
我們可以使用"collection.object.link"來鏈接一個對象

00:11:13.109 --> 00:11:17.674
就這樣，我們可以把Suzanne.003添加到裡面

00:11:18.654 --> 00:11:22.109
讓我們把這個放到一個有點像腳本的地方

00:11:23.462 --> 00:11:25.917
所以我要在這裡把視窗分開

00:11:27.276 --> 00:11:30.301
改成文本編輯器，創建你的腳本

00:11:33.397 --> 00:11:37.477
把它叫做move_stuff.py，總是以"bpy"開頭

00:11:45.705 --> 00:11:47.010
現在我們假設

00:11:47.010 --> 00:11:51.650
我們想把一個集合裡面的東西都搬到另一個集合裡面去

00:11:53.728 --> 00:11:55.598
所以我們必須有一個

00:11:55.598 --> 00:11:58.333
coll_from=bpy.data.collection['collection
1']

00:12:05.615 --> 00:12:08.025
然後我們有一個類似的東西

00:12:08.241 --> 00:12:10.921
coll_to=bpy.data.collection['SFA']

00:12:17.442 --> 00:12:19.827
所以現在我們有了兩個集合

00:12:19.990 --> 00:12:21.970
讓我們對1進行循環

00:12:21.970 --> 00:12:25.845
然後把所有找到的對象添加到另一個集合中

00:12:26.763 --> 00:12:29.398
所以，for ob in coll_from.object:

00:12:33.706 --> 00:12:35.416
coll_to.objects.Link(ob)

00:12:40.353 --> 00:12:45.423
這樣就已經把一個集合中的所有對像都鏈接到了另一個集合中

00:12:48.301 --> 00:12:52.846
剩下的是要移動的，就是要從其他集合中解開鏈接

00:12:54.455 --> 00:12:57.300
所以我們需要從"coll_from"中解開鏈接

00:12:57.737 --> 00:13:02.172
但這也意味著要從"coll_from.objects"中刪除這個對象

00:13:04.650 --> 00:13:06.710
所以，這就意味著

00:13:06.710 --> 00:13:11.715
通過解除鏈接，我們就改變了當前正在循環的那個東西

00:13:11.715 --> 00:13:13.445
這不是一個好主意

00:13:13.445 --> 00:13:15.030
你不應該這樣做

00:13:15.627 --> 00:13:19.197
在最好的情況下，它將是不可預測的

00:13:19.483 --> 00:13:20.783
最壞的情況下

00:13:21.341 --> 00:13:24.386
它會讓Blender崩潰，你會失去數據

00:13:25.279 --> 00:13:28.694
對此，最簡單的解決辦法，有很多

00:13:30.941 --> 00:13:35.056
但最簡單的辦法就是記錄你要解開鏈接的對象

00:13:35.929 --> 00:13:39.539
所以說要解開鏈接的對像是一個空列表

00:13:41.186 --> 00:13:46.051
而在這個列表中，我們要記錄下我們以後要解綁的對象

00:13:46.891 --> 00:13:49.581
所以我們可以說，to_unlink.append(ob)

00:13:54.540 --> 00:13:56.745
而一旦這個For循環完成

00:13:57.576 --> 00:14:02.241
我們就可以在這個上面解開循環，解開所有的東西

00:14:03.155 --> 00:14:04.680
所以 for ob in to_unlink:

00:14:09.483 --> 00:14:11.393
coll_from.objects.unlink(ob)

00:14:16.763 --> 00:14:18.058
這樣就可以了

00:14:18.978 --> 00:14:20.223
我們來試一試

00:14:27.660 --> 00:14:30.300
當然，我的腳本運行失敗了

00:14:32.247 --> 00:14:34.117
我們來看看控制台

00:14:36.058 --> 00:14:39.088
如果我們看看從我啟動Blender的終端

00:14:40.000 --> 00:14:42.940
你可以看到它給了我一個運行時錯誤

00:14:43.610 --> 00:14:47.515
對象Suzanne.003已經在集合SFA中

00:14:49.026 --> 00:14:49.846
有道理

00:14:51.897 --> 00:14:55.257
它不喜歡我們鏈接一個已經在裡面的對象

00:14:57.051 --> 00:15:02.066
基本上有兩種方法可以避免你的腳本因為這樣的錯誤而崩潰

00:15:05.288 --> 00:15:07.558
一種是一開始就避免錯誤

00:15:08.817 --> 00:15:11.692
另一種是在錯誤發生時處理錯誤

00:15:13.412 --> 00:15:15.347
我認為在這種情況下

00:15:15.347 --> 00:15:17.902
最簡單的方法就是修正錯誤

00:15:18.013 --> 00:15:21.363
確保我們的腳本在發生錯誤時繼續運行

00:15:22.546 --> 00:15:25.361
錯誤說的是第8行是問題所在

00:15:27.469 --> 00:15:29.639
所以我們來看看第8行

00:15:31.058 --> 00:15:33.648
所以第8行是代碼中的這一行

00:15:35.160 --> 00:15:36.235
它delinking了

00:15:37.212 --> 00:15:39.367
當然，這當然會出錯

00:15:40.062 --> 00:15:44.377
你可以告訴 Python 試試這一行，看看會發生什麼

00:15:47.774 --> 00:15:50.189
從字面上看，你說try

00:15:51.303 --> 00:15:55.248
然後用一個冒號，就像我們看到的For循環

00:15:55.248 --> 00:15:57.328
和"If"和其他的東西一樣

00:15:57.328 --> 00:16:00.743
在一個列中，你必須縮進其餘的部分

00:16:01.359 --> 00:16:03.544
這表明它需要嘗試什麼

00:16:06.827 --> 00:16:09.212
然後當我們看終端的時候

00:16:09.376 --> 00:16:12.176
我們看到運行時的錯誤就在這裡

00:16:17.147 --> 00:16:19.012
這就是異常的類型

00:16:20.160 --> 00:16:23.805
我就不細說了，至於這一切意味著什麼

00:16:24.295 --> 00:16:27.280
只要知道你必須在這裡輸入就可以了

00:16:29.199 --> 00:16:32.789
所以說，如果在這個try腳本中出現異常

00:16:38.471 --> 00:16:42.686
這個類型的異常，那麼就在這裡執行這段代碼

00:16:46.101 --> 00:16:48.891
而在我們的例子中，這就很好

00:16:48.973 --> 00:16:51.288
當這個對像已經在集合中

00:16:54.038 --> 00:16:56.018
這意味著我們很高興

00:16:56.446 --> 00:17:00.771
因為我們想把它鏈接到那裡，它已經在那裡了

00:17:00.771 --> 00:17:04.171
所以一切都很好，所以我們可以讓這個"pass"

00:17:04.171 --> 00:17:08.586
也就是字面上的意思，只要在那裡鍵入"pass"就可以了

00:17:08.586 --> 00:17:09.926
這就告訴Python

00:17:09.926 --> 00:17:13.436
這裡不要做任何事情，不要理會這個錯誤

00:17:13.436 --> 00:17:14.846
什麼都沒有發生

00:17:14.846 --> 00:17:18.201
當然，接下來的這一行還是很重要的

00:17:19.680 --> 00:17:23.500
因為我們還是要處理這個，雖然對象移動了

00:17:25.227 --> 00:17:28.497
鏈接出了問題，因為它已經在那裡了

00:17:28.695 --> 00:17:31.780
它仍然需要從原來的集合中解開鏈接

00:17:31.780 --> 00:17:34.335
所以我們就可以繼續往前走了

00:17:34.335 --> 00:17:37.505
而這個應該就能解決我們的代碼問題了

00:17:38.782 --> 00:17:40.127
讓我們試一試

00:17:42.692 --> 00:17:46.857
就這樣，所有的對像都已經搬到了SFA中

00:17:48.871 --> 00:17:51.051
已經從Collection 1中拿走了

00:17:52.606 --> 00:17:55.631
當然，我們還可以做相反的事情

00:17:55.653 --> 00:18:00.363
我們可以說，把名字翻轉一下，再運行一次腳本

00:18:04.596 --> 00:18:07.271
然後它們又回到了開始的地方

00:18:09.519 --> 00:18:13.329
所以，這就是你如何在Collection之間移動對象

00:18:14.404 --> 00:18:18.534
最後我們還可以做一件事，這可能有點沒用

00:18:22.273 --> 00:18:24.428
但只是給大家做個演示

00:18:24.428 --> 00:18:26.988
我們還可以刪除我們移動的集合

00:18:28.509 --> 00:18:31.624
那就是bpy.data.collections.remove(coll_from)

00:18:45.847 --> 00:18:47.677
讓我們再翻轉一下

00:18:49.022 --> 00:18:53.087
我們將所有的對像從collection 1中移動到SFA

00:18:53.288 --> 00:18:56.553
然後一旦完成後，我們刪除Collection 1

00:18:58.294 --> 00:19:00.844
就這樣，我們就這樣做了

00:19:00.844 --> 00:19:03.309
現在，Collection 1已經消失了

00:19:03.309 --> 00:19:05.679
所有的對像都被再次移動了

00:19:05.679 --> 00:19:08.349
這就是Python中的集合的工作方式

00:19:08.855 --> 00:19:12.455
為了結束這一集，讓我們再來看看 Outliner

00:19:16.240 --> 00:19:19.885
有一些你可以設置的toggles，比如顯示toggles

00:19:21.027 --> 00:19:22.692
讓我們來看一看

00:19:22.692 --> 00:19:25.602
如果我想改變這個集合的視窗渲染

00:19:29.367 --> 00:19:34.022
可以看到在用戶首選項中的點和工具提示中可以啟用

00:19:35.787 --> 00:19:40.177
可以看到bpy.data.collection.SFA.hide_viewport

00:19:41.671 --> 00:19:43.821
就是我們要切換的東西

00:19:43.821 --> 00:19:45.826
下面我們來看看那裡

00:19:47.465 --> 00:19:49.425
我們取D.collections['SFA'].hide_

00:19:53.318 --> 00:19:54.558
那裡已經有了

00:19:55.003 --> 00:19:57.408
Hide Render、Hide Select、Hide Viewport

00:20:01.646 --> 00:20:03.761
你可以把它們設置為"True"

00:20:05.708 --> 00:20:09.353
再設置為"False"，然後你就可以玩這個了

00:20:12.418 --> 00:20:16.273
它幾乎可以實現你所期望的點擊圖標的功能

00:20:18.691 --> 00:20:19.696
就這樣了

00:20:19.841 --> 00:20:22.816
如果你有什麼問題，請留下評論

00:20:22.816 --> 00:20:24.576
我們下期視頻再見