我在 Raycast3D 中选择一个对象时遇到问题

Im having problems with Raycast3D selecting one object in Godot

提问人:TheZombrex 提问时间:9/18/2023 最后编辑:TheZombrex 更新时间:9/30/2023 访问量:148

问:

问题是,当我使用RayCast激活或停用一个立方体时,其他立方体都会被激活。我把它们放在一个组中,我只想激活我点击的立方体。

事实是,这对我来说似乎非常复杂,因为这是我使用 Godot 的第一天,而且我来自 Unity,这很容易做到并且工作正常。

这里有一个视频:https://youtu.be/2k7qQWHNvwA

我尝试仅激活我使用 _raycast.get_collider() 单击的立方体并检查带有碰撞体的立方体是否在特定组中。

目标是,当你左键点击一个立方体时,它会改变它的透明度,使其完全可见,并在第 1 层发生碰撞,这是它与玩家碰撞的地方。

右键单击时,透明度会发生变化,使其不完全可见,碰撞层 1 将被停用,以便玩家可以通过它。

所有这些只需要在你点击的立方体上起作用,而且只有当它是一个红色的立方体时。

重要提示:Raycast3D 节点位于播放器内的 Camera 节点内,脚本位于 RayCast3D 中。

脚本如下:

extends RayCast3D

@export var raycast_path: NodePath
@onready var _raycast = get_node_or_null(raycast_path)

func _ready():
    pass

func _input(event):
    if event is InputEventMouseButton:
        if event.button_index == MOUSE_BUTTON_LEFT && event.pressed:
            _handle_left_click()
        elif event.button_index == MOUSE_BUTTON_RIGHT && event.pressed:
            _handle_right_click()

func _handle_left_click():
    if _raycast.is_colliding():
        var collider = _raycast.get_collider().owner
        if "CuboRojo" in collider.get_groups():
            var cubo_rojo = collider as GeometryInstance3D
            var material = cubo_rojo.material_override
            material.transparency = 0
            cubo_rojo.get_node("StaticBody3D").collision_layer = 1 | 2

func _handle_right_click():
    if _raycast.is_colliding():
        var collider = _raycast.get_collider().owner
        if "CuboRojo" in collider.get_groups():
            var cubo_rojo = collider as GeometryInstance3D
            var material = cubo_rojo.material_override
            material.transparency = 1
            cubo_rojo.get_node("StaticBody3D").collision_layer = 2

我尝试了多种方式,但所有对象都同时激活。

光线投射 Godot4

评论


答:

0赞 Theraot 9/19/2023 #1

问题是它们都共享相同的材料。因此,当您修改材质以添加或删除透明度时,更改将反映在共享相同材质的所有立方体中。

更容易掌握的方法是在修改材料之前复制材料:

cubo_rojo.material_override = cubo_rojo.material_override.duplicate()

但是,当然,这意味着您每次都会创建一个新的材质对象。因此,我建议定义具有透明度的第二种材质(也许在脚本中为它导出一个变量,以便您可以在检查器中设置它),并替换材质而不是修改它。

或者,您可以存储一个元数据变量,以便在您已经复制了材料时进行跟踪:

if not cubo_rojo.get_meta("material_duplicated", false):
    cubo_rojo.material_override = cubo_rojo.material_override.duplicate()
    cubo_rojo.set_meta("material_duplicated", true)

这里我们用来读取一个元数据变量 called ,如果元数据变量不存在(这将是起始情况),那么它将返回(我们指定)。当然,我们用来编写元数据变量。get_metacubo_rojo"material_duplicated"falseset_meta


我还想指出,使用将比 或 更有效。collider.is_in_group("CuboRojo")"CuboRojo" in collider.get_groups()collider.get_groups().has("CuboRojo")


补遗

当我写下答案时,这逃脱了我的脑海。

您可以将 s(例如材质)标记为与场景的每个实例重复,而不是重复使用。为此,请将 的属性设置为 。Resourceresource_local_to_sceneResourcetrue