How to optimize same behavior on multiple objects?

I am developing a puzzle adventure game, and in short I have a main map with different objects in this map that lead to mini puzzles. I have some same action for every object, but they also do some different things, so I created a different script for same actions.
For example, when the player click an object, a mini-puzzle screen opens, and when mini-puzzle closed, the player teleport to last clicked object. And the background song contunies were it left. The codes for teleportation and background music are ready, but I want this in most optimal way, is there any suggestions?

Here what I did so far:
I had these codes done on my manager script, and objects refer to the manager script. If I attached the script to all objects, and refer to manager in start function, are all the objects execute start function? Or the scipt executed once and all the objects benefit from it?

Here is my code so far for all objects to contunie song and teleport last point and do some other things:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class MiniPuzzleScript : MonoBehaviour, IInteractable
{

    GameObject data;
    GameObject manager;
    [SerializeField] GameObject player;
    [SerializeField] GameObject onMouseOver;
    [SerializeField] GameObject mouseClicked;
    public MapName newMapname;
    public bool finished;
    // Start is called before the first frame update
    public enum MapName
    {
        Vakvak_1_1,
        Zodiac_2_1,
        Haseki_1_4,
    }
    void Start()
    {
        data = GameObject.Find("Load&Save");
        manager = GameObject.Find("Manager");
    }
    private void OnMouseDown()
    {
            player.GetComponent<PlayerPointAndClick>().clickedItem = gameObject;
            player.GetComponent<PlayerPointAndClick>().setDestination(30f); 
    }
    private void OnMouseEnter()
    {
        if (!finished)
            mouseClicked.SetActive(true);
    }
    private void OnMouseExit()
    {
        if (player.GetComponent<PlayerPointAndClick>().clickedItem != gameObject && !finished)
        {
            onMouseOver.SetActive(true);
            mouseClicked.SetActive(false);
        }
    }
    public void changeDialogue()
    {
       
        //take Item to inventory ? destroy it
    }
    public void Apply()
    {
        if(data)
        {
            //data.GetComponent<LoadData>().loadData.positionOfPlayer.x = GameObject.Find("mandıracı").transform.position.x;
            //data.GetComponent<LoadData>().loadData.positionOfPlayer.y = GameObject.Find("mandıracı").transform.position.y;
            //data.GetComponent<LoadData>().loadData.positionOfPlayer.z = GameObject.Find("mandıracı").transform.position.z;
            manager.GetComponent<Manager>().GetComponent<Manager>().savePosition();
            manager.GetComponent<Manager>().saveMusictime();
        }
        SceneManager.LoadScene(newMapname.ToString());

    }
}

For all performance and optimization issues, ALWAYS start by using the Profiler window:

Window → Analysis → Profiler

Generally optimization is:

  • avoid doing the thing that is slow
  • do it fewer times and store its result
  • do the slow thing less frequently over time
  • do the slow thing when nobody cares much (during level loading or in another thread, etc.)
  • find a faster way to do the thing (hardest)

DO NOT OPTIMIZE “JUST BECAUSE…” If you don’t have a problem, DO NOT OPTIMIZE!

If you DO have a problem, there is only ONE way to find out: measuring with the profiler.

Failure to use the profiler first means you’re just guessing, making a mess of your code for no good reason.

Not only that but performance on platform A will likely be completely different than platform B. Test on the platform(s) that you care about, and test to the extent that it is worth your effort, and no more.

https://discussions.unity.com/t/841163/2

Remember that you are gathering information at this stage. You cannot FIX until you FIND.

Remember that optimized code is ALWAYS harder to work with and more brittle, making subsequent feature development difficult or impossible, or incurring massive technical debt on future development.

Don’t forget about the Frame Debugger window either, available right near the Profiler in the menu system.

Notes on optimizing UnityEngine.UI setups:

https://discussions.unity.com/t/846847/2

At a minimum you want to clearly understand what performance issues you are having:

  • running too slowly?
  • loading too slowly?
  • using too much runtime memory?
  • final bundle too large?
  • too much network traffic?
  • something else?

If you are unable to engage the profiler, then your next solution is gross guessing changes, such as “reimport all textures as 32x32 tiny textures” or “replace some complex 3D objects with cubes/capsules” to try and figure out what is bogging you down.

Each experiment you do may give you intel about what is causing the performance issue that you identified. More importantly let you eliminate candidates for optimization. For instance if you swap out your biggest textures with 32x32 stamps and you STILL have a problem, you may be able to eliminate textures as an issue and move onto something else.

This sort of speculative optimization assumes you’re properly using source control so it takes one click to revert to the way your project was before if there is no improvement, while carefully making notes about what you have tried and more importantly what results it has had.

“Software does not run in a magic fairy aether powered by the fevered dreams of CS PhDs.” - Mike Acton

1 Like

Every instance of GameObject is going to run the code. If you are trying to make a Manager GameObject that persists across scene loads then you can use DontDestroyOnLoad. You can test this for yourself by putting Debug.Log statements in your Start functions and seeing how many times they fire.

Here is an example of using DontDestroyOnLoad. Place a script like this on a GameObject in the first scene you load and it will persist.

using UnityEngine;

public class Manager : MonoBehaviour
{
    void Awake()
    {
        GameObject[] objs = GameObject.FindGameObjectsWithTag("Manager");
        if (objs.Length > 1) {
            Destroy(gameObject);
        }
        DontDestroyOnLoad(gameObject);
    }

    void Start()
    {
        // this start function only runs once
    }
}

Thank you. I use the DontDestroyOnLoad function on my game manager, but there is no need for other game objects to persist across scenes. I thought it would be better if I referenced the manager once, and all game objects took values from it. I hoped using the same script would achieve that. However, as Kurt-Dekker mentioned, guessing is not the right approach. I will look into the profile window for optimization. Maybe running the same code for all objects isn’t that bad after all.

Thank you very much, I will look at it!