STRUCTURAL

Proxy

What Is It?

Proxy is a structural design pattern where a placeholder or representative object stands in front of a real object and controls access to it. Instead of communicating with the real object directly, the client talks to the proxy.

The proxy implements the same interface as the real object, so the client does not need to know whether it is working with the actual object or a proxy. The proxy can decide what to do before forwarding the request: allow it, block it, delay it, log it, cache it, or create the real object only when it is needed.

In Unity, this can be imagined as an extra layer between your game code and a heavy system, such as an enemy AI, a large asset, an Addressable object, or a multiplayer player representation.

When Is It Used?

Proxy is useful when access to an object needs to be controlled or managed. One common case is when the real object is expensive to create. Instead of loading it immediately, the proxy waits until the object is actually needed.

It is also useful for access control. If a player is not allowed to perform an attack, the proxy can block the request before it reaches the real object.

In multiplayer games, a remote player object can also behave like a proxy. The actual player may exist on another machine or server, while the local object only represents it.

Proxy can also be used for logging, caching, or measuring calls without changing the original class. A simple way to think about it is this: catch the request first, make a decision, and then pass it to the real object only if needed.

Animation

IEnemyrealEnemy«client»GameManagerMonoBehaviourcanAttack: ?EnemyProxyimplements IEnemyEnemyimplements IEnemy

Code

Assets / Scripts / Structural / ProxyEnemyProxy.cs
READ ONLY
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
using UnityEngine;

namespace Patterns.Structural.Proxy
{
    public class EnemyProxy : IEnemy
    {
        private Enemy _realEnemy;
        private bool _canAttack;

        public EnemyProxy(bool canAttack)
        {
            this._canAttack = canAttack;
        }

        public void Attack()
        {
            if (!_canAttack)
            {
                Debug.Log("Enemy cannot attack yet.");
                return;
            }

            if (_realEnemy == null)
            {
                Debug.Log("Enemy created lazily.");
                _realEnemy = new Enemy();
            }

            _realEnemy.Attack();
        }
    }
}

Advantages and Disadvantages

• Advantages:

  • Adds control without changing the real object.
  • Keeps extra responsibilities away from the real class.
  • Shared interfaces keep client code clean.

• Disadvantages:

  • It adds another layer to the architecture.
  • Debugging can become harder.
  • Small performance costs can matter in hot paths.

Tips

In Unity, Proxy works well with services, asset loading, AI systems, and multiplayer objects. Instead of directly depending on a specific MonoBehaviour, it is often better to use an interface and let a proxy handle the access.

If you are using Addressables or Asset Bundles, a virtual proxy can be very useful. The proxy can exist immediately, show a placeholder behavior while the real asset is loading, and then forward calls to the real object once loading is complete.

For performance-critical systems, be careful with proxy checks inside Update() or FixedUpdate(). If possible, move the proxy logic outside the frame loop.

With lazy loading, avoid creating heavy objects at a sudden gameplay moment. Warming them up before the critical moment can prevent frame drops.

In multiplayer projects, tools like Mirror or Netcode for Game Objects already use a similar idea. Thinking of remote players as proxies can make RPC calls and local-versus-remote logic easier to design.