
Isometric traffic and pedestrian movement
This script is designed for creating pedestrian and traffic control in my game, MOP, using C# and Unity. The game map coordinates are read from a dictionary, and agent spawn locations are converted to isometric coordinates. Agents are assigned random locations to move to, and at the end of each street (map’s rows and columns), they can choose to turn left, right, or continue straight. These decisions are made in Cartesian coordinates but are converted to isometric coordinates for rendering. Additionally, the script is useful for spawning crowd agents. Rectangular instance bounds are converted to isometric, and agents are randomly instantiated within these bounds.
Conversation between Cartesian and isometric coordinates.
cartesian to isometric conversion Takes a Vector2 representing Cartesian coordinates (transformCart) and returns a Vector2 representing the equivalent isometric coordinates. The conversion is done using the formulas
iso.x = cart.x - cart.y and iso.y = (cart.x + cart.y) / 2.
// Converts Cartesian coordinates to isometric coordinates
public Vector2 cartToIso(Vector2 transformCart)
{
Vector2 transformIso;
transformIso.x = transformCart.x - transformCart.y;
transformIso.y = (transformCart.x + transformCart.y) / 2;
// Uncomment the line below for debugging
// print(transformCart + "Iso>>" + transformIso);
return transformIso;
}
Isometric to cartesian conversion : Takes a Vector2 representing isometric coordinates (transformIso) and returns a Vector2 representing the equivalent Cartesian coordinates. The conversion is done using the formulas
cart.x = (2 * iso.y + iso.x) / 2 and cart.y = (2 * iso.y - iso.x) / 2.
// Converts isometric coordinates to Cartesian coordinates
public Vector2 isoToCart(Vector2 transformIso)
{
Vector2 transformCart;
transformCart.x = (2 * transformIso.y + transformIso.x) / 2;
transformCart.y = (2 * transformIso.y - transformIso.x) / 2;
// Uncomment the line below for debugging
// print(transformIso + "toCart>>" + transformCart);
return transformCart;
}
MotionControl
The motionControl script manages the movement, state, and lifecycle of an object (either a vehicle or pedestrian) in a grid-based environment within a Unity game. It handles spawning, movement direction changes, speed variations, infection states, and object destruction. The script also interacts with various other game components for map preparation, event control, sound, and UI updates.
spawn(): Initializes and spawns the object in the grid, sets its initial position, life duration, speed, and handles infection states and related visual/audio cues.
void spawn()
{
// Adjust life and speed based on variations
life = (int)(life * UnityEngine.Random.Range(lifeVariation.x, lifeVariation.y));
speed *= UnityEngine.Random.Range(speedVariation.x, speedVariation.y);
// Randomly select start position within grid
int startRow = (int)(UnityEngine.Random.Range(0, (MapPrep.rowNum)));
int startColumn = (int)(UnityEngine.Random.Range(0, (MapPrep.columnNum)));
currentGrid = new Vector3Int(startRow, startColumn, 0);
// If the object is secondarily infected and just spawned, set to specific grid
if (state == "secondaryInfected" && age == 0)
{
currentGrid = EventCtrl.secondaryInfectionGrid;
startRow = currentGrid.x;
startColumn = currentGrid.y;
}
// Set initial world position based on type
if (type == 0)
currentPosition = MapPrep.coordinates[startRow][startColumn];
else if (type == 1)
currentPosition = MapPrep.coordinatesPed[startRow][startColumn];
this.gameObject.transform.localPosition = currentPosition;
// If infected, instantiate alert object and adjust speed
if (state == "infected" || state == "secondaryInfected")
{
speed *= .75f;
alertObj = Instantiate(alertInfectedPrefab, new Vector3(currentPosition.x, currentPosition.y + 75, currentPosition.z), Quaternion.identity);
alertObj.transform.SetParent(UI.map_objects.transform, false);
// Configure the alert object's eventPrefab component
eventPrefab EventPrefab;
EventPrefab = alertObj.GetComponent<eventPrefab>();
EventPrefab.life = life;
EventPrefab.sourceObject = this.gameObject;
// Play infection sound
SoundCtrl.clipPlay("infected");
}
targetSelect(); // Select initial target position
}
targetSelect(): Determines the next target position for the object to move towards based on its current direction and probability to change direction.
// Method to select the target position
void targetSelect()
{
// List of possible directions
List<string> directions = new List<string> { "R", "L", "U", "D" };
int currentRow = currentGrid.x;
int currentColumn = currentGrid.y;
int targetColumn = currentColumn;
int targetRow = currentRow;
// Remove reverse direction from the list
if (direction == "R")
directions.Remove("L");
else if (direction == "L")
directions.Remove("R");
else if (direction == "U")
directions.Remove("D");
else if (direction == "D")
directions.Remove("U");
// Remove invalid directions based on grid boundaries
if (currentColumn == 0)
directions.Remove("L");
if (currentColumn == (MapPrep.columnNum - 1))
directions.Remove("R");
if (currentRow == 0)
directions.Remove("D");
if (currentRow == (MapPrep.rowNum - 1))
directions.Remove("U");
// Check if the current direction is valid
bool dirValid = directions.Contains(direction);
float changeRandSeed = (UnityEngine.Random.Range(0f, 1f));
// Force direction change if invalid or not set
if (!dirValid || direction == "NA")
changeRandSeed = 1;
// Change direction based on probability
if (changeRandSeed > 1 - changeDirProb)
{
int randDirection = (int)(UnityEngine.Random.Range(0, (directions.Count)));
direction = directions[randDirection];
}
// Update target position based on the selected direction
if (direction == "R")
{
targetColumn = currentColumn + 1;
objRenderer.sprite = sprites[0]; // Right sprite
}
else if (direction == "L")
{
targetColumn = currentColumn - 1;
objRenderer.sprite = sprites[1]; // Left sprite
}
else if (direction == "U")
{
targetRow = currentRow + 1;
objRenderer.sprite = sprites[3]; // Up sprite
}
else
{
targetRow = currentRow - 1;
objRenderer.sprite = sprites[2]; // Down sprite
}
targetGrid = new Vector3Int(targetRow, targetColumn, 0);
// Set target position based on type
if (type == 0)
targetPosition = MapPrep.coordinates[targetRow][targetColumn];
else if (type == 1)
targetPosition = MapPrep.coordinatesPed[targetRow][targetColumn];
currentGrid = targetGrid; // Update current grid position
}
positionUpdate(): Updates the object’s position towards the target, adjusts its speed, handles aging, and manages the object’s infection alert position.
// Method to update the object's position
void positionUpdate()
{
if (UI.delay > 0)
{
float step = 1 / UI.delay;
age += step;
float updatedSpeed = speed * step;
Vector3 targetDirection = (targetPosition - currentPosition);
// Move towards the target position
if (targetDirection.magnitude > (updatedSpeed * .8))
{
targetDirection.Normalize();
currentPosition += (targetDirection * updatedSpeed);
}
else if (targetDirection.magnitude <= (updatedSpeed * .8))
{
currentPosition = targetPosition;
targetSelect(); // Select new target position
}
this.gameObject.transform.localPosition = currentPosition;
// Update alert object position if infected
if (state == "infected" || state == "secondaryInfected")
{
if (alertObj != null)
alertObj.transform.localPosition = new Vector3(currentPosition.x, currentPosition.y + 75, currentPosition.z);
}
// Destroy the object if its age exceeds its life duration
if (age > life)
kill();
}
// Update the sorting order of the sprite based on its position
int depth = (int)((currentPosition.y - 1000) * -1) - 1500;
objRenderer.sortingOrder = depth;
}
amazing! Breaking: Landmark Agreement Reached on [International Matter] 2025 nice