C# Interop
The CS global gives you access to any C# type.
Basic Usage
Access types through their full namespace:
// Static methods
CS.UnityEngine.Debug.Log("Hello from JS!")
// Static properties
const deltaTime = CS.UnityEngine.Time.deltaTime
// Create instances
const vec = new CS.UnityEngine.Vector3(1, 2, 3)
// Access instance properties
console.log(vec.x, vec.y, vec.z)
// Call instance methods
const normalized = vec.normalizedYour Own Code
Access your game code the same way:
// C# code in your project
namespace MyGame {
public class GameManager {
public static int Score { get; set; }
public static void AddScore(int points) { Score += points; }
}
}// JavaScript
CS.MyGame.GameManager.AddScore(100)
const score = CS.MyGame.GameManager.ScoreCreating Objects
Use new to instantiate C# classes:
// Create a GameObject
const go = new CS.UnityEngine.GameObject("MyObject")
// Add a component
const rb = go.AddComponent(CS.UnityEngine.Rigidbody)
// Set properties
rb.mass = 2.0
rb.useGravity = trueGeneric Types
Create bound generic types with function syntax:
// List<int>
const IntList = CS.System.Collections.Generic.List(CS.System.Int32)
const numbers = new IntList()
numbers.Add(1)
numbers.Add(2)
numbers.Add(3)
// Dictionary<string, int>
const StringIntDict = CS.System.Collections.Generic.Dictionary(
CS.System.String,
CS.System.Int32
)
const scores = new StringIntDict()
scores.set_Item("player1", 100)Async Methods
C# async methods return Promises in JavaScript:
// C#
public class DataLoader {
public static async Task<string> LoadDataAsync(string url) {
// ... async loading
return data;
}
}// JavaScript
const data = await CS.MyGame.DataLoader.LoadDataAsync("/api/data")
console.log(data)Events and Delegates
Subscribe to C# events:
// Get an event
const button = CS.UnityEngine.UI.Button.FindObjectOfType(CS.UnityEngine.UI.Button)
// Subscribe
button.onClick.AddListener(() => {
console.log("Button clicked!")
})Create delegates for callbacks:
// Create an Action delegate
const action = new CS.System.Action(() => {
console.log("Action invoked!")
})
// Pass to C# methods that expect Action
SomeApi.DoSomething(action)Enums
Access enum values directly:
// Access enum values
const space = CS.UnityEngine.Space.World
// Use in method calls
transform.Translate(new CS.UnityEngine.Vector3(1, 0, 0), space)
// Compare
if (keyCode === CS.UnityEngine.KeyCode.Space) {
console.log("Space pressed!")
}Arrays and Collections
Work with C# collections:
// C# arrays
const renderers = go.GetComponentsInChildren(CS.UnityEngine.Renderer)
for (let i = 0; i < renderers.Length; i++) {
renderers[i].enabled = false
}
// Lists
const list = new (CS.System.Collections.Generic.List(CS.System.String))()
list.Add("one")
list.Add("two")
console.log(list.Count) // 2
// Access by index
console.log(list[0]) // "one"Type Checking
Check types at runtime:
const component = go.GetComponent(CS.UnityEngine.Component)
// Check type
if (component.GetType().Name === "Rigidbody") {
// It's a Rigidbody
}
// Or use typeof
const rigidbodyType = CS.UnityEngine.Rigidbody
if (component instanceof rigidbodyType) {
// It's a Rigidbody
}Common Patterns
Finding Objects
// Find by type
const player = CS.UnityEngine.GameObject.FindWithTag("Player")
// Find all
const enemies = CS.UnityEngine.GameObject.FindGameObjectsWithTag("Enemy")
// Find component
const camera = CS.UnityEngine.Camera.mainCoroutine Alternative
Since JS has async/await, you often don't need coroutines:
async function fadeOut(renderer, duration) {
const material = renderer.material
let alpha = 1.0
const startTime = CS.UnityEngine.Time.time
while (alpha > 0) {
await new Promise(resolve => requestAnimationFrame(resolve))
const elapsed = CS.UnityEngine.Time.time - startTime
alpha = 1.0 - (elapsed / duration)
material.color = new CS.UnityEngine.Color(1, 1, 1, Math.max(0, alpha))
}
}Input Handling
function checkInput() {
if (CS.UnityEngine.Input.GetKeyDown(CS.UnityEngine.KeyCode.Space)) {
console.log("Jump!")
}
const horizontal = CS.UnityEngine.Input.GetAxis("Horizontal")
const vertical = CS.UnityEngine.Input.GetAxis("Vertical")
}
// Call every frame
function update() {
checkInput()
requestAnimationFrame(update)
}
requestAnimationFrame(update)Performance Tips
- Cache type references: Don't look up types repeatedly in hot loops
- Batch property access: Get multiple values at once when possible
- Use fast paths: Common operations like
Time.deltaTimeare optimized - Avoid reflection in loops: Pre-resolve types outside the loop
za API eliminates all managed heap allocations after initial setup.