godot 之前都是主要使用它的 2d 功能,最近创建 3d 场景时遇到一个问题, 无法正确改变复制出来的物体的颜色,我们来看一下如何解决
我们用 godot 3.0 创建一个简单场景来重现一下这个问题
在这个场景中我们画一个白球
你可能发现这个球似乎是蓝色,没有关系,是因为它倒映了 godot 默认的蓝天的颜色
在这个场景中我们利用 sphere.tscn 并复制成三个球
其中相机的 translation 设为 -30,0,0、rotation degree 设为 0,-90,0
在脚本中,我们复制了两个球,相关脚本内容如下:
func _ready():
# Called when the node is added to the scene for the first time.
# Initialization here
var new_sphere = $sphere.duplicate()
new_sphere.translate(Vector3(0,0,5))
add_child(new_sphere)
new_sphere = $sphere.duplicate()
new_sphere.translate(Vector3(0,0,10))
add_child(new_sphere)
我们来试试看修改脚本来改变复制球的颜色
func _ready():
# Called when the node is added to the scene for the first time.
# Initialization here
var new_sphere = $sphere.duplicate()
new_sphere.translate(Vector3(0,0,5))
var mat = new_sphere.get_node("MeshInstance").mesh.material
mat.albedo_color = Color(1,0,0)
add_child(new_sphere)
new_sphere = $sphere.duplicate()
new_sphere.translate(Vector3(0,0,10))
add_child(new_sphere)
然后运行一下 test 场景
包含原球,三个球的颜色都变成了红色,这就是我们要解决的问题
我们首先想到的是,albedo_color 是一个引用,三个球都引用了相同的颜色, 如果这个是真,那么由于 albedo_color 是从属于 material 的, 所以三个球的材料也是相同的,那么我们尝试复制一份材料
func _ready():
# Called when the node is added to the scene for the first time.
# Initialization here
var new_sphere = $sphere.duplicate()
new_sphere.translate(Vector3(0,0,5))
var mesh_inst = new_sphere.get_node("MeshInstance")
var mat = mesh_inst.mesh.material.duplicate()
mat.albedo_color = Color(1,0,0)
mesh_inst.mesh.material = mat
add_child(new_sphere)
new_sphere = $sphere.duplicate()
new_sphere.translate(Vector3(0,0,10))
add_child(new_sphere)
运行 test 场景,问题没有解决,依然是三个红球
我们再往上推一层,材料是属于 mesh 的,那么我们来复制一份 mesh, 注意之前复制材料的动作需要保留,否则的话,虽然 mesh 不同,材料相同, 依然会显示相同的颜色
func _ready():
# Called when the node is added to the scene for the first time.
# Initialization here
var new_sphere = $sphere.duplicate()
new_sphere.translate(Vector3(0,0,5))
var mesh_inst = new_sphere.get_node("MeshInstance")
var new_mesh = mesh_inst.mesh.duplicate()
var mat = new_mesh.material.duplicate()
mat.albedo_color = Color(1,0,0)
new_mesh.material = mat
mesh_inst.mesh = new_mesh
add_child(new_sphere)
new_sphere = $sphere.duplicate()
new_sphere.translate(Vector3(0,0,10))
add_child(new_sphere)
运行一下场景,得到这样的结果
这就跟我们的预期相符了:原球没有改变,复制球变为红色,继续从原球复制也可以保持原来的属性
从以上实验我们可以看到 godot 中,基于引用的原因,mesh 和 material 是绑定在一起的, 看上去你可能没有办法只改变 material 而不改变 mesh,因为一旦某个 mesh 的 material 改变, 所有指向这个 mesh 的物体的材料都会发生变化