ライセンス契約
このプラグインは、Action Game Maker 上で、無料プロジェクトか商用プロジェクトかを問わず、あらゆる目的で自由に使用または改変できます。ただし、再配布はしないでください。
クレジットの表示は必須ではありませんが、歓迎します。
プラグインの機能
このプラグインノードの名前は JatkRotateToMovement です。
その機能は、各物理フレームごとに Node2D を回転させ、選択された Node2D ソースの実際の移動変位方向を指すようにすることです。
これは、以前の JatkRotateToMovementDemo アクション案のノード版です。アクション版は、その挙動を VS ステート内部に保持させたい場合に便利です。一方、このノード版は、回転挙動を通常の Godot ノードと同様に、再利用可能なコンポーネントとしてシーンツリー内に保持させたい場合に便利です。
フレーム間の位置差分から方向を計算するため、velocity に依存しません。GameObject、Area2DGameObject、または時間とともに global_position が変化する任意の通常の 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
フレームごとのglobal_positionの差分を移動方向として使用するNode2Dです。空のままにすると、親のNode2Dが使用されます。node_to_rotate
回転させる対象となるNode2Dです。空のままにすると、まず親のNode2Dが使用されます。rotation_mode
Instantは現在の移動変位方向に即座に揃えます。Smoothは徐々にその方向へ回転させます。rotation_speed
Smoothモードでのみ使用されます。値が大きいほど回転が速く追従します。min_displacement_squared
最小の変位二乗閾値です。フレーム間の変位二乗がこの値より大きい場合のみ回転が発生します。二乗値を使用することで、不要な平方根計算を回避できます。
ノード版を使用するタイミング
回転挙動がシーンオブジェクト自体に属し、どの 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 が設定されておらず、親が Node2D ではありません")
return
if _resolved_node_to_rotate == null:
printerr("[JatkRotateToMovement] node_to_rotate が設定されておらず、代替となる Node2D が利用できません")
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)