利用服务器进行优化
Scene System 来访问和使用的. 使用节点和资源可以简化复杂游戏中的项目组织和资产管理. 当然, 总是有缺点的:
- 那有一个额外复杂层
- 性能比直接使用简单API要低
- 无法使用多个线程来控制它们
- 需要更多的内存.
在很多情况下, 这并不是一个真正的问题(Godot是非常优化的, 大多数操作都是用信号处理的, 所以不需要轮询). 不过, 有时候还是会有这样的情况. 例如, 对于每一帧都需要处理的东西来说, 处理数以万计的实例可能是一个瓶颈.
这种情况会让程序员后悔自己使用的是游戏引擎, 希望能回到更加手动, 更加低层的游戏代码实现中去.
当然,Godot的设计工作中还是可以解决这个问题.
Servers
可选的 . 虽然目前还不能编译出来, 但完全可以绕过它. 核心是,Godot使用了Servers的概念. 它们是非常低级的API, 用来控制渲染, 物理, 声音等. 场景系统建立在它们之上, 直接使用它们. 最常见的服务器有: - VisualServer: 处理与图形相关的一切.
- PhysicsServer: 处理一切相关的3d物体.
- Physics2DServer: 处理一切相关的2D物理.
- AudioServer: 处理与音频相关的一切.
你只需研究它们的API, 就会意识到, 它们所提供的全部函数都是Godot允许你操作的低级实现.
RIDs (Resource ID)
RID )对象. 这些对象是服务实现的非公开的句柄. 它们是手动分配和释放的. 几乎服务中的每个功能都需要RID来访问实际的资源. Resource 的东西都可以直接指向RID(不过, 并不是所有资源都包含RID, 在这种情况下,RID会是空的). 事实上, 资源可以作为RID传递给服务API. 只要确保将资源的引用保留在服务之外, 因为如果资源被删除, 内部的RID也会被删除. 对于节点来说, 有很多函数功能可以使用: - CanvasItem.get_canvas_item() 方法将在服务器中返回画布项目RID.
- CanvasLayer.get_canvas() 方法将返回服务器中的canvas RID.
- Viewport.get_viewport_rid() 方法将返回服务器中的视口RID.
- World 资源(可在 Viewport 和 Spatial 节点中获得)包含获取 VisualServer Scenario 和 PhysicsServer Space 的函数. 这样就可以直接用服务API创建3D对象并使用它们.
- World2D 资源(可在 Viewport 和 CanvasItem 节点中获取)包含获取 VisualServer Canvas 和 Physics2DServer Space 的函数. 这样就可以直接用服务API创建2D对象并使用它们.
- VisualInstance 类, 可以分别通过 VisualInstance.get_instance() 和 VisualInstance.get_base() 来获取场景 instance 和 instance base .
RID 的功能.
不建议从已经有节点关联的对象中控制RID. 相反, 服务函数应始终用于创建和控制新的以及与现有的交互.
创建精灵
CanvasItem API移动它. GDScript
服务中的 Canvas Item API 允许您向其添加绘制基本单元. 一旦添加, 它们就不能被修改. 需要清除 Item, 并重新添加基本单元(设置变换时则不然, 变换可根据需要多次进行). 基本单元是这种方式被清除: GDScriptextends Node2D# VisualServer expects references to be kept around.var texturefunc _ready(): # Create a canvas item, child of this node. var ci_rid = VisualServer.canvas_item_create() # Make this node the parent. VisualServer.canvas_item_set_parent(ci_rid, get_canvas_item()) # Draw a texture on it. # Remember, keep this reference. texture = load("res://my_texture.png") # Add it, centered. VisualServer.canvas_item_add_texture_rect(ci_rid, Rect2(texture.get_size() / 2, texture.get_size()), texture) # Add the item, rotated 45 degrees and translated. var xform = Transform2D().rotated(deg2rad(45)).translated(Vector2(20, 30)) VisualServer.canvas_item_set_transform(ci_rid, xform)
VisualServer.canvas_item_clear(ci_rid)
将网格实例化到3D空间
3D的API与2D的API不同, 所以必须使用实例化API. GDScriptextends Spatial# VisualServer expects references to be kept around.var meshfunc _ready(): # Create a visual instance (for 3D). var instance = VisualServer.instance_create() # Set the scenario from the world, this ensures it # appears with the same objects as the scene. var scenario = get_world().scenario VisualServer.instance_set_scenario(instance, scenario) # Add a mesh to it. # Remember, keep the reference. mesh = load("res://mymesh.obj") VisualServer.instance_set_base(instance, mesh) # Move the mesh around. var xform = Transform(Basis(), Vector3(20, 100, 0)) VisualServer.instance_set_transform(instance, xform)
创建一个2D刚体并使用它移动精灵
Physics2DServer API创建一个 RigidBody2D, 并在物体移动时移动一个 CanvasItem. GDScript
RigidBody 和 PhysicsServer ).# Physics2DServer expects references to be kept around.var bodyvar shapefunc _body_moved(state, index): # Created your own canvas item, use it here. VisualServer.canvas_item_set_transform(canvas_item, state.transform)func _ready(): # Create the body. body = Physics2DServer.body_create() Physics2DServer.body_set_mode(body, Physics2DServer.BODY_MODE_RIGID) # Add a shape. shape = Physics2DServer.rectangle_shape_create() # Set rectangle extents. Physics2DServer.shape_set_data(shape, Vector2(10, 10)) # Make sure to keep the shape reference! Physics2DServer.body_add_shape(body, shape) # Set space, so it collides in the same space as current scene. Physics2DServer.body_set_space(body, get_world_2d().space) # Move initial position. Physics2DServer.body_set_state(body, Physics2DServer.BODY_STATE_TRANSFORM, Transform2D(0, Vector2(10, 20))) # Add the transform callback, when body moves # The last parameter is optional, can be used as index # if you have many bodies and a single callback. Physics2DServer.body_set_force_integration_callback(body, self, "_body_moved", 0)
从服务器获取数据
VisualServer,PhysicsServer或Physics2DServer请求任何信息. 这些服务器通常会为了性能而异步运行, 调用任何返回值的函数都会使它们停滞, 并迫使它们处理任何待处理的东西, 直到函数被实际调用. 如果你每一帧都调用它们, 这将严重降低性能(而且原因不会很明显). 正因为如此, 这类服务器中的大部分API都被设计成连信息都无法请求回来, 直到这是可以保存的实际数据.
