本文へ移動
cccskills
無料GitHub で公開

math-essentials

Use when implementing game math — vectors, transforms, interpolation, curves, random number generation, and common geometric recipes

インストール方法を見る

含まれるファイル(4)

  • SKILL.md13.1 KB
  • references/curves-and-paths.md1.9 KB
  • references/game-math-recipes.md2.7 KB
  • references/random-numbers.md2.9 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Game Math in Godot 4.3+

All examples target Godot 4.3+ with no deprecated APIs. GDScript is shown first, then C#.

Related skills: player-controller for movement physics, ai-navigation for pathfinding math, camera-system for camera interpolation, tween-animation for easing curves, physics-system for collision math.


1. Vector Operations

Essential Vector Methods

MethodReturnsDescription
length()floatMagnitude of the vector
length_squared()floatSquared magnitude (faster, skip sqrt)
normalized()VectorUnit vector (length 1) in the same direction
distance_to(b)floatDistance between two points
distance_squared_to(b)floatSquared distance (faster for comparisons)
direction_to(b)VectorNormalized direction from this to b
angle_to(b)floatAngle in radians between two vectors
angle_to_point(b)floatAngle from this point to b (2D)
dot(b)floatDot product
cross(b)float/Vector3Cross product (2D returns float, 3D returns vector)
rotated(angle)Vector2Rotated by radians (2D)
move_toward(to, delta)VectorMove toward target by at most delta
clamp(min, max)VectorClamp each component
snapped(step)VectorSnap to grid
reflect(normal)VectorReflect off a surface
bounce(normal)VectorBounce off a surface (inverted reflect)
slide(normal)VectorSlide along a surface

Direction and Distance

# Get direction from A to B (normalized)
var dir: Vector2 = global_position.direction_to(target.global_position)

# Get distance
var dist: float = global_position.distance_to(target.global_position)

# Use squared distance for comparisons (faster — avoids sqrt)
if global_position.distance_squared_to(target.global_position) < detection_range * detection_range:
    chase_target()
Vector2 dir = GlobalPosition.DirectionTo(target.GlobalPosition);
float dist = GlobalPosition.DistanceTo(target.GlobalPosition);

if (GlobalPosition.DistanceSquaredTo(target.GlobalPosition) < detectionRange * detectionRange)
    ChaseTarget();

Dot Product

The dot product tells you how aligned two vectors are.

# Is the target in front of us? (dot > 0 = in front, < 0 = behind)
var forward: Vector2 = Vector2.RIGHT.rotated(rotation)
var to_target: Vector2 = global_position.direction_to(target.global_position)
var dot: float = forward.dot(to_target)

if dot > 0.7:  # roughly within ~45° cone
    print("Target is ahead")
elif dot < -0.7:
    print("Target is behind")
Vector2 forward = Vector2.Right.Rotated(Rotation);
Vector2 toTarget = GlobalPosition.DirectionTo(target.GlobalPosition);
float dot = forward.Dot(toTarget);

if (dot > 0.7f) GD.Print("Target is ahead");

Cross Product (3D)

The cross product gives a vector perpendicular to two input vectors.

# Get the surface normal from two edge vectors
var edge1: Vector3 = vertex_b - vertex_a
var edge2: Vector3 = vertex_c - vertex_a
var normal: Vector3 = edge1.cross(edge2).normalized()
Vector3 edge1 = vertexB - vertexA;
Vector3 edge2 = vertexC - vertexA;
Vector3 normal = edge1.Cross(edge2).Normalized();

2. Transforms

Transform2D

A 2D transform holds position, rotation, and scale.

# Get the global transform
var xform: Transform2D = global_transform

# Convert between local and global space
var local_point: Vector2 = to_local(global_point)
var world_point: Vector2 = to_global(local_point)

# Apply transform to a point
var transformed: Vector2 = xform * Vector2(10, 0)  # point in local space → global

# Inverse transform
var local: Vector2 = xform.affine_inverse() * global_point
Transform2D xform = GlobalTransform;
Vector2 localPoint = ToLocal(globalPoint);
Vector2 worldPoint = ToGlobal(localPoint);
Vector2 transformed = xform * new Vector2(10, 0);
Vector2 local = xform.AffineInverse() * globalPoint;

Transform3D & Basis

# Basis holds rotation and scale as 3 column vectors
var basis: Basis = global_transform.basis

# Forward direction (looking along -Z in Godot)
var forward: Vector3 = -basis.z
var right: Vector3 = basis.x
var up: Vector3 = basis.y

# Look at a target
look_at(target.global_position, Vector3.UP)

# Rotate around an axis
rotate_y(deg_to_rad(90.0))
rotate_object_local(Vector3.UP, deg_to_rad(45.0))

# Interpolate between two transforms (smooth transition)
var a: Transform3D = $Start.global_transform
var b: Transform3D = $End.global_transform
global_transform = a.interpolate_with(b, 0.5)  # halfway
Basis basis = GlobalTransform.Basis;
Vector3 forward = -basis.Z;
Vector3 right = basis.X;
Vector3 up = basis.Y;

LookAt(target.GlobalPosition, Vector3.Up);
RotateY(Mathf.DegToRad(90.0f));

Transform3D a = GetNode<Node3D>("Start").GlobalTransform;
Transform3D b = GetNode<Node3D>("End").GlobalTransform;
GlobalTransform = a.InterpolateWith(b, 0.5f);

is_orthonormal() (Godot 4.7+)

Basis.is_orthonormal() (const) returns true if the basis is orthogonal (axes perpendicular to each other) and normalized (every axis has length 1.0) — especially useful during physics calculations. It complements orthonormalized(): check first, and only re-orthonormalize when accumulated floating-point drift has denormalized the basis.

if not global_transform.basis.is_orthonormal():
    global_transform.basis = global_transform.basis.orthonormalized()
if (!GlobalTransform.Basis.IsOrthonormal())
{
    GlobalTransform = new Transform3D(
        GlobalTransform.Basis.Orthonormalized(), GlobalPosition);
}

3. Interpolation

lerp — Linear Interpolation

# Interpolate between two values (t = 0.0 to 1.0)
var mid: float = lerp(0.0, 100.0, 0.5)   # 50.0
var pos: Vector2 = lerp(start_pos, end_pos, 0.75)  # 75% of the way

# Smooth following — lerp with delta for frame-rate independence
func _process(delta: float) -> void:
    position = position.lerp(target_position, 5.0 * delta)
float mid = Mathf.Lerp(0.0f, 100.0f, 0.5f);
Vector2 pos = startPos.Lerp(endPos, 0.75f);

public override void _Process(double delta)
{
    Position = Position.Lerp(targetPosition, 5.0f * (float)delta);
}

Warning: lerp(a, b, speed * delta) is frame-rate dependent and never fully reaches the target. For precise movement, use move_toward() instead.

move_toward — Fixed-Speed Approach

# Move exactly `speed * delta` units toward target each frame
position.x = move_toward(position.x, target_x, speed * delta)

# Vector version
position = position.move_toward(target_position, speed * delta)
float newX = Mathf.MoveToward(Position.X, targetX, speed * (float)delta);
Position = Position.MoveToward(targetPosition, speed * (float)delta);

slerp — Spherical Interpolation

For smooth rotation interpolation (preserves arc, not straight line).

# Quaternion slerp for smooth 3D rotation
var current_quat: Quaternion = global_transform.basis.get_rotation_quaternion()
var target_quat: Quaternion = target_transform.basis.get_rotation_quaternion()
var result: Quaternion = current_quat.slerp(target_quat, 5.0 * delta)
global_transform.basis = Basis(result)
Quaternion currentQuat = GlobalTransform.Basis.GetRotationQuaternion();
Quaternion targetQuat = targetTransform.Basis.GetRotationQuaternion();
Quaternion result = currentQuat.Slerp(targetQuat, 5.0f * (float)delta);
GlobalTransform = new Transform3D(new Basis(result), GlobalPosition);

smoothstep — S-Curve Easing

# Returns 0.0 when x <= from, 1.0 when x >= to, smooth curve between
var t: float = smoothstep(0.0, 10.0, distance)  # 0→1 as distance goes 0→10

# Useful for soft thresholds (fog density, volume falloff)
var fog_intensity: float = smoothstep(50.0, 100.0, camera_distance)

cubic_interpolate — Smooth Path Following

# Smooth interpolation using 4 control points (catmull-rom style)
var point: Vector2 = p1.cubic_interpolate(p2, p0, p3, t)
# p0 = before start, p1 = start, p2 = end, p3 = after end

Interpolation Comparison

FunctionSpeedReaches TargetSmoothUse For
lerp(a, b, t)VariableOnly at t=1YesUI transitions, blending
move_toward()ConstantYesNoMovement, timers
slerp()VariableOnly at t=1YesRotation blending
smoothstep()S-curveSoft thresholdYesFog, volume, thresholds
cubic_interpolate()VariableOnly at t=1VeryPaths, camera rails

4. Curves and Paths

Curve resource for value-over-time (e.g., damage falloff curves). Path2D / Path3D for spatial paths sampled by PathFollow2D / PathFollow3D — use for moving platforms, missile guidance, camera rails.

See references/curves-and-paths.md for Curve setup, Path nodes, PathFollow properties.


5. Random Number Generation

Global functions (randf(), randi() % N, randf_range(a, b)) for one-shot randomness. RandomNumberGenerator for seeded, reproducible randomness (procgen, replay, save-state). Weighted selection via cumulative-sum or alias method.

See references/random-numbers.md for full GDScript on each pattern, plus FastNoiseLite for procedural generation noise.


6. Common Game Math Recipes

Five recipes: look at target (2D Vector2.angle_to_point), orbit around a point (polar coordinates), sine-wave bob (floating UI elements, treasure), angle wrapping (-PI..PI canonicalization), clamped approach with deadzone (analog input + small-input ignore).

See references/game-math-recipes.md for ready-to-use code on each recipe.


7. Common Pitfalls

SymptomCauseFix
lerp never reaches targetUsing lerp(a, b, speed * delta) each frameUse move_toward() for exact arrival
Rotation jumps at 180°Using lerp instead of lerp_angleAlways use lerp_angle() for angle interpolation
Object faces wrong direction (3D)Forgot Godot uses -Z as forwardForward direction is -global_transform.basis.z
Distance check too slowCalling distance_to on many objectsUse distance_squared_to and compare against range * range
Normalized zero vector crashesCalling normalized() on Vector2.ZEROCheck length() > 0 first, or use direction_to()
Transform interpolation looks wrongLerping euler angles instead of quaternionsUse Quaternion.slerp() or Transform3D.interpolate_with()
Random results repeat after restartUsing RandomNumberGenerator with fixed seedGodot 4.x auto-seeds global RNG; for RandomNumberGenerator use randomize() or set seed
Noise values are all ~0frequency too lowIncrease FastNoiseLite.frequency (try 0.01–0.1)

8. Implementation Checklist

  • Distance comparisons use distance_squared_to() for performance
  • Angle interpolation uses lerp_angle(), not lerp()
  • 3D forward direction is -transform.basis.z, not +z
  • move_toward() is used when exact arrival at target is needed
  • lerp(a, b, speed * delta) is understood as frame-rate dependent smooth following, not exact movement
  • RandomNumberGenerator is used for deterministic/seeded randomness (procedural generation, replays)
  • Noise-based generation uses FastNoiseLite with appropriate frequency and seed
  • Weighted random selection is used for loot tables and probability-based systems
  • Path following uses PathFollow2D/3D with progress or progress_ratio
  • Quaternion slerp is used for 3D rotation interpolation instead of euler angles

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Use when working with 2D-specific systems — TileMaps, parallax scrolling, 2D lights and shadows, canvas layers, particles 2D, custom drawing, and 2D meshes in Godot 4.3+

日本語の概要は準備中です。原文の説明を表示しています。

jame581/GodotPrompter8122026年10月12日 更新

Use when working with 3D-specific systems — materials, lighting, shadows, environment, global illumination, fog, LOD, occlusion culling, and decals in Godot 4.3+

日本語の概要は準備中です。原文の説明を表示しています。

jame581/GodotPrompter8122026年10月12日 更新

Use when building character abilities — Resource-based abilities with cost/cooldown/cast, buffs/debuffs, stat modifiers, gameplay tags, and HUD binding

日本語の概要は準備中です。原文の説明を表示しています。

jame581/GodotPrompter8122026年10月12日 更新

Use when creating Godot editor plugins — EditorPlugin, @tool scripts, custom inspectors, and dock panels

日本語の概要は準備中です。原文の説明を表示しています。

jame581/GodotPrompter8122026年10月12日 更新

Use when implementing AI movement — NavigationAgent2D/3D, steering behaviors, behavior trees, and patrol patterns

日本語の概要は準備中です。原文の説明を表示しています。

jame581/GodotPrompter8122026年10月12日 更新

Use when implementing animations — AnimationPlayer, AnimationTree, blend trees, state machines, sprite animation, and code-driven animation

日本語の概要は準備中です。原文の説明を表示しています。

jame581/GodotPrompter8122026年10月12日 更新

jame581 のスキルをすべて見る

このスキルの問題を報告する