著作権ライセンス
このプラグインは、Action Game Makerにおいて、無料または商用のプロジェクトを問わず、あらゆる目的で無料で使用または修正することができます。
ただし、再配布はご遠慮ください。クレジット表記は必須ではありませんが、いただければ幸いです。
プラグインの効果
このプラグインノードの名前はJatkRotateToMovementです。
このノードは、各物理フレームごとにNode2Dを回転させ、特定のNode2Dソースオブジェクトが実際に移動した方向を向かせます。
これは以前JatkRotateToMovementDemoアクションとして提示されていた考え方のノード版です。アクション版は、行動をVS(ビジュアルスクリプト)のステートに組み込み、ステートによって開始と終了を制御する場合に適しています。一方、ノード版は、通常のGodotノードと同様に、回転処理をシーンツリー内の常駐コンポーネントとして使用する場合に適しています。
このプラグインは前後のフレーム間の位置差に基づいて方向を計算するため、velocity(速度)に依存しません。global_positionが時間とともに変化すれば、GameObjectやArea2DGameObject、さらには通常のNode2Dでも使用可能です。
要点
JatkRotateToMovement.gdをプロジェクト内の任意の場所に配置するだけで済みます- シーンに通常の
Nodeを追加し、このスクリプトをアタッチして、インスペクターで設定します movement_sourceは、移動方向を観察するNode2Dですnode_to_rotateは、実際に回転させたいNode2Dですmovement_sourceを空欄にすると、デフォルトで親Node2Dが運動源として使用されますnode_to_rotateを空欄にすると、優先的に親Node2Dが回転対象となります- したがって、コンポーネントをビジュアルモデルノードの下に配置し、
movement_sourceを移動中のキャラクターに向け、node_to_rotateを空欄にすることで、モデル自体を回転させることができます Instant(即時)とSmooth(滑らか)の2つの回転モードを使用できますrotation_speedはSmoothモードでのみ有効ですmin_displacement_squaredを使用して、非常に小さな振動による移動をフィルタリングできます
使用方法
手順
- 以下の
JatkRotateToMovement.gdスクリプト全体をコピーし、プロジェクト内の任意の場所に保存します。 - AGMaker/Godotがスクリプトクラスをリフレッシュするのを待ちます。
- 移動中のオブジェクト、または回転させたいビジュアル
Node2Dを選択します。 Ctrl+Aを押して通常のNodeを追加し、JatkRotateToMovement.gdをそのノードにアタッチします。- 必要に応じて
movement_source、node_to_rotate、rotation_mode、rotation_speed、min_displacement_squaredを設定します。 - このコンポーネントが、移動と回転を担当する同じ
Node2Dの下にアタッチされている場合、movement_sourceとnode_to_rotateの両方を空欄にできます。 - このコンポーネントがビジュアルモデルの下にあり、キャラクターオブジェクトの移動方向に従う場合は、
movement_sourceをキャラクターに向け、node_to_rotateを空欄にします。
パラメータの説明
movement_source
2フレーム間のグローバル位置の差を計算するために使用されるNode2D。空欄の場合、デフォルトで親Node2Dが使用されます。node_to_rotate
回転させる必要があるNode2D。空欄の場合、優先的に親Node2Dが使用されます。rotation_mode
Instantは現在の移動方向に即時に合わせます。Smoothは滑らかに回転します。rotation_speed
Smoothモードでのみ使用されます。数値が大きいほど、移動方向を追従する速度が速くなります。min_displacement_squared
最小移動距離の二乗しきい値。2フレーム間の移動距離の二乗がこの値より大きい場合のみ回転が発生します。二乗値を使用することで、余計な平方根計算を回避できます。
ノード版を使用すべき場合
この回転処理がシーンオブジェクト自体の一部であり、現在のVSステートに関係なく継続的に実行されるべき場合は、JatkRotateToMovementを使用します。
この回転処理が特定のVSステートによって開始および終了されるべき場合は、カスタムアクションJatkRotateToMovementDemoを使用します。
両方のバージョンのコアとなる考え方は同じです:velocityに依存せず、実際の移動に基づいて進行方向を導き出します。
スクリプト
class_name JatkRotateToMovement extends Node
enum RotationMode {
INSTANT,
SMOOTH,
}
@export var node_to_rotate: Node2D
@export var movement_source: Node2D
@export var rotation_mode: RotationMode = RotationMode.SMOOTH
@export var rotation_speed: float = 5.0
@export var min_displacement_squared: float = 0.0001
var _resolved_node_to_rotate: Node2D
var _resolved_movement_source: Node2D
var _previous_global_position: Vector2 = Vector2.ZERO
var _has_previous_global_position: bool = false
func _ready() -> void:
process_physics_priority = 100
_resolve_runtime_nodes()
func _physics_process(delta: float) -> void:
if _resolved_movement_source == null or not is_instance_valid(_resolved_movement_source):
_resolve_runtime_nodes()
return
if _resolved_node_to_rotate == null or not is_instance_valid(_resolved_node_to_rotate):
_resolved_node_to_rotate = _resolve_node_to_rotate()
if _resolved_node_to_rotate == null:
return
var current_global_position: Vector2 = _resolved_movement_source.global_position
if not _has_previous_global_position:
_previous_global_position = current_global_position
_has_previous_global_position = true
return
var displacement: Vector2 = current_global_position - _previous_global_position
_previous_global_position = current_global_position
if displacement.length_squared() < min_displacement_squared:
return
_apply_rotation_from_displacement(displacement, delta)
func _resolve_runtime_nodes() -> void:
_resolved_movement_source = _resolve_movement_source()
_resolved_node_to_rotate = _resolve_node_to_rotate()
_has_previous_global_position = false
if _resolved_movement_source == null:
printerr("[JatkRotateToMovement] movement_source is not set and parent is not a Node2D")
return
if _resolved_node_to_rotate == null:
printerr("[JatkRotateToMovement] node_to_rotate is not set and no fallback Node2D is available")
return
_previous_global_position = _resolved_movement_source.global_position
_has_previous_global_position = true
func _resolve_movement_source() -> Node2D:
if movement_source != null:
return movement_source
return get_parent() as Node2D
func _resolve_node_to_rotate() -> Node2D:
if node_to_rotate != null:
return node_to_rotate
var parent_node_2d: Node2D = get_parent() as Node2D
if parent_node_2d != null:
return parent_node_2d
if _resolved_movement_source != null:
return _resolved_movement_source
return _resolve_movement_source()
func _apply_rotation_from_displacement(displacement: Vector2, delta: float) -> void:
var target_angle: float = displacement.angle()
match rotation_mode:
RotationMode.INSTANT:
_resolved_node_to_rotate.global_rotation = target_angle
RotationMode.SMOOTH:
var current_angle: float = _resolved_node_to_rotate.global_rotation
var angle_diff: float = wrapf(target_angle - current_angle, -PI, PI)
var rotation_weight: float = minf(1.0, maxf(rotation_speed, 0.0) * maxf(delta, 0.0))
_resolved_node_to_rotate.global_rotation = current_angle + angle_diff * rotation_weight
JatkRotateToMovement.gd (3.0 KB)