Need advise for better scripting

My first game is nearly complete but I had figured out that my script is too difficult to review even by myself. I need advise for my next project so people could understand my code, please share your tips and please reply with simple sentences so I can understand (I am not native english speaker) and did you still make GDD or class diagram even your solo project?

Might be helpful to post an example of your supposedly problematic code.

But in general though, you should only place code in the same script which is related to each other. Take large nested methods and break them up into several methods that each handle a separate chunk of the work. You should use an easy to understand naming convention for variables and methods, and the names should be self explanatory of what they are for.

Your code should be easy enough to read what it does. I use comments to explain the “why” part.

1 Like

writes code w/o commenting
Looking over it a month later "what… why did i do it this way?, it can be exprrssed simply as … entire game breaks, pc on fire"

Story of my life as a dev.

2 Likes

Yeah early on I used comments extensively to explain what code does. Then I started getting better at both quickly reading code and writing in a more easily to follow fashion that I cut back on my comments. I ran into a problem though looking at a year old code that I wrote and being able to read it but not understanding why I wrote it in the first place :stuck_out_tongue:

So now I try to always explain the purpose of my code in comments, without going through and explaining every step what it is doing.

1 Like

my problem some kind of yours, for example: I’d 2 classes, first is for animation and other for input. When I try to figured out a method it’s like “jumpy” from class to another class. Maybe I must learn how to make class diagram or whatever it is

Events are fantastic at solving the problem of seemingly unrelated objects needing to interact with each other.
A common example you find in most games is when the player takes damage. Some of the things that typically happen are:

  • The camera shakes
  • The screen flashes red
  • An audio clip plays
  • The UI is updated.

The player object itself, however, shouldn’t need to directly control these objects, as it just adds unnecessary dependancies that aren’t required for it to perform its main purpose.

You can instead define an event that is invoked whenever the player takes damage, and anything else that needs to care about this event happening can listen for it, and perform whatever action it needs to.

An example of how this can be structured is as follows:

public class Player : MonoBehavior {
   public float health;
  
   //The event to Invoke whenever the player takes damage.
   //Because the player taking damage is a global event, we can declare this as static. This may not work for multiplayer games.
   public static event Action OnDamageTaken;

   public void TakeDamage(float damage) {
      health -= damage;

      //Here, we Invoke the event, and anything listening for it will be able to perform an action at this point.
      OnDamageTaken?.Invoke();
  }
}

And if we wanted to implement a camera shake when the player takes damage, we can do so like this:

public class CameraController : MonoBehavior {
   void OnEnable() {
      //Here, we assign the Shake method as the listener for when the player takes damage.
      Player.OnDamageTaken += Shake;
   }

   void OnDisable() {
      //Here, we unassign the event listener when this object is disabled or destroyed.
      //Every listener assignment should also have an unassignment in order to free up memory when not being used.
      Player.OnDamageTaken -= Shake;
   }

   void Shake() {
      //Some code to shake the camera here.
   }
}

Effectively, the Player object influences the CameraController object without directly referencing it.

Unity also has UnityEvents that serve this purpose as well. I haven’t used them much though, so I cant really comment on them.

That’s really helpful but what if I want to give damage to specific character without reference it?

Could you please elaborate more on this? Generally, this isn’t possible. You will need a reference to an object if you plan on doing anything with it.

for example: every character has same Stats component based on Stats class. When someone got hit, I should get victim reference of their “Stats component” to modify their health. Am I right? or we can do with events instead call reference?

I’d rather have each character manage their own stats, rather than external scripts manipulating them.
For instance, when damaging the character, the external script should only need to call a simple “TakeDamage()” (or whatever) method from the character class, and this method handles modifying the character’s stats instead.

Say you started out by having the character’s health simply reduce when they take damage, but later on decide to give them an “armor” stat that can reduce damage taken.

With this structure, stats are modified in one script by the object that has them, meaning you only need to modify the code in one place, rather than every other external script that’s modifying these values. It’s much easier to debug and maintain.

Example:

public class Weapon : MonoBehaviour {
   public float damage;

   //Implying the weapon can collide with a character and deal damage.
   void OnTriggerEnter2D(Collider2D collider) {
      collider.gameObject.GetComponent<Character>().TakeDamage(damage);
   }
}
public class Character : MonoBehaviour {
   public CharacterStats stats;

   public void TakeDamage(float damage) {
      stats.health -= (damage / stats.armor);
   }
}

[Serializable]
public struct CharacterStats {
   float health;
   float armor;
   float speed;
   //etc...
}

My weapon script are similar with yours, but my weapon manager is following sharp accent’s tutorial. He uses external scripts and scriptables object. And yeah I can’t figured out how this work, as far as I know he just manage spawned weapon with scriptables:
https://www.youtube.com/watch?v=PuCsMJpyvSs