Code works on my laptop but not on my desktop, using GitHub to share files

Some basic code I have written to change scenes works on my Laptop but not on my Desktop. I doubt it’s a problem with the code but I will still explain it all here. When we move to a new scene not only do we have to identify which scene but we need to enter which door to spawn the player at in this scene. To do this I assign an int variable to an object that has “DontDestroyOnLoad”. They reference that int as an index position of a list that contains all the spawn points in that room

Here is the door code:

public class DoorManager : MonoBehaviour
{
    [SerializeField] private GameObject levelManager;
    [SerializeField] private int nextScene;
    [SerializeField] private int sceneDoor;
    [SerializeField] private float openRange;
    [SerializeField] private GameObject doorCentre;
    [SerializeField] private GameObject playerBody;
    private GameObject levelData;
    private Animator anim;
    void Start()
    {
        levelData = GameObject.Find("LevelData");
        anim = GetComponent<Animator>();
    }

    void Update()
    {
        anim.SetBool("isOpen", Vector3.Distance(playerBody.transform.position, doorCentre.transform.position) < openRange);
    }

    private void OnTriggerEnter(Collider other)
    {
        if(other.gameObject.tag == "Player")
        {
            if (levelData != null)
            {
                levelData.GetComponent<LevelData>().ChangeSpawnDoor(sceneDoor);
            }
            levelManager.GetComponent<LevelManagment>().SceneTransition(nextScene);
        }
    }
}

ChangeSpawnDoor() on the “LevelData” component just updates a variable in that script to the parameter we feed in like so. It also has the DontDestroyOnLoad feature:

public class LevelData : MonoBehaviour
{
    public int doorIndex;
    [SerializeField] private GameObject self;
    private GameObject[] duplicates;
    // Network state

    void Start()
    {
        DontDestroyOnLoad(self);
    }

    void Update()
    {
        duplicates = GameObject.FindGameObjectsWithTag("LevelData");
        if(duplicates.Length > 1)
        {
            Destroy(duplicates[1]);
        }
    }

    public void ChangeSpawnDoor(int doorValue)
    {
        doorIndex = doorValue;
    }
}

Finally, this is the Level Manager script. The function previously called, SceneTransition() just changes the scene to what we feed in, ignore PlayerBeatLevel() and ConnectedLevelBeat(), that is for a different feature.

public class LevelManagment : MonoBehaviour
{
    private bool isComplete;
    private bool isLevelOn;
    private GameObject levelData;
    [SerializeField] private GameObject player;
    [SerializeField] private GameObject[] connectedLevels;
    [SerializeField] private Transform[] spawnPoints;

    private void Start()
    {
        levelData = GameObject.Find("LevelData");
        if (levelData != null)
        {
            player.transform.position = spawnPoints[levelData.GetComponent<LevelData>().doorIndex].position;
        }
    }

    public void SceneTransition(int _nextScene)
    {
        SceneManager.LoadScene(_nextScene, LoadSceneMode.Single);
    }

    public void PlayerBeatLevel()
    {
        isComplete = true;
        isLevelOn = !isLevelOn;
    }

    public void ConnectedLevelBeat()
    {
        isLevelOn = !isLevelOn;
    }
}

The line in the start function should set the player’s position to the predefined spawn point whose index matches the predefined door variable.

All of this code works on my laptop and it works consistently however when I upload to GitHub and download it on the desktop, the line of code in the start function of level manager does not run. The player’s scene changes but they are not put in front of any door. They are left at the point where the player game object is in the editor.

Any help is appreciated, I have been looking online and trying to bug fix myself for about 2 weeks. Also, let me know if there is a better way to manage scenes with multiple exit and entry points

You have to find out if you’re properly source controlling it with github first.

Clone it to another location on the computer where it actually works. Does it work? If it does, then you’re source-controlling it correctly. If it does not, then fix the source control problem first.

1 Like

If LevelData is suppose to be a singleton, then look up how to do a proper singleton. Because as it currently sits, it is possible it’s destroying the object that has your int value set on it, or doing something else there.

I would either have a static variable that you use instead, or just make a proper singleton.

And while I know you said it works on one computer but not another, any time you deal with order of operation stuff or stuff that relies on the “Find” commands, you run into risk of it not always working the same.

The big thing is to debug. Add Debug.Log calls throughout your code. Make sure you are getting the values you expect. Use log viewer (free) https://assetstore.unity.com/packages/tools/integration/log-viewer-12047 to see your debug messages in a build.

Yes, there could be problems with identifying the LevelData game object. However, if this were true and it was identifying the wrong object in the scene, the variable would still read 0 so the game would move the player to spawn point 0 every time which isn’t happening, it just keeps the player at spawn where it is in the editor.

Well, you can spend 2 more weeks staring at the code, or you can start implementing debugging steps as I suggested. And, as I mentioned, use a proper singleton.

1 Like

For Unity singletons, I never put stuff in a scene. I always use a variation of this approach:

Simple Singleton (UnitySingleton):

Some super-simple Singleton examples to take and modify:

Simple Unity3D Singleton (no predefined data):

Unity3D Singleton with a Prefab (or a ScriptableObject) used for predefined data:

These are pure-code solutions, do not put anything into any scene, just access it via .Instance!

If it is a GameManager, when the game is over, make a function in that singleton that Destroys itself so the next time you access it you get a fresh one, something like:

public void DestroyThyself()
{
   Destroy(gameObject);
   Instance = null;    // because destroy doesn't happen until end of frame
}

There are also lots of Youtube tutorials on the concepts involved in making a suitable GameManager, which obviously depends a lot on what your game might need.

Here’s some debugging notes:

You must find a way to get the information you need in order to reason about what the problem is.

What is often happening in these cases is one of the following:

  • the code you think is executing is not actually executing at all
  • the code is executing far EARLIER or LATER than you think
  • the code is executing far LESS OFTEN than you think
  • the code is executing far MORE OFTEN than you think
  • the code is executing on another GameObject than you think it is
  • you’re getting an error or warning and you haven’t noticed it in the console window

To help gain more insight into your problem, I recommend liberally sprinkling Debug.Log() statements through your code to display information in realtime.

Doing this should help you answer these types of questions:

  • is this code even running? which parts are running? how often does it run? what order does it run in?
  • what are the values of the variables involved? Are they initialized? Are the values reasonable?
  • are you meeting ALL the requirements to receive callbacks such as triggers / colliders (review the documentation)

Knowing this information will help you reason about the behavior you are seeing.

If your problem would benefit from in-scene or in-game visualization, Debug.DrawRay() or Debug.DrawLine() can help you visualize things like rays (used in raycasting) or distances.

You can also call Debug.Break() to pause the Editor when certain interesting pieces of code run, and then study the scene manually, looking for all the parts, where they are, what scripts are on them, etc.

You can also call GameObject.CreatePrimitive() to emplace debug-marker-ish objects in the scene at runtime.

You could also just display various important quantities in UI Text elements to watch them change as you play the game.

If you are running a mobile device you can also view the console output. Google for how on your particular mobile target, such as this answer or iOS: How To - Capturing Device Logs on iOS or this answer for Android: How To - Capturing Device Logs on Android

Another useful approach is to temporarily strip out everything besides what is necessary to prove your issue. This can simplify and isolate compounding effects of other items in your scene or prefab.

Here’s an example of putting in a laser-focused Debug.Log() and how that can save you a TON of time wallowing around speculating what might be going wrong:

1 Like

Wow, Thank you very much