3.2 Unity’s Default Paradigm

Unity’s default paradigm describes the set of default design philosophies integrated into the workflow of building applications with Unity. It’s the decisions taken during the development of the engine that results in the workflow of building applications in Unity as opposite to other engines or frameworks. This is why it’s very important to start with.

When you’re thinking of building scalable features, you’d often need to combine multiple design paradigms. This is expected. Unity’s default paradigm is always going to be one of those paradigms as it’s how the engine operates.

A part of utilizing other paradigms within Unity is understanding how to bend the default paradigm in order to implement others. This is going to be necessary to understand even if you have an understanding of how to utilize them outside of Unity.

Characteristics

Components
Unity utilities a component-based architecture to represent your behaviours. Often time, behaviours are composed together of different scripts to represent entities. The lifecycle of your scripts and game objects are handled by Unity.

Focus on developing features quickly
It’s unbelievably fast to put together features in Unity. This is one of its core strengths, and it justifies a lot of the design philosophies that it ships with. This is still an aspect you can utilize even in combination with other paradigms.

No entry point
Implementations of architectures often start with an entry point (E.g. a main() method) where you have control of how you create, initialize, and pass the elements in your architecture. This isn’t the case in Unity, which might require substitution and compromise.

Criteria

Feature placement
Unity’s default paradigm favours getting things done over placing features in a relational architecture

Reference handling
References are serialized on your scripts and assigned in the inspector. Additionally, Unity provides methods for grabbing references from the scene at runtime.

Scalability
Without utilizing other paradigms, Unity’s default paradigm poses many concerns for scalability, making it mostly suitable for prototypes.

⚠️ Disclaimer
It’s often difficult to characterize the set of design philosophies behind the workflow of Unity without getting messages about how it’s efficient for scalability. This is usually the result of developers, after some experience, finding smart solutions to the scalability issues as they accidentally utilize other paradigms without realizing it.

However, it’s important to understand that the majority of new developers, even ones who aren’t very new, won’t be able to identify issues in their process without breaking this down to its most default forms. The issues here arise naturally when you follow the majority of Unity tutorials out there.

Scalability concerns

Serialized references
Any field on your scripts can be serialized and assigned in the editor. This removes any architectural constraints on what kind of references a class could access, which might make it an anti-pattern comparable to singletons.

This grants you the power to implement things quickly, but without care, it can easily result in coupled code. You have the responsibility to maintain your architectural integrity without natural constraints.

Cost of components-based architecture
While components allow you to composite behaviours quickly, this introduces a couple of issues when it’s time to scale.

Effective architecture allows you to manage the lifecycle of your features as a whole. New features should integrate naturally into your game state without a lot of extra work.

Compositing your behaviours means you’ll have to spend a lot of time micromanaging building blocks on a low level, instead of managing your code on a high level. This is because it’s inherently stateless.

Not to mention that being stateless almost always results in the spaghettification of your code.

Take a look at this example. We’ve examined this scenario in a previous chapter.
This script moves an object towards a player if the player is close enough.

using UnityEngine;
public class MoveToPlayer : MonoBehaviour
{
   public Transform player;
   public float speed;
   public float maxDistance;
  
   void Update()
   {
       if (Vector3.Distance(player.position, transform.position) < maxDistance)
       {
           float step = speed * Time.deltaTime;
           transform.position = Vector3.MoveTowards(transform.position, player.position, step);
       }
   }
}

You’ll have to do one of the following if you want to implement sound or animation:

  • Put the animation and sound code directly in this class, making it carry more responsibilities than what it was designed to do
  • Replicate the same condition in another script and put the animation or sound code there instead, repeating your code and thus having to keep track of more things if you want to make changes
  • Accessing this script somewhere else to determine if the object is moving towards the player, but then you’ll have to deduce the state of the object according to multiple similarly non-contextual behaviour scripts

This is just one example on a very small scale.

Keep in mind

From my experience, it seems that the majority of indie and new developers power through this paradigm on its own. A lot of them do it with success, too. Which is to iterate: the purpose here is to make your life easier, not to make your code functional. But managing a growing project is just far easier when you’re able to address the scalability concerns by combining it with other paradigms.

Loading

3.2 Unity’s Default Paradigm

Unity’s default paradigm describes the set of default design philosophies integrated into the workflow of building applications with Unity. It’s the decisions taken during the development of the engine that results in the workflow of building applications in Unity as opposite to other engines or frameworks. This is why it’s very important to start with.

When you’re thinking of building scalable features, you’d often need to combine multiple design paradigms. This is expected. Unity’s default paradigm is always going to be one of those paradigms as it’s how the engine operates.

A part of utilizing other paradigms within Unity is understanding how to bend the default paradigm in order to implement others. This is going to be necessary to understand even if you have an understanding of how to utilize them outside of Unity.

Characteristics

Components
Unity utilities a component-based architecture to represent your behaviours. Often time, behaviours are composed together of different scripts to represent entities. The lifecycle of your scripts and game objects are handled by Unity.

Focus on developing features quickly
It’s unbelievably fast to put together features in Unity. This is one of its core strengths, and it justifies a lot of the design philosophies that it ships with. This is still an aspect you can utilize even in combination with other paradigms.

No entry point
Implementations of architectures often start with an entry point (E.g. a main() method) where you have control of how you create, initialize, and pass the elements in your architecture. This isn’t the case in Unity, which might require substitution and compromise.

Criteria

Feature placement
Unity’s default paradigm favours getting things done over placing features in a relational architecture

Reference handling
References are serialized on your scripts and assigned in the inspector. Additionally, Unity provides methods for grabbing references from the scene at runtime.

Scalability
Without utilizing other paradigms, Unity’s default paradigm poses many concerns for scalability, making it mostly suitable for prototypes.

⚠️ Disclaimer
It’s often difficult to characterize the set of design philosophies behind the workflow of Unity without getting messages about how it’s efficient for scalability. This is usually the result of developers, after some experience, finding smart solutions to the scalability issues as they accidentally utilize other paradigms without realizing it.

However, it’s important to understand that the majority of new developers, even ones who aren’t very new, won’t be able to identify issues in their process without breaking this down to its most default forms. The issues here arise naturally when you follow the majority of Unity tutorials out there.

Scalability concerns

Serialized references
Any field on your scripts can be serialized and assigned in the editor. This removes any architectural constraints on what kind of references a class could access, which might make it an anti-pattern comparable to singletons.

This grants you the power to implement things quickly, but without care, it can easily result in coupled code. You have the responsibility to maintain your architectural integrity without natural constraints.

Cost of components-based architecture
While components allow you to composite behaviours quickly, this introduces a couple of issues when it’s time to scale.

Effective architecture allows you to manage the lifecycle of your features as a whole. New features should integrate naturally into your game state without a lot of extra work.

Compositing your behaviours means you’ll have to spend a lot of time micromanaging building blocks on a low level, instead of managing your code on a high level. This is because it’s inherently stateless.

Not to mention that being stateless almost always results in the spaghettification of your code.

Take a look at this example. We’ve examined this scenario in a previous chapter.
This script moves an object towards a player if the player is close enough.

using UnityEngine;
public class MoveToPlayer : MonoBehaviour
{
   public Transform player;
   public float speed;
   public float maxDistance;
  
   void Update()
   {
       if (Vector3.Distance(player.position, transform.position) < maxDistance)
       {
           float step = speed * Time.deltaTime;
           transform.position = Vector3.MoveTowards(transform.position, player.position, step);
       }
   }
}

You’ll have to do one of the following if you want to implement sound or animation:

  • Put the animation and sound code directly in this class, making it carry more responsibilities than what it was designed to do
  • Replicate the same condition in another script and put the animation or sound code there instead, repeating your code and thus having to keep track of more things if you want to make changes
  • Accessing this script somewhere else to determine if the object is moving towards the player, but then you’ll have to deduce the state of the object according to multiple similarly non-contextual behaviour scripts

This is just one example on a very small scale.

Keep in mind

From my experience, it seems that the majority of indie and new developers power through this paradigm on its own. A lot of them do it with success, too. Which is to iterate: the purpose here is to make your life easier, not to make your code functional. But managing a growing project is just far easier when you’re able to address the scalability concerns by combining it with other paradigms.

Loading

PHP Code Snippets Powered By : XYZScripts.com