Managing Object References for Inter-Script Communication in Unity

Setup Overview

Two key nodes exist in this scenario: a Unit Manager node (equipped with Transform and UnitFactory components) and a Unit prefab node (equipped with Tarnsform and Unit components). The objective involves retrieving the Unit component from the instantiated prefab.

Direct Component Reference Approach

A common novice implementation looks like this:

using UnityEngine;

public class UnitFactory : MonoBehaviour
{
    [SerializeField] private GameObject _unitPrefab;

    private GameObject _spawnController;
    private Unit _spawnedUnit;

    private void Start()
    {
        _spawnController = Instantiate(_unitPrefab);
        _spawnedUnit = _spawnController.GetComponent<Unit>();
    }
}

This approach carries performance overhead. A more efficient method references the component directly:

using UnityEngine;

public class UnitFactory : MonoBehaviour
{
    [SerializeField] private Unit _unitPrefab;

    private Unit _spawnedUnit;

    private void Start()
    {
        _spawnedUnit = Instantiate(_unitPrefab);
    }
}

Any script inheriting from MonoBehaviour can leverage this pattern.

Managing Multiple Units with a Collection

To manage multiple units, introduce a private list within the UnitFactory class:

private List<Unit> _activeUnits = new List<Unit>();

Ensure the proper namespace is included at the top of the script:

using System.Collections.Generic;

Populate the collection in the Start method:

for (int i = 0; i < 10; i++)
{
    _activeUnits.Add(Instantiate(_unitPrefab));
}

To control unit positions dynamically, update the logic within the Update method:

foreach (var unit in _activeUnits)
{
    unit.transform.position = Random.insideUnitSphere;
}

Exposing Data Through a Static Singleton

When multiple scripts need access to unit data, a static singleton pattern provides convenient access.

Add the following to UnitFactory:

public static UnitFactory Instance { get; private set; }

private void Awake() => Instance = this;

Modify the collection's visibility and expose it:

public List<Unit> Units { get; private set; } = new List<Unit>();

For preserving serialized data when renaming fields, use the Unity attribute:

[FormerlySerializedAs("_activeUnits")]
public List<Unit> Units { get; private set; } = new List<Unit>();

Remember to include the required namespace:

using UnityEngine.Serialization;

Create an empty GameObject in the Hierarchy and attach a MapManager script. Use this implementation:

using UnityEngine;

public class MapManager : MonoBehaviour
{
    void Update()
    {
        foreach (var unit in UnitFactory.Instance.Units)
        {
            unit.transform.position = Random.insideUnitSphere;
        }
    }
}

Read-Only Property Access Pattern

To allow external scripts to read the collection without mdoification, expose the field as a property:

public List<Unit> Units { get; private set; } = new List<Unit>();

Collision Detection Best Practices

When handling collisions, check whether the colliding object contains a specific component:

A less efficient pattern:

using UnityEngine;

public class Unit : MonoBehaviour
{
    private void OnCollisionEnter(Collision other)
    {
        var targetUnit = other.gameObject.GetComponent<Unit>();
        if (targetUnit != null)
        {
            //Do something.
        }
    }
}

The TryGetComponent method provides cleaner syntax and better performance:

using UnityEngine;

public class Unit : MonoBehaviour
{
    private void OnCollisionEnter(Collision other)
    {
        if (other.gameObject.TryGetComponent(out Unit targetUnit))
        {
            //Do something.
        }
    }
}

Avoiding Reflection-Based Method Invocation

The SendMessage approach invokes methods via reflection, which carries significant performance penalties:

using UnityEngine;

public class Unit : MonoBehaviour
{
    public void HandleCollision(int damage){}

    private void OnCollisionEnter(Collision other)
    {
        other.gameObject.SendMessage("HandleCollision", 10);
    }
}

This technique should be avoided in production code.

Tags: unity csharp game-development script-communication monobehaviour

Posted on Fri, 29 May 2026 16:48:06 +0000 by Mirage