Docs 4. Scripting



Overview

This document explains how to create and use scripts with objects in your engine. Scripts allow you to add custom behavior, logic, and event handling to your GameObjects and UI elements.

Scripts are attached to GameObject or UiElement instances via the Component base class. Each object can have multiple components/scripts that run in order.

Component Structure

namespace Engine.Scripting
{
    public abstract class Component
    {
        public Vector2 Position { get; set; }
        public Vector2 Size { get; set; }
        public bool Visible { get; set; }

        public virtual void Update(float deltaTime) { }
        public virtual void Render() { }
    }
}

All scripts inherit from Component and implement:

• Update(float deltaTime) - Called once per frame

• Render() - For rendering-specific logic (optional)

• Position, Size, Visible - Properties to access/modify

Creating Scripts

Basic Script Template

using OpenTK;
using Engine.Scripting;

namespace MyGame.Scripts
{
    public class MoveScript : Component
    {
        public float Speed { get; set; } = 100f;
        public Vector2 Direction { get; set; } = new Vector2(1f, 0f);

        public override void Update(float deltaTime)
        {
            Position += Direction * Speed * deltaTime;
        }
    }
}

Using with GameObject

// Create a GameObject
var player = new GameObject("Player", new Vector2(100, 100), new Vector2(50, 50));

// Add a script
var moveScript = new MoveScript();
player.AddComponent(moveScript);

// Add to workspace
workspace.Add(player);

Using with UI Elements

// Create a Button
var button = new Button("Click Me", texture, position, size);

// Add a script to handle click
var clickHandler = new ClickHandler();
button.AddComponent(clickHandler);

// Add to workspace
workspace.Add(button);

Properties and Events

Accessing Object Properties

Scripts have built-in properties to access the parent object:

public class ScriptExample : Component
{
    public void Update(float deltaTime)
    {
        // Access position, size, visibility
        Console.WriteLine($"Position: {Position}");
        Console.WriteLine($"Size: {Size}");
        Console.WriteLine($"Visible: {Visible}");

        // Modify properties
        Position += new Vector2(10, 0);
    }

Creating Events in Scripts

public class EventScript : Component
{
    public event Action? OnValueChanged;
    public event Action? OnEnterBounds;
    public event Action? OnExitBounds;

    public override void Update(float deltaTime)
    {
        if (Position.X > 500)
        {
            OnValueChanged?.Invoke();
        }
    }
}

Common Script Patterns

Movemnt Script

public class MovementScript : Component
{
    public Vector2 Speed { get; set; } = new Vector2(100, 100);
    public Vector2 TargetPosition { get; set; }
    public float MovementSpeed { get; set; } = 300f;

    public override void Update(float deltaTime)
    {
        // Smooth movement toward target
        var distance = TargetPosition - Position;
        if (distance.Length() > MovementSpeed * deltaTime)
        {
            Position += distance.Normalized() * MovementSpeed * deltaTime;
        }
        else
        {
            Position = TargetPosition;
        }
    }
}

Timer Script

public class TimerScript : Component
{
    public float Duration { get; set; } = 5f;
    public event Action<float>? OnTimeUpdate;
    public event Action? OnComplete;

    public override void Update(float deltaTime)
    {
        var progress = Duration - (Duration - deltaTime);
        OnTimeUpdate?.Invoke(progress);

        if (progress <= 0)
        {
            OnComplete?.Invoke();
        }
    }
}

Component Lifecycle

  1. Created - Component is instantiated and added to an object
  2. Updated - Update(deltaTime) called once per frame
  3. Visible - Visible property controls whether Render() is called
  4. Removed - Component removed from object's list

Best Practices

Keep Scripts Small and Focused

Each script should handle one specific behavior. Create separate scripts for:

• Movement

• Animation

• State changes

• Collision logic

• UI interactions

Summary

Create scripts by inheriting from Component

• Override Update() to define behavior

• Use events to communicate with other scripts

• Attach scripts using object.AddComponent(script)

• Remove scripts using object.RemoveComponent(script)

• Keep scripts focused on single responsibilities

© 2026 CoreScript Engine. Documentation licensed under MIT.