You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过canvas_item_set_transform实现绕自身轴旋转?VisualServer复制Sprite节点时旋转位置偏移问题

Fixing Position Offset When Rotating VisualServer Canvas Items in Godot

Ah, I see the issue here—you're running into a classic transform order problem with Godot's Transform2D. When you apply rotation before translation, the translation happens in the rotated coordinate system, which shifts your sprite way off where you expect it to be. Let's break down how to fix this.

Why Your Current Code Fails

Godot applies Transform2D operations in the order: Scale → Rotate → Translate. When you call rotated() followed by translated(), the translation is applied relative to the rotated axes. So instead of moving your rotated sprite to the original position, you're moving it along the rotated X/Y directions, causing that unwanted shift.

To rotate a sprite around its own center, you need to adjust the transform origin to the sprite's center first, then rotate, then move it to the target position.

Corrected Implementation

Here's the fixed code with explanations:

ci_rid = VisualServer.canvas_item_create()
VisualServer.canvas_item_set_parent(ci_rid, get_canvas_item())

# First, save all needed sprite properties BEFORE freeing the node
# This avoids potential issues with accessing properties after the node is queued for deletion
var sprite_pos = sprite_node.position
var sprite_rot_deg = sprite_node.rotation_degrees
var sprite_region_enabled = sprite_node.region_enabled
var sprite_region_rect = sprite_node.region_rect
var sprite_texture_path = sprite_node.texture.resource_path

self.remove_child(sprite_node)
sprite_node.queue_free()

var texture = load(sprite_texture_path)
var pos_and_size = Rect2(Vector2(0, 0), sprite_region_rect.size)

# Draw the texture (with region if enabled)
if sprite_region_enabled:
    VisualServer.canvas_item_add_texture_rect_region(ci_rid, pos_and_size, texture, sprite_region_rect)
else:
    # Fallback for when region is disabled
    VisualServer.canvas_item_add_texture_rect(ci_rid, pos_and_size, texture)

# Calculate the offset from the texture's top-left corner to its center (our rotation pivot)
var pivot_offset = sprite_region_rect.size / 2

# Build the transform in the correct order:
# 1. Translate to move the origin to the texture's center
# 2. Rotate around that center
# 3. Translate again to move the rotated sprite to the original sprite's position
var transform_matrix = Transform2D.IDENTITY
    .translated(pivot_offset)
    .rotated(deg2rad(sprite_rot_deg))
    .translated(sprite_pos - pivot_offset)

VisualServer.canvas_item_set_transform(ci_rid, transform_matrix)

Key Changes Explained

  1. Save properties first: We grab all necessary sprite data before freeing the node to prevent any unexpected errors from accessing deallocated resources.
  2. Transform order: By first translating to the texture's center, we make the rotation happen around the sprite's own axis. Then, translating back to the original position (adjusted for the pivot offset) ensures the rotated sprite stays exactly where the original was.
  3. Fallback for disabled regions: Added a case for when the sprite's region isn't enabled to make the code more robust.

This should give you the expected result: a rotated sprite that stays anchored to its original position, rotating around its own center.

内容的提问来源于stack exchange,提问作者cak3_lover

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 18:43:12