Mathematical Foundations
Mathf Utilities
float circleRatio = Mathf.PI;
int absoluteValue = Mathf.Abs(-42);
int ceilingValue = Mathf.CeilToInt(1.2f); // 2
int floorValue = Mathf.FloorToInt(1.9f); // 1
int constrained = Mathf.Clamp(25, 0, 100); // 25
int smallest = Mathf.Min(10, 3, 7);
int largest = Mathf.Max(10, 3, 7);
float exponential = Mathf.Pow(3, 2); // 9
int nearestInt = Mathf.RoundToInt(1.5f);
float squareRoot = Mathf.Sqrt(25f); // 5
Trigonometry
// Radians to degrees conversion
float radianMeasure = Mathf.PI / 4;
float degreeMeasure = radianMeasure * Mathf.Rad2Deg; // 45
// Degrees to radians conversion
degreeMeasure = 90f;
radianMeasure = degreeMeasure * Mathf.Deg2Rad;
// Standard trig functions (input radians)
float angleInRad = 30f * Mathf.Deg2Rad;
float sineValue = Mathf.Sin(angleInRad);
// Inverse functions (return radians)
float arcSineRad = Mathf.Asin(1f);
float arcSineDeg = arcSineRad * Mathf.Rad2Deg; // 90
Vector Mathematics
// Core operations
float scalarProduct = Vector3.Dot(directionA, directionB);
Vector3 perpendicular = Vector3.Cross(directionA, directionB);
float angularSeparation = Vector3.Angle(fromVector, toVector);
float separationDistance = Vector3.Distance(positionA, positionB);
// Interpolation
Vector3 interpolatedPos = Vector3.Lerp(startPoint, endPoint, 0.5f);
Quaternion Operations
// Axis-angle rotation
Quaternion rotation60 = Quaternion.AngleAxis(60f, Vector3.right);
transform.rotation = rotation60;
// Euler angle conversions
Vector3 eulerRotation = new Vector3(45f, 90f, 0f);
Quaternion quaternionForm = Quaternion.Euler(eulerRotation);
// Extract Euler angles
Vector3 extractedEuler = quaternionForm.eulerAngles;
// Orient towards target
Quaternion lookRotation = Quaternion.LookRotation(target.position - transform.position);
transform.rotation = lookRotation;
Delayed Execution Patterns
// Single execution delay
Invoke("TargetMethod", delaySeconds);
// Recurring execution
InvokeRepeating("TargetMethod", initialDelay, repeatInterval);
// Cancellation
CancelInvoke(); // All pending
CancelInvoke("TargetMethod"); // Specific method
// Status checking
bool isPending = IsInvoking("TargetMethod");
Constraints: Delayed functions cannot except parameters directly. Method names must match script-defined functions. Execution persists through component disabling but terminates with object destruction.
Coroutine Systems
Threading vs Coroutines
Unlike threads which spawn separate execution paths:
private Thread workerThread;
void Start()
{
workerThread = new Thread(BackgroundProcess);
workerThread.Start();
}
void OnDestroy()
{
if (workerThread != null)
{
workerThread.Abort();
workerThread = null;
}
}
void BackgroundProcess()
{
while (true)
{
Thread.Sleep(1000);
Debug.Log("Thread tick");
}
}
Critical: New threads cannot access Unity API objects (Transforms, GameObjects).
Coroutine Implementation
Coroutines provide cooperative multitasking on the main thread:
IEnumerator ComplexSequence(int iterations, string identifier)
{
Debug.Log($"Start {identifier}");
yield return new WaitForSeconds(3f);
Debug.Log($"End {identifier}");
}
// Initiation
Coroutine activeRoutine = StartCoroutine(ComplexSequence(5, "ProcessA"));
StartCoroutine(ComplexSequence(5, "ProcessB"));
// Termination
StopCoroutine(activeRoutine);
StopAllCoroutines();
Yield Instruction Behaviors
| Yield Statement | Execution Timing |
|---|---|
yield return null / yield return 0 |
Between Update and LateUpdate |
yield return new WaitForSeconds(t) |
Between Update and LateUpdate |
yield return new WaitForFixedUpdate() |
After FixedUpdate and physics |
yield return new WaitForEndOfFrame() |
After rendering completes |
yield break |
Immediate coroutine termination |
Lifecycle Notes: Coroutines cease when the GameObject is destroyed or deactivated. Component disabling does not stop coroutines.
Resource Management
Special Folder Functions
| Folder | Access Pattern | Characteristics |
|---|---|---|
Assets/ |
Application.dataPath |
Editor-only, non-existent in builds |
Resources/ |
API loading | Compressed, read-only, always included in builds |
StreamingAssets/ |
Application.streamingAssetsPath |
Uncompressed, platform-dependent access |
PersistentDataPath/ |
Application.persistentDataPath |
Writable, for runtime-generated data |
Plugins/ |
Platform-specific | Native library imports |
Editor/ |
Editor-only | Excluded from runtime builds |
Synchronous Loading
// Type-safe generic loading
GameObject enemyPrefab = Resources.Load<GameObject>("Prefabs/Enemy");
Instantiate(enemyPrefab);
AudioClip bgm = Resources.Load<AudioClip>("Audio/Theme");
TextAsset configData = Resources.Load<TextAsset>("Config/Settings");
Texture2D hudTexture = Resources.Load<Texture2D>("UI/HUDElement");
// Handling name collisions by type
Object[] textureVariants = Resources.LoadAll("Textures/Sprite");
Performance Note: Repeated Resources.Load calls return cached references without memory duplication, but incur processing overhead. Cache references locally for repeated use.
Asynchronous Loading
Prevents frame stuttering with large assets:
// Event-driven approach
ResourceRequest textureRequest = Resources.LoadAsync<Texture>("HeavyTexture");
textureRequest.completed += (operation) => {
Texture loaded = ((ResourceRequest)operation).asset as Texture;
ApplyTexture(loaded);
};
// Coroutine-driven approach (enables progress tracking)
IEnumerator LoadWithProgress(string assetPath)
{
ResourceRequest request = Resources.LoadAsync<GameObject>(assetPath);
while (!request.isDone)
{
Debug.Log($"Loading: {request.progress:P0}");
yield return null;
}
Instantiate(request.asset);
}
Asynchronous loading requires minimum one frame before asset availability.
Memory Unloading
// Specific asset release (not applicable to GameObjects)
Resources.UnloadAsset(specificTexture);
assetReference = null;
// Comprehensive cleanup (execute during scene transitions)
Resources.UnloadUnusedAssets();
System.GC.Collect();
Scene Transitions
// Immediate (blocking) load
SceneManager.LoadScene("TargetScene");
// Asynchronous loading
AsyncOperation sceneLoader = SceneManager.LoadSceneAsync("TargetScene");
sceneLoader.completed += (op) => Debug.Log("Load complete");
// Coroutine approach
IEnumerator TransitionToScene(string sceneName)
{
AsyncOperation loader = SceneManager.LoadSceneAsync(sceneName);
yield return loader;
// Scene now active
}
// Object persistence
DontDestroyOnLoad(persistentObject);
Rendering Components
Line Configuration
LineRenderer pathVisualizer = gameObject.AddComponent<LineRenderer>();
pathVisualizer.loop = true;
pathVisualizer.startWidth = 0.05f;
pathVisualizer.endWidth = 0.05f;
pathVisualizer.startColor = Color.cyan;
pathVisualizer.endColor = Color.magenta;
pathVisualizer.material = Resources.Load<Material>("Materials/LineMat");
pathVisualizer.positionCount = 4;
pathVisualizer.SetPositions(new Vector3[] {
new Vector3(-2, 0, -2),
new Vector3(-2, 0, 2),
new Vector3(2, 0, 2),
new Vector3(2, 0, -2)
});
pathVisualizer.useWorldSpace = true;
Physics Detection
Layer Mask Construction
int uiLayer = 1 << LayerMask.NameToLayer("UI");
int enemyLayer = 1 << LayerMask.NameToLayer("Enemy");
int combinedMask = uiLayer | enemyLayer; // Include both
int excludeUIMask = ~uiLayer; // Exclude UI
Volume Overlaps
Instantaneous spatial queries (require Collider components on targets):
// Axis-aligned bounding box
Collider[] boxHits = Physics.OverlapBox(centerPosition, halfSize, Quaternion.identity, layerMask);
int hitCount = Physics.OverlapBoxNonAlloc(centerPosition, halfSize, resultsArray, rotation, mask);
// Spherical volume
Collider[] sphereHits = Physics.OverlapSphere(origin, radius, layerMask, QueryTriggerInteraction.Collide);
// Capsule (cylindrical with hemispherical ends)
Collider[] capsuleHits = Physics.OverlapCapsule(topPoint, bottomPoint, radius, layerMask);
Raycasting
// Ray construction methods
Ray worldRay = new Ray(rayOrigin, rayDirection);
Ray mouseRay = Camera.main.ScreenPointToRay(Input.mousePosition);
// Single intersection
if (Physics.Raycast(worldRay, out RaycastHit hitInfo, maxDistance, layerMask))
{
GameObject struckObject = hitInfo.collider.gameObject;
Vector3 impactPoint = hitInfo.point;
Vector3 surfaceNormal = hitInfo.normal;
float impactDistance = hitInfo.distance;
}
// Multiple intersections
RaycastHit[] allIntersections = Physics.RaycastAll(worldRay, maxDistance, layerMask);
int intersectionCount = Physics.RaycastNonAlloc(worldRay, hitBuffer, maxDistance, layerMask);