Zenva----Godot学习之旅

脚本介绍

变量extends Node2D


var score:int = 10
var move_speed : float = 2.53
var game_over : bool = false
var ability : String = "slassh"

func _ready():
        move_speed = 0.1123
        game_over = true
        ability = "attack"
        print(move_speed)
        print(game_over)
    
        print(ability)
  1. extends Node2D声明这个脚本继承自 Node2D节点(Godot引擎中的一种基础节点类型,用于2D场景中的物体,支持位置、旋转、缩放等2D变换)。这意味着这个脚本可以附加到 Node2D或其派生节点(如 Sprite2DArea2D等)上,并继承 Node2D的所有属性和方法。
  2. var score:int = 10定义一个**整数类型**(:int)的变量 score,并初始化为 10var是GDScript中声明变量的关键字,:int明确指定变量类型为整数(用于存储没有小数的数值)。
  3. var move_speed : float = 2.53定义一个**浮点类型**(:float)的变量 move_speed,初始化为 2.53。浮点型用于存储带小数的数值(通常用于表示速度、位置等需要精度的属性)。
  4. var game_over : bool = false定义一个**布尔类型**(:bool)的变量 game_over,初始化为 false。布尔型变量只有两个可能的值:true(真)或 false(假),通常用于表示状态(这里可能用于标记游戏是否结束)。
  5. var ability : String = "slassh"定义一个**字符串类型**(:String)的变量 ability,初始化为 "slassh"(字符串需要用双引号包裹)。字符串用于存储文本信息(这里可能表示角色的技能名称,注意原词可能是"slash"的拼写错误)。
  6. func _ready():定义 _ready()函数,这是Godot引擎的**生命周期回调函数**之一。当节点及其所有子节点加载完成、准备好开始运行时,会自动执行这个函数内的代码(通常用于初始化操作)。
  7. move_speed = 0.1123_ready()函数中,修改 move_speed变量的值为 0.1123(覆盖了之前的初始值 2.53)。
  8. game_over = true修改 game_over变量的值为 true(覆盖了之前的初始值 false)。
  9. ability = "attack"修改 ability变量的值为 "attack"(覆盖了之前的初始值 "slassh")。
  10. print(move_speed)调用 print()函数,在控制台输出 move_speed当前的值(此时已被修改为 0.1123)。
  11. print(game_over)输出 game_over当前的值(此时已被修改为 true)。
  12. print(ability)输出 ability当前的值(此时已被修改为 "attack")。

最后将修改后的值打印到控制台。运行后,控制台会输出:0.1123trueattack

运算符

extends Node2D

var score :int = 0
var speed :float = 5.5
var text : String = "First"

func _ready():
        score = 10
        score +=1
        score -=5
        score *=2
        score /=4
        print(5)
    
        speed *=2.548
        speed /= 2.09
        print(speed)
    
        text +="second"
        print(text)
    


输出结果
5
6.70526315789474
Firstsecond

条件

extends Node2D

var score : int = 10

func _ready():
        if score == 10:
                print("socre is 10")
        if score > 5 :
                print("score is greater than")
        var a :int = 100
        var b: int = 100
        if a < b:
                print("a is less than b")
        if a != b:
                print("a is not b")


输出:socre is 10
score is greater than

函数

extends Node2D

func _ready():
        _add(5,8)
func  _process(delta):
        pass
func  _add(a,b):
        var sum = a+b
        print(sum)
func _welcome_message():
        print("welcome")
extends Node2D

func _ready():
        var result = _add(33,91)
        print(result)
func  _process(delta):
        pass
func  _add(a:float,b:float):
        var sum:float = a+b
        return sum
    
func _welcom_message():
        print("wqdadada")

题目

extends Node2D

func _ready():
        var game_over = _has_won(120)
        print(game_over)
func  _process(delta):
        pass

func _has_won(score:int) -> bool:
        if score > 100:
                return true
        else:
                return false

向量

自己移动

extends Sprite2D

func _process(delta):
        position .x+=1
#向右自动移动
extends Sprite2D


#调节速度
var speed : float = 100


func _process(delta):
        var direction = Vector2(0,1)
        position += direction * delta *speed   #方向向量 × 时间间隔(delta) × 速度(speed)

1. extends Sprite2D

声明当前脚本继承自 Sprite2D节点。Sprite2D是 Godot 中用于显示 2D 图像(如角色、道具、背景元素等)的基础节点,自带 position(位置)、texture(纹理,即显示的图片)等属性。继承后,附加该脚本的节点会拥有 Sprite2D的所有功能。

2. var speed : float = 100

定义一个浮点型变量 speed,初始值为 100,注释 “调节速度” 说明其作用是控制精灵的移动速度(单位:像素 / 秒)。

3. func _process(delta):

_process(delta)是 Godot 的每帧回调函数(默认每帧执行一次,帧率通常为 60 帧 / 秒)。

  • 参数 delta:当前帧与上一帧的时间间隔(单位:秒),用于确保移动 / 逻辑在不同帧率下速度一致(例如,高帧率时 delta小,低帧率时 delta大,乘以 delta后移动距离会和实际时间挂钩,而非帧数)。
  1. 函数内部逻辑
  • var direction = Vector2(0, 1):定义一个 2D 方向向量 directionVector2(x, y)中,x控制水平方向(正数向右,负数向左),y控制垂直方向(Godot 中 Y 轴正方向是向下,所以 y=1表示向下,y=-1表示向上)。这里 (0,1)表示 “纯向下” 的方向。
  • position += direction * delta * speed:更新精灵的位置。
    • positionSprite2D的位置属性(Vector2类型),表示精灵在 2D 场景中的坐标。
    • 计算逻辑:方向向量 × 时间间隔(delta) × 速度(speed),得到 “当前帧应该移动的距离”,再叠加到当前位置上。
    • 实际效果:精灵会以每秒 100像素的速度持续向下移动(因为 direction是向下,且每帧都会执行该逻辑)。

整体效果

当脚本附加到一个 Sprite2D节点上后,运行场景时,该精灵会从初始位置开始,以每秒 100 像素的速度一直向下移动(直到移出屏幕或被其他逻辑停止)。

硬币收藏家游戏

控制玩家上下左右脚本

extends CharacterBody2D
# 继承CharacterBody2D节点(Godot 4 2D角色移动核心节点,自带物理移动、碰撞检测功能,脚本需挂载到该节点上)

var speed : float = 100
# 声明全局浮点型变量speed,初始化值100(单位:像素/秒,控制角色移动快慢)

func _physics_process(delta):
# 物理帧回调函数(固定60次/秒调用,不受帧率影响,专门处理移动、碰撞等物理逻辑;delta是帧间隔时间,此处由move_and_slide自动适配)
        velocity.x = 0
# 重置水平速度为0(避免松开方向键后角色因残留速度滑行,实现"松键即停")
        velocity.y = 0
# 重置垂直速度为0(同理,清空垂直方向残留速度)
        if Input.is_key_pressed(KEY_RIGHT):
# 检测右方向键是否被持续按压(is_key_pressed返回bool值,按住时每帧为true)
                velocity.x += speed
# 水平速度 += 移动速度(x正方向=右,此时velocity.x=100,角色向右移动)
        if Input.is_key_pressed(KEY_LEFT):
# 检测左方向键是否被持续按压
                velocity.x -= speed
# 水平速度 -= 移动速度(x负方向=左,此时velocity.x=-100,角色向左移动)
        if Input.is_key_pressed(KEY_UP):
# 检测上方向键是否被持续按压(Godot 2D默认y轴向下为正,上对应y负方向)
                velocity.y -= speed
# 垂直速度 -= 移动速度(此时velocity.y=-100,角色向上移动)
        if Input.is_key_pressed(KEY_DOWN):
# 检测下方向键是否被持续按压
                velocity.y += speed
# 垂直速度 += 移动速度(此时velocity.y=100,角色向下移动)
            
        move_and_slide()
# CharacterBody2D内置移动方法:根据velocity计算移动距离,自动处理碰撞(需搭配CollisionShape2D),触发角色实际移动

这段代码是基于Godot引擎的GDScript脚本,功能是实现一个"触发区域"的逻辑,具体解析如下:

1. 基础结构:extends Area2D

  • 表示当前脚本所附加的节点类型是 Area2D(2D碰撞区域节点)。
  • Area2D是Godot中用于碰撞检测的节点,它本身不参与物理碰撞响应(不会被推开),但可以检测其他物体进入/离开该区域,常用于实现"触发器"效果(比如踩陷阱、触碰道具等)。

2. 核心函数:_on_body_entered(body)

  • 这是一个**信号回调函数**,对应 Area2D节点的 body_entered信号。
  • 当有其他"物理体节点"(如 KinematicBody2DRigidBody2D等带有碰撞体的节点)进入当前 Area2D的碰撞区域时,会自动触发该函数。
  • 参数 body:表示进入区域的那个物理体节点(即被检测到的物体)。

3. 逻辑实现

  • body.scale.x += 0.2body.scale.y += 0.2

修改进入区域的物体(body)的缩放比例。scale是节点的缩放属性,xy分别对应水平和垂直方向的缩放倍数。这里是在原缩放基础上各增加0.2,即让进入的物体"变大一点"。

  • queue_free()

销毁当前 Area2D节点(将自身从场景中移除)。这确保该区域只会触发一次效果(触发后自己消失,不会重复检测)。

注意事项

  • 要使该逻辑生效,需要在Godot编辑器中手动将 Area2Dbody_entered信号连接到脚本中的 _on_body_entered函数(否则信号不会触发)。
  • Area2D和进入的 body都必须添加碰撞形状(如 CollisionShape2DCollisionPolygon2D),否则无法检测到碰撞。

总结

这段代码实现了一个"一次性放大触发器":当任何物理体进入该 Area2D区域时,会被放大(x和y方向各增加0.2倍缩放),随后触发器自身会销毁,不再生效。

金币脚本

extends Area2D


func _on_body_entered(body):
        body.scale.x +=0.2
        body.scale.y +=0.2
    
        queue_free()

这段代码是基于Godot引擎的GDScript脚本,用于实现一个由方向键控制的2D角色移动逻辑,具体解析如下:

1. 基础结构:extends CharacterBody2D

  • 表示当前脚本附加的节点类型是 CharacterBody2D
  • CharacterBody2D是Godot中专门用于处理**角色移动**的物理节点,适合实现玩家控制的角色(如平台游戏主角、顶视角角色等),它自带碰撞处理和移动方法,比普通节点更适合角色逻辑。

2. 变量定义:var speed : float = 100

  • 定义了一个浮点型变量 speed,值为100,用于控制角色的移动速度(单位通常是“像素/秒”,即每秒移动100像素)。
  • 变量类型标注 : float是可选的,但能提高代码可读性和编辑器的类型提示能力。

3. 核心函数:_physics_process(delta)

  • 这是Godot的**物理帧更新函数**,每帧调用一次(帧率与物理引擎同步,通常默认60帧/秒)。
  • 参数 delta表示上一帧到当前帧的时间间隔(单位:秒),用于确保移动速度不受帧率波动影响(比如低帧率时移动距离会自动补偿,保持实际速度一致)。

4. 移动逻辑实现

  • 重置速度velocity.x = 0velocity.y = 0

velocityCharacterBody2D自带的属性(Vector2类型),表示节点的运动速度(x为水平方向,y为垂直方向)。

每次物理帧先重置速度为0,避免角色在没有输入时继续“惯性移动”。

  • 处理方向键输入
    • 右键(KEY_RIGHT):velocity.x += speed → 水平速度增加 speed,角色向右移动。
    • 左键(KEY_LEFT):velocity.x -= speed → 水平速度减少 speed(即负方向),角色向左移动。
    • 上键(KEY_UP):velocity.y -= speed → 垂直速度减少 speed(Godot中y轴向下为正,所以负y是向上),角色向上移动。
    • 下键(KEY_DOWN):velocity.y += speed → 垂直速度增加 speed,角色向下移动。
      这里支持**八方向移动**(比如同时按上和右,角色会斜向移动,此时 velocity的x和y分量都有值)。
  • 执行移动move_and_slide()

这是 CharacterBody2D的核心移动方法,作用是:

  • 根据 velocity计算移动距离(自动结合 delta时间,无需手动乘以 delta);
  • 自动检测碰撞(如果碰到障碍物,会沿碰撞边缘滑动或停止,避免穿墙);
  • 适合实现角色在地面、平台上的移动(比如不会掉穿地面)。

注意事项

  • 要使移动生效,CharacterBody2D必须添加碰撞形状(如 CollisionShape2D),否则无法检测碰撞,可能导致角色“穿墙”。
  • move_and_slide()会自动处理速度与时间的关系,因此代码中无需手动写 velocity *= delta
  • 若需要限制斜向移动速度(避免斜向比直线快,因为勾股定理会导致斜向速度实际为 √(speed² + speed²) ≈ 1.414*speed),可以在移动前对 velocity归一化,例如:velocity = velocity.normalized() * speed(但需注意静止时的特殊处理)。

总结

这段代码实现了一个基础的“方向键控制角色移动”功能:通过 _physics_process实时检测方向键输入,计算角色速度,再通过 move_and_slide完成带碰撞处理的移动,适合顶视角或简单平台游戏的角色控制。

导出游戏

Godot迷你项目

(3D)气球爆破者

初步

气球逐渐变大

ballon.gd:管 “单个气球” 的交互(点击、缩放、销毁),是 “子模块”;

extends Area3D

# 气球副本
@export var clicks_to_pop : int = 5  #引爆所需点击次数
@export var size_increase : float = 0.2  # 次点击的尺寸增加量 
@export var score_to_give : int = 1  #  引爆后给予的分


func _on_input_event(camera, event, event_position, normal, shape_idx):
        if event is not InputEventMouseButton:
                return
            
        if event.button_index != MOUSE_BUTTON_LEFT:
                return
        if not event_position:
                return
        scale = Vector3.ONE * size_increase
        clicks_to_pop -=1
        if clicks_to_pop == 0:
                queue_free()

下面逐行拆解这段 ballon.gd 代码(基于 Godot 4 语法),结合 Godot 引擎特性和脚本逻辑,从“是什么”“为什么这么写”“注意点”三个维度解析,新手也能看懂~

1. 脚本继承声明

extends Area3D
  • 作用:指定当前脚本的父类是 Area3D 节点。
  • 关键说明
    • Area3D 是 Godot 专门用于「检测交互/碰撞」的 3D 节点,**本身不会有物理刚体的碰撞效果**(比如不会被推走、不会掉落),但能捕捉鼠标点击、射线检测等事件——完美适配“点击气球”的需求(只需要检测点击,不需要物理碰撞)。
    • 脚本必须绑定到场景树中的 Area3D 节点上才能生效(比如新建 Area3D 节点,给它挂载这个脚本)。

2. 导出变量声明(3行)

这3行是「可配置参数」,用 @export 标记后,在编辑器中能直接调整,不用改代码。

第1个导出变量

@export var clicks_to_pop : int = 5  #引爆所需点击次数
  • 逐部分解析
    • @export:Godot 关键字,让变量在编辑器的「检查器」面板中显示,支持可视化修改(比如把 5 改成 3,不用动代码)。
    • var clicks_to_pop:声明变量名,含义是“引爆气球需要的点击次数”。
    • : int:指定变量类型为「整数」(避免传入小数导致逻辑错误)。
    • = 5:默认值为 5(初始状态下,气球需要点击 5 次才会爆)。
    • # 注释:后面的文字是代码注释,不会执行,用于说明变量用途,方便自己/他人看懂代码。

第2个导出变量

@export var size_increase : float = 0.2  # 次点击的尺寸增加量 
  • 逐部分解析
    • size_increase:变量名,含义是“每次点击后气球的尺寸增加量”。
    • : float:变量类型为「浮点数」(支持小数,比如 0.2、0.15)。
    • = 0.2:默认每次点击放大 0.2 倍(注意:这里有个**潜在错误**,后面会详细说)。
    • 注释漏了“每”字,实际含义是“每次点击的尺寸增加量”。

第3个导出变量

@export var score_to_give : int = 1  #  引爆后给予的分
  • 逐部分解析
    • score_to_give:变量名,含义是“气球引爆后应该给玩家加的分数”。
    • : int:整数类型(分数通常是整数)。
    • = 1:默认每次爆气球加 1 分。
    • 注释多了个空格,不影响执行,只是格式问题。

3. 输入事件回调函数(核心逻辑)

func _on_input_event(camera, event, event_position, normal, shape_idx):
  • 作用Area3D 节点的「内置信号回调函数」——当鼠标在这个 Area3D 节点的范围的内发生输入事件(点击、移动、滚轮等)时,Godot 会自动调用这个函数。
  • 关键说明
    • 函数名不能乱改:必须是 _on_input_event(这是 Godot 约定的信号回调名),且需要在编辑器中「连接信号」才能生效(步骤:选中 Area3D 节点 → 右侧「信号」面板 → 找到 input_event → 连接到当前脚本的这个函数)。
    • 参数不用手动传:Godot 会自动传入 5 个参数(新手不用深究所有参数,重点看 eventevent_position):
      • camera:当前渲染场景的相机节点(比如玩家视角的相机)。
      • event:具体的输入事件(比如“鼠标左键按下”“鼠标移动”)。
      • event_position:点击在 Area3D 节点上的本地位置(是否有效代表“是否真的点到了气球”)。
      • normal:点击位置的表面法向量(3D 场景中用于判断点击方向,这里用不上)。
      • shape_idx:如果 Area3D 有多个碰撞形状,用于区分点击的是哪个形状(这里气球通常只有一个碰撞形状,用不上)。

4. 事件过滤逻辑(3个 if 判断)

这3行的核心目的是:**只保留“有效点击”(鼠标左键、点在气球上),过滤掉所有无效事件**。

第1个过滤:只保留鼠标按钮事件

if event is not InputEventMouseButton:
        return
  • 作用:判断当前输入事件是不是“鼠标按钮事件”(比如左键点击、右键点击、中键点击)。
  • 逻辑
    • 如果是「非鼠标按钮事件」(比如鼠标移动、键盘按键、滚轮滚动),就执行 return(直接退出函数,后面的代码不执行)。
    • 举例:鼠标划过气球(没点击)、按键盘 A 键,都不会触发后续逻辑。

第2个过滤:只保留鼠标左键

if event.button_index != MOUSE_BUTTON_LEFT:
        return
  • 作用:在“鼠标按钮事件”中,只保留「左键点击」,过滤右键、中键等。
  • 关键说明
    • event.button_index:获取鼠标按钮的类型(Godot 内置枚举:MOUSE_BUTTON_LEFT=左键,MOUSE_BUTTON_RIGHT=右键,MOUSE_BUTTON_MIDDLE=中键)。
    • 逻辑:如果点击的不是左键,就退出函数,后续代码不执行。

第3个过滤:只保留有效点击位置

if not event_position:
        return
  • 作用:判断点击位置是否有效(避免“鼠标刚好在气球边缘”“碰撞形状异常”导致的无效点击)。
  • 逻辑:如果 event_position 是无效值(比如 Vector3.ZERO 且无实际意义),就退出函数——确保只有“真的点到气球上”才会触发后续逻辑。

5. 气球缩放逻辑

scale = Vector3.ONE * size_increase
  • 作用:每次有效点击后,调整气球的尺寸。
  • 逐部分解析
    • scale:节点的缩放属性(Vector3 类型,(x,y,z) 分别代表x、y、z轴的缩放比例,默认 (1,1,1) 是原始尺寸)。
    • Vector3.ONE:Godot 内置常量,等价于 Vector3(1,1,1)(原始缩放比例)。
    • * size_increase:乘以尺寸增加量(默认 0.2),结果是 (0.2,0.2,0.2)
  • 关键问题(之前你遇到的“越点越小”的根源)
    • 这行代码是「直接覆盖缩放值」,而不是「在原有缩放基础上累加」。
    • 比如初始缩放是 1,第一次点击后被设为 0.2(变小),之后每次点击都保持 0.2——所以气球会越点越小,且不会继续变大。
    • 正确写法scale += Vector3.ONE * size_increase(用 += 累加,每次在当前尺寸上放大 0.2 倍)。

6. 减少点击次数 & 销毁气球

clicks_to_pop -=1
  • 作用:每次有效点击后,把“剩余点击次数”减 1。
  • 举例:初始 clicks_to_pop=5,第一次点击后变成 4,第二次变成 3,直到减到 0。
if clicks_to_pop == 0:
        queue_free()
  • 作用:当剩余点击次数为 0 时,销毁气球节点。
  • 关键说明
    • queue_free():Godot 中安全销毁节点的方法(会等待当前帧结束后再销毁,避免出现“节点还在但已失效”的异常),比直接用 free() 更安全。
    • 逻辑:气球被点击足够次数后,从场景树中移除,视觉上“消失”。

整体逻辑流程总结

当你在游戏中点击气球时,代码会按以下顺序执行:

  1. 检测是否是「鼠标左键点击」且「真的点到了气球」;
  2. 是 → 调整气球缩放(当前错误逻辑:设为 0.2 倍,变小);
  3. 剩余点击次数减 1;
  4. 如果次数减到 0 → 销毁气球。

必须补充的2个关键注意点(否则脚本可能无效)

  1. 信号必须连接_on_input_event 是信号回调,必须在编辑器中把 Area3Dinput_event 信号连接到这个函数,否则点击气球没任何反应。
  2. 碰撞形状必须添加Area3D 本身没有“可点击范围”,需要给它添加子节点(比如 SphereShape3D 球体碰撞形状),且碰撞形状的大小要和气球模型匹配,否则点击不到。

balloon_popoerMain.gd:管 “全局分数” 的存储和更新,是 “管理模块”;

extends Node3D
var  score:int  = 0
func  increase_score(amount : int):
        score += amount
        print(score)

分数计数

balloon_popoerMain.gd

extends Node3D

var score : int  = 0
var score_text : Label


func _ready():
        score_text = $ScoreText  # 第6行:统一用4个空格缩进(删除原混合缩进)
        score_text.text = " 分数 : 0 "
func increase_score(amount : int):
        score += amount
        score_text.text = "分数: " + str(score)  # 补充空格,代码更规范(非报错必需)

下面逐行解析这段 **Godot 4 的 GDScript 代码**,结合语法规则、Godot 引擎特性和代码功能,从基础到细节讲清楚每一行的作用:

整体背景

这段代码是一个挂载在 Node3D 节点上的脚本,核心功能是 **管理游戏分数**:初始化分数显示、提供加分方法、实时更新分数文本(对应场景中一个叫 ScoreTextLabel 节点)。

逐行解析

1. extends Node3D

  • 语法作用:GDScript 的「继承声明」,指定当前脚本的父类是 Node3D
  • 实际意义
    • Node3D 是 Godot 3D 场景的基础节点,自带「位置、旋转、缩放」等 3D 空间属性。
    • 脚本挂载到任何 Node3D 及其子类节点(如 CharacterBody3DStaticBody3D)上都能生效,脚本会继承 Node3D 的所有功能(比如 global_position 位置属性、rotate() 旋转方法)。
  • 注意:必须放在脚本第一行,且只能有一个继承声明。

2. var score : int = 0

  • 语法作用:声明一个「带类型注解的全局变量」。
    • var:GDScript 声明变量的关键字(类似 Python 的 var/let)。
    • score:变量名(自定义,语义是“分数”)。
    • : int:类型注解,指定变量是「整数类型」(GDScript 是弱类型语言,可省略,但加注解更规范、能触发编辑器语法检查)。
    • = 0:初始化赋值,分数初始值设为 0。
  • 实际意义:全局存储游戏分数,整个脚本的所有函数都能访问和修改它。

3. var score_text : Label

  • 语法作用:声明一个「未初始化的 Label 类型全局变量」。
    • : Label:类型注解指定变量是 Label 节点类型(Label 是 Godot 用于显示文本的基础节点,核心属性是 .text)。
    • 未赋值:因为 Label 节点是「场景中的可视化节点」,需要等场景加载完成后才能通过路径找到,所以这里先声明“要用到这个节点”,后续在 _ready() 中初始化。
  • 实际意义:保存场景中显示分数的 Label 节点引用,后续通过这个变量操作文本显示(比如更新分数)。

4. 空白行

  • 作用:无语法意义,纯粹是「代码分隔符」,让变量声明和函数定义之间有视觉间隔,提升代码可读性(GDScript 忽略空白行,建议养成用空白行分隔代码块的习惯)。

5. func _ready():

  • 语法作用:Godot 的「生命周期回调函数」(特殊函数,由 Godot 自动调用,无需手动调用)。
  • 核心规则
    • 当脚本所在节点 **及其所有子节点都加载完成后**,Godot 会自动执行 _ready() 里的代码(仅执行一次,相当于“初始化函数”)。
    • 函数名 _ready 是固定的(以下划线开头,Godot 内置回调),不能自定义。
  • 实际意义:用于脚本初始化操作(比如查找场景节点、设置初始状态)。

6. score_text = $ScoreText

  • 语法作用:给 score_text 变量赋值,通过「节点路径」找到场景中的 Label 节点。
    • $:Godot 特有的「节点路径查找运算符」,等价于 get_node() 方法,用于查找「当前节点的子节点」(或相对路径节点)。
    • ScoreText:是你在场景编辑器中给 Label 节点起的「名称」(必须和场景中节点名称完全一致,大小写敏感)。
  • 实际意义:把场景中显示文本的 Label 节点“绑定”到脚本的 score_text 变量上,后续通过 score_text 就能操作这个节点(比如改文本、改颜色)。
  • 补充:之前的缩进错误就是这里导致的,现在已统一用 4 个空格缩进(GDScript 要求函数内代码必须缩进,且不能混合 Tab 和空格)。

7. score_text.text = " 分数 : 0 "

  • 语法作用:修改 Label 节点的 text 属性,设置初始显示文本。
    • score_text:已绑定的 Label 节点对象。
    • .textLabel 节点的核心属性,用于控制显示的字符串内容。
    • " 分数 : 0 ":字符串字面量,前后的空格是为了美观(非语法必需,可去掉写成 "分数:0")。
  • 实际意义:游戏启动时,分数文本框默认显示“ 分数 : 0 ”,告诉玩家初始分数是 0。

8. func increase_score(amount : int):

  • 语法作用:声明一个「自定义函数」,用于实现“增加分数”的功能。
    • func:GDScript 声明函数的关键字。
    • increase_score:函数名(自定义,语义是“增加分数”,建议用下划线命名法,符合 GDScript 规范)。
    • (amount : int):函数参数,amount 是参数名(表示“增加的分数值”),: int 是类型注解(指定参数必须是整数)。
  • 实际意义:提供一个可复用的“加分接口”,其他脚本或当前脚本可通过调用这个函数,传入要加的分数(比如 increase_score(10) 就是加 10 分)。

9. score += amount

  • 语法作用:「复合赋值运算」,等价于 score = score + amount
    • score:全局变量(当前分数)。
    • +=:加赋值运算符,把右边的 amount(增加的分数)加到左边的 score 上,更新 score 的值。
  • 实际意义:修改全局分数(比如当前分数是 0,调用 increase_score(5) 后,score 就变成 5)。

10. score_text.text = "分数: " + str(score)

  • 语法作用:更新 Label 节点的文本,显示最新分数。
    • str(score):类型转换函数,把整数类型的 score 转为字符串(因为 .text 属性只接受字符串,不能直接拼接整数和字符串)。
    • "分数: " + str(score):字符串拼接,把固定文本“分数: ”和转换后的分数字符串连起来(比如 score=5 时,结果是“分数: 5”)。
  • 实际意义:分数更新后,实时刷新文本显示,让玩家能看到最新分数。
  • 补充:这里的空格(“分数: ”)是为了排版美观,非必需,可根据需求调整。

代码逻辑串联(整体流程)

  1. 游戏启动 → 场景加载完成 → Godot 自动调用 _ready()
  2. _ready() 中:
    1. 找到场景中的 ScoreText(Label 节点),绑定到 score_text 变量;
    2. score_text 设置初始文本“ 分数 : 0 ”;
  3. 游戏过程中(比如玩家捡道具、杀敌人),调用 increase_score(amount) 函数(比如 increase_score(10));
  4. 函数执行:
    1. amount 加到 score 上(更新分数);
    2. 把新分数转为字符串,拼接后更新 score_text 的文本,玩家看到分数变化。

关键注意点(新手容易踩坑)

  1. 节点名称匹配:$ScoreText 必须和场景中 Label 节点的名称完全一致(大小写、空格都不能错),否则会报“节点未找到”错误;
  2. 缩进规范:函数内代码必须缩进(推荐 4 个空格),不能混合 Tab 和空格(之前的报错根源);
  3. 类型转换:score 是整数,必须用 str(score) 转为字符串才能拼接,否则会报错;
  4. 全局变量:scorescore_text 是全局变量(在函数外声明),所有函数都能访问;如果声明在函数内,就是局部变量,其他函数无法使用。

(2D)内部物理小游戏

# 1. 类继承声明:当前脚本挂载的节点必须是 RigidBody2D 或其派生类(如 CharacterBody2D 不适用)
# 作用:让脚本拥有 RigidBody2D 的所有内置属性(如 global_position、mass)和方法(如 apply_impulse)
extends RigidBody2D

# 2. 变量定义:声明一个用于控制冲量大小的浮点型变量
# hit_force:变量名(语义化命名,表“撞击力”);float:类型标注(指定为浮点型,可选但推荐,提升代码可读性)
# 50.0:初始值(冲量的基础大小,值越大,物体被推动的速度越快)
var hit_force : float = 50.0

# 3. 帧更新回调函数:每帧(与帧率同步,如60帧/秒)自动调用一次,用于处理非物理相关的逻辑
# _process:Godot 内置回调函数名,不可自定义;delta:参数(帧间隔时间,单位秒,用于帧率补偿)
# 🔴 注意:RigidBody2D 是物理体,物理操作(如施加冲量)不推荐放这里,建议改用 _physics_process(与物理引擎同步)
func _process (delta):
    # 4. 输入检测条件:判断鼠标左键是否被按住
    # Input:Godot 输入系统的全局类(提供所有输入相关方法)
    # is_mouse_button_pressed:Input 类的静态方法(检测指定鼠标按键是否处于“按住”状态)
    # MOUSE_BUTTON_LEFT:Godot 内置常量(表“鼠标左键”,其他可选值如 MOUSE_BUTTON_RIGHT 是右键)
    if Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT):
        # 5. 获取鼠标全局位置:获取当前鼠标在屏幕上的全局坐标(Vector2 类型,含 x/y 轴)
        # get_global_mouse_position():节点的内置方法(无论节点层级,直接返回全局坐标,避免局部坐标计算错误)
        var mouse_pos = get_global_mouse_position()
        # 6. 计算方向向量:获取“当前节点”指向“鼠标位置”的单位向量(长度为1,只保留方向信息)
        # global_position:节点的内置属性(当前节点的全局坐标,与 mouse_pos 坐标体系一致)
        # direction_to(mouse_pos):Vector2 类的方法(计算从自身到目标点的单位向量,自动归一化,避免距离影响力的大小)
        var dir = global_position.direction_to(mouse_pos)
    
        # 7. 施加冲量:给 RigidBody2D 施加瞬时力,使其产生运动
        # apply_impulse:RigidBody2D 的内置方法(专门用于施加冲量,瞬时改变物体速度)
        # 🔴 原代码错误:该方法需要 2 个参数,原代码只传了 1 个(会导致运行报错)
        # 正确格式:apply_impulse(作用点, 冲量向量)
        # 作用点:相对节点自身的坐标(如 Vector2.ZERO 表示重心);冲量向量:dir(方向)* hit_force(大小)
        apply_impulse(dir * hit_force)

(3D)3D滑雪小游戏

# 声明当前脚本继承自 3D 刚体节点(用于模拟物理运动的核心节点)
extends RigidBody3D

# @export 让变量可在编辑器面板修改,定义移动速度(浮点型,默认值 2.0)
@export var move_speed : float = 2.0

# 物理帧更新函数(默认 60 次/秒,专门处理物理相关逻辑)
# delta:物理帧时间间隔,用于抵消不同设备帧率差异(此处未直接使用)
func _physics_process(delta):
        # 检测物理按键「方向右键」是否按下(物理按键检测更适配跨平台)
        if Input.is_physical_key_pressed(KEY_RIGHT):
                # 给刚体施加向右的力(Vector3.RIGHT = (1,0,0),乘以速度系数控制力的大小)
                apply_force(Vector3.RIGHT * move_speed)
        # 若右键未按下,检测物理按键「方向左键」是否按下
        elif Input.is_physical_key_pressed(KEY_LEFT):
                # 给刚体施加向左的力(Vector3.LEFT = (-1,0,0))
                apply_force(Vector3.LEFT * move_speed)

# 碰撞体进入当前刚体碰撞区域时触发的回调函数
# body:参数表示进入碰撞的那个节点(如 Tree 节点)
func _on_body_entered(body):
        # 判断碰撞的节点是否属于 "Tree" 分组(分组需在编辑器给目标节点设置)
        if body.is_in_group("Tree"):
                # 延迟重载当前场景(call_deferred 避免物理帧中修改场景树导致异常)
                get_tree().reload_current_scene.call_deferred()

reload_current_scene 是 Godot 引擎中 SceneTree 类的内置方法,属于引擎核心 API,专门用于重载(重启)当前正在运行的场景。下面详细拆解它的来源、调用逻辑和使用规则:

(2D)随机生成小星星

# 解析:声明当前脚本继承Node2D(2D节点基类),拥有position/scale/add_child等2D节点核心属性/方法,
#       脚本需挂载到场景中的Node2D(或其子类)节点上才能生效
extends Node2D

# 解析:@export标记让变量暴露到编辑器「检查器」面板,可可视化修改;
#       var声明变量spawn_count,:int指定整型类型,=200是默认值,控制星星生成总数
@export var spawn_count : int = 200

# 解析:声明变量star_scene并指定类型为PackedScene(Godot预制体场景类型);
#       preload()是预加载函数,脚本加载时就加载指定路径的星星预制体场景,避免运行时加载卡顿;
#       路径res://LoopsdotTSCN/star.tscn需确保和项目中星星场景的实际路径一致,否则会报资源找不到错误
var star_scene : PackedScene = preload("res://LoopsdotTSCN/star.tscn")

# 解析:_ready()是Godot内置生命周期函数,节点加入场景树且所有子节点加载完成后仅执行一次,
#       是初始化(如生成星星)的核心入口函数
func _ready():
    # 解析:for循环,i是循环变量(从0到spawn_count-1),循环次数等于spawn_count(默认200次),
    #       每次循环生成1颗星星,最终生成指定数量的星星
    for i in spawn_count:
        # 解析:调用PackedScene的instantiate()方法,实例化星星预制体,返回一个星星节点实例;
        #       此时星星节点还未加入场景树,仅在内存中
        var star = star_scene.instantiate()
        # 解析:调用当前Node2D节点的add_child()方法,将实例化的星星节点添加为自己的子节点;
        #       执行后星星才会显示在场景中,且继承当前节点的坐标/缩放等变换属性
        add_child(star)
    
        # 解析:给星星节点的position.x(x轴坐标)赋值,randf_range(-280,280)生成-280到280之间的随机浮点数;
        #       固定范围导致星星仅分布在x轴±280区域,是星星集中的核心原因之一
        star.position.x = randf_range(-280,280)
        # 解析:同理,给星星y轴坐标赋值,随机范围-150到150,范围过小加剧星星集中问题
        star.position.y = randf_range(-150,150)
    
        # 解析:生成0.5到5.0之间的随机浮点数,作为星星的缩放系数
        var star_scale = randf_range(0.5,5.0)
        # 解析:设置星星x轴缩放值为随机系数,控制星星宽度大小
        star.scale.x = star_scale 
        # 解析:设置星星y轴缩放值为同一随机系数,保证星星等比缩放(不拉伸变形)
        star.scale.y = star_scale