Maintaining Code Quality / Correctness

With things like ActionStart and ActionComplete on BaseAction how do you enforce (or remind yourself if you’re the only developer) that it should always be called within the class that overrides it? and that it should be overridden in a particular way. And that these methods need to be called at the right time to avoid problems like the ones referenced at around 4:29 in the video?

The code has gotten to the point where I can’t remember all this. What do you all (particularly the experienced engineers) do to keep all this straight? This is honestly one of my major concerns with starting to do more game development outside this course. I worry I’ll get lost in my own code.

1 Like

Documentation.

Look up XML comments.

Thanks. I have some familiarity with the XML comment system.

Was wondering if there were any tricks with automation? I had a related question a while ago when I noticed various components (in particular the Unit with the Visual with the LevelGrid) go out of sync or fail to get initialized correctly.

Then in many of the recent videos, particularly the last few lessons which feature a lot of refactoring, I see Hugo doing a lot of testing with the play mode. I have to imagine some kind of automation would be useful and wondering what some simple tests would look like? I can surmise that too much automation too soon would mean you are not only rewriting code, but rewriting tests so hence my curiosity what a practical approach looks like.

So I have the early stages of an idea and would love feedback.

  1. Create a new script called something like ConsistencyChecker.
  2. Set the script execution order to very high (i.e. I want it last)
  3. Within the Awake() method run code to make sure there is consistency between unit state, unit lists, LevelGrid, visuals, etc Make sure also that the expected number of listeners are present. If I know I have 5 units for example, I should expect 6 listeners to the healthSystem.OnDead (one per unit + one more for RagdollSpawner)
  4. Within the Update() method continue to make sure there is consistency.
  5. Create the ability to skip consistency checks if there are units with a busy state (e.g. moving)
  6. Add a boolean flag that can turn on/off the code within the Update method for performance reasons.

Since the script execution order would be high (combined with 5), I think this should guarantee that it runs only at times that there should be consistency.

I haven’t written this yet, but thinking about it after having to go through much pain of debugging and adding/removing various debug statements to find n bugs. I’m not an engineer so I’m sure there are much much better ways. This is the best I could think of.

You could write some Unit testing or intergration testing classes, but that’s a lot of extra work for what I’d see as very little benefit in this case… or YAGNI (You ain’t gonna need it).

Was there anything specific you had in mind?

Learn to use the actual debugger. It’s really good. Still painful but really good.

You could write 100+ lines of code testing 30-50 lines of code but while that could be considered a better way, in this case, especially since you’re only learning, I’d consider it an absolute waste of time.

Let me tell you about one of the problems I’m having. I’ve previously used used Unity 2021 LTS and this is the first time with 2022 and URP. I’m noticing it’s way slower for me when transitioning from VS to Unity and from edit to play mode. Domain reloads went from being a minor thing to being long and painful. To prove out this hypothesis, I exported everything and attempted to reload in 2021. It definitely seems to be behaving better but I’m running into this issue: Unity Turn Based Strategy Game - Error I don’t want to try fixing that.

So given this problem that it’s way slower to work within Unity now. My laptop, while an i7 based system is 10 years old. I’m going to look to upgrade this summer when retailers try to compete with Prime Day. I’d also love an Intel i9 :slight_smile: Maybe it will last me 10 more years!

So bottom line:
I’m looking for tricks that can help reduce (a) the amount of time I have to go back and forth between VS and Unity and (b) to avoid entering/exiting play mode.

Ideas

  1. See what I wrote in my prior comment for one idea.
  2. I’m also thinking maybe I implement a keystroke to reset the game state without having to exit or re-enter play mode. Suggestion to GameDevTV team - please include this early in the tutorials!
  3. Building something to turn detailed logging on and off (while still in play mode) would also help.

I’ve previously used debuggers. Not afraid of them. But never in VS, and never with Unity so it does seem like there’s a bit to learn to figure out how to coordinate the two. I tried about a month ago, seemed hard. But at some point I should learn how to do it in this environment.

Ok so I implemented this part of it. It is working great except for one area where I am running into a very strange bug after I load the scene again. Unity thinks the actionCameraGameObject game object referenced by the CameraManager is being destroyed. In the hierarchy ActionVirtualCamera object is still there (still disabled). The CameraManager game object is still there too. And CameraManager still has a reference to the ActionVirtualCamera object when I look in the inspector. The gameplay is fine except the switch back and forth between cameras is no longer working and two MissingReference Exceptions are being thrown both of which when I run any code to reference the actionCameraGameObject.

MissingReferenceException: The object of type ‘GameObject’ has been destroyed but you are still trying to access it.
Your script should either check if it is null or you should not destroy the object.
CameraManager.BaseAction_OnAnyActionStarted (System.Object sender, System.EventArgs e) (at Assets/Scripts/CameraManager.cs:48)
BaseAction.ActionStart (System.Action onActionComplete) (at Assets/Scripts/Actions/BaseAction.cs:54)
ShootAction.TakeAction (GridPosition gridPosition, System.Action onActionComplete) (at Assets/Scripts/Actions/ShootAction.cs:160)
UnitActionSystem.HandleSelectedAction () (at Assets/Scripts/UnitActionSystem.cs:82)
UnitActionSystem.Update () (at Assets/Scripts/UnitActionSystem.cs:67)

MissingReferenceException: The object of type ‘GameObject’ has been destroyed but you are still trying to access it.
Your script should either check if it is null or you should not destroy the object.
CameraManager.HideActionCamera () (at Assets/Scripts/CameraManager.cs:26)
CameraManager.BaseAction_OnAnyActionCompleted (System.Object sender, System.EventArgs e) (at Assets/Scripts/CameraManager.cs:60)
BaseAction.ActionComplete () (at Assets/Scripts/Actions/BaseAction.cs:61)
ShootAction.NextState () (at Assets/Scripts/Actions/ShootAction.cs:83)
ShootAction.Update () (at Assets/Scripts/Actions/ShootAction.cs:57)

The code I’m running to reset the Scene is: At the moment I’m just clicking the resetSceneButton as nothing else is implemented and I haven’t modified any other code anywhere else.

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

public class DebugSystemUI : MonoBehaviour
{
    [SerializeField] private Button resetSceneButton;
    [SerializeField] private Toggle loggingToggle;

    public void Start()
    {

        resetSceneButton.onClick.AddListener(() =>
        {
            HandleSceneReset();
        });

        Debug.Log("Reset Button listerner added");

        loggingToggle.onValueChanged.AddListener(delegate
        {
            HandleLoggingMode(loggingToggle);
        });


    }

    private void HandleSceneReset()
    {
        SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
    }

    private void HandleLoggingMode(Toggle toggle)
    {
        Debug.Log($"Confirm that toggle is set to: {toggle.isOn}");
    }
}

The plot thickens!

I added debugging within the CameraManager object. After a scene reload, Awake and Start both run and it has a reference to the actionCameraGameObject. But when the BaseAction_OnAnyActionStarted code is triggered, then it’s null in there. I did a GameObject.Find() and still couldn’t find it. So it seems some references are getting lost on the reload.

My guess is it has something to do with the fact that we have a “static event EventHandler” in BaseAction. But what’s curious is that an analogous issue doesn’t seem to be triggering with the Unit.OnAny* events. Maybe because BaseAction is an abstract class??

This may warrant a separate thread now since it’s gone way off the topic of my original Q. Let me know if I should make this a separate thread.

Your options are limited to: Using versions that load faster with your use case.
Appropriate hardware upgrades that are a stop-gap to solve your speed issue.

At the moment, Unity is limited to .net5 while the rest of the world is on .net6 or 7 with 8 coming out later this year. 6 and 7 had performance improvements that may fix your issues, but Unity has to work out how to make it happen.

If you’ve used debuggers, it shouldn’t be hard. Took me about 5 minutes after watching a youtube video to get the basics down.

It’s a good idea to open a new thread for new issues.

This error is usually when you’re trying to instantiate a gameObject that no longer exists. I usually see this happen when people Instantiate from GameObjects that are inside a scene, but are destroyed, or Prefabs that are destroyed while the game is running. Usually the former option.

I’ve not used this asset personally, but I’ve had it recommended to me a couple of times. It’s supposed to greatly speed up Unity’s compilation time.

This video links to the source code (free!) and walks through the package installation.

1 Like

I just fixed it! Posted my solution here: Scene reloading while avoiding MissingReferenceException on action camera

Thank you!!! I will look into this.

Privacy & Terms