Quick answer
Game describes the current tick, while Memory stores JSON-compatible data for later ticks. A Creep's memory property is a convenient view of Memory.creeps[creep.name]. Use it for small facts such as a role, a working-state flag, a target ID, or a home-room name. Do not save a live Source, Creep, or Structure object in Memory.
Why ordinary variables are not persistent state
The main loop runs again on every tick. A variable created inside that loop is created again when the loop runs again:
module.exports.loop = function () {
let working = false;
if (working) {
console.log('The Creep is working.');
}
};
This example always starts with working set to false. It is useful as current-execution data, but it does not represent a durable decision. Review how ticks and module.exports.loop work before using cross-tick state.
What the Memory object is
Screeps provides the global Memory object for JSON-compatible information that must be available later:
Memory.exampleValue = 1;
console.log(Memory.exampleValue);
Official documentation explains that Game is rebuilt for the current tick, whereas changes written through Memory are serialized and passed forward. Memory is limited, and reading it has a parsing cost, so this beginner guide stores only small values.
How creep.memory maps to Memory.creeps
const creep = Game.creeps.Harvester1;
if (creep) {
creep.memory.role = 'harvester';
console.log(creep.memory.role);
console.log(Memory.creeps[creep.name].role);
}
Both reads point to the same Creep Memory entry. The role string does not create an official class. It is a label that your own code can use while iterating over Game.creeps:
for (const name in Game.creeps) {
const creep = Game.creeps[name];
if (creep.memory.role === 'harvester') {
console.log(creep.name + ' is assigned to harvesting.');
}
}
See the beginner role guide for the difference between body abilities and player-defined jobs.
Write role Memory when spawning
StructureSpawn.spawnCreep() accepts an options object that can include initial Memory:
const result = Game.spawns.Spawn1.spawnCreep(
[WORK, CARRY, MOVE],
'Harvester1',
{
memory: {
role: 'harvester',
working: false
}
}
);
console.log('spawnCreep() returned ' + result);
This creates the Memory entry as part of the spawn request. The method still needs its normal name, body, energy, and return-code checks. Review the spawnCreep() tutorial before adding role-based replacement logic.
Use a boolean working state
working is a player-defined field that commonly separates an Energy-acquisition phase from an Energy-spending phase:
const usedEnergy =
creep.store.getUsedCapacity(RESOURCE_ENERGY);
const freeEnergy =
creep.store.getFreeCapacity(RESOURCE_ENERGY);
if (usedEnergy === 0) {
creep.memory.working = false;
}
if (freeEnergy === 0) {
creep.memory.working = true;
}
Your script must then read the flag and call the appropriate API. Writing creep.memory.working = true does not automatically call build(), transfer(), or upgradeController(). The same pattern appears in the Energy-delivery tutorial.
What belongs in Memory
| Good beginner values | Why |
|---|---|
'harvester' | Small role string. |
true or false | Simple working-state decision. |
'E51S44' | Room name that can be checked later. |
| A game object ID string | Lets later code recover the current object. |
| Small arrays or plain objects | Remain JSON-compatible when deliberately bounded. |
Functions, circular values, and live game objects do not belong in Memory. Large caches and RawMemory performance work are outside this beginner article.
Save object IDs, not live game objects
A Source object belongs to the current visible game state. Save its ID instead:
const source = creep.pos.findClosestByRange(FIND_SOURCES);
if (source) {
creep.memory.sourceId = source.id;
}
On a later tick, recover the current object and handle null:
const source = creep.memory.sourceId
? Game.getObjectById(creep.memory.sourceId)
: null;
if (!source) {
delete creep.memory.sourceId;
}
Game.getObjectById() can return null when the object no longer exists or is not currently visible. The ID is durable data; the returned game object is still current-tick data.
Why dead Creep Memory can remain
Game.creeps and Memory.creeps are related but separate. After a Creep dies, its name disappears from Game.creeps, while the old Memory entry may remain until your code removes it. Do not add automatic deletion before understanding the comparison:
for (const name in Memory.creeps) {
if (!Game.creeps[name]) {
console.log(name + ' exists only in Memory.');
}
}
Complete beginner example
State impact: this script writes one role string and one boolean to the selected Creep's Memory. It does not move the Creep or submit a game action.
module.exports.loop = function () {
const creep = Game.creeps.Harvester1;
if (!creep) {
console.log('Harvester1 was not found.');
return;
}
if (creep.memory.role === undefined) {
creep.memory.role = 'harvester';
}
if (creep.memory.working === undefined) {
creep.memory.working = false;
}
console.log(JSON.stringify({
name: creep.name,
role: creep.memory.role,
working: creep.memory.working
}));
};
Observe the Memory inspector and several later ticks. A real multi-tick room test has not been performed for this article, so the verification panel remains explicit about that boundary.
Debugging checklist
- Confirm the Creep exists before reading
creep.memory. - Use one spelling and capitalization for every role value.
- Remember that custom fields do nothing until your code reads them.
- Store JSON-compatible values only.
- Store a game object's ID, not the object itself.
- Handle
Game.getObjectById()returningnull. - Expect dead Creep entries to remain until cleanup code removes them.
- Use the English error-code reference when a later action fails.
Scope and next steps
This guide does not cover RawMemory, segments, parse-cost optimization, global caching, automatic role counts, replacement spawning, or modular role files. Continue with withdrawing Energy from a Container, where Memory can later connect acquisition and delivery states.
Frequently asked questions
Does a normal JavaScript variable survive every Screeps tick?
Do not use a local loop variable as durable game state. Use Memory for information that must be available later.
Is creep.memory different from Memory.creeps?
creep.memory is a convenient alias for the matching Memory.creeps entry.
Can I save a Source object directly?
No. Save source.id, then call Game.getObjectById() on a later tick.
Is working an official field?
No. It is a player-defined boolean whose meaning comes entirely from your own branching logic.