How should I put this together?

I’m really struggling with structure and would love to know how you would do this scenario.

Super basic stuff.

So you’ve got a player object and a mob object.

The player object has a controller to take player input, while the mob has an AI controller.

Both are character class which contain stats variables. For the sake of conversation we’ll say the stats are “healthPoints” and “attackDamage”.

Now how would I go about making a global attack function that both objects can use and input their stats and then alter them?

Where would I place the script that declares the global attack function?

How should I fit in the fact that they’re both characters, but have different controllers?

And where should I declare the values of the stats?

Thank you in advance for any help you can offer.

So if I were you I would create a singleton which holds my stats for the player and I would have a function to update the current enemy’s stats to the singleton object. Then in FixedUpdate(), let’s say we have a method calles Attack()
so do something like this:

void FixedUpdate()
{
   if(input.GetKey(mouse1)
   {
      getenemystats();
      Attack();
   }
}

ps.: the code is just a POC

I assume your attacks are done via Raycasts or Colliders? If so then you can just call something like this:

OnTriggerEnter (Collider other)
{
if (other.gameObject.tag == "Enemy")
{
EnemyController eC = other.gameObject.GetComponent<EnemyController>();
eC.TakeDamage(//some damage);
}
}

If not make a singleton/static function for the players stats.

1 Like

Make an interface that both player and monster inherit, so that the “attack” can access this.
Even a global singleton can use that interface

1 Like

EverQuest Next was planned to use something like this :slight_smile: but unfortunately the game is canceled.

Were you the developer of that? :o

No :slight_smile: , i am working a scifi RPG online game. with a small team of 3 people, and there is no plans on canceling this project.

I think this is a great concept “Not_Sure” let me know if you want a code example of what i suggested

I suppose it depends how you implement the stats themselves. Like do the enemy stats depend on/are decided based on player stats? If so, you could just keep everything in one singleton, have your “randomness” decide how much stronger or weaker than the player the enemy is, assign that to some variable for later references, then as your player attack is called, ask the singleton/game master how much damage the player does, how much defense the enemy has, and so forth. Ideally the player would just have his script control the animation and detecting if he is alive and such.

I don’t have any code to share but there’s my two cents, and since I know your projects are quality stuff that perhaps benefits more than yourself, I feel urged to try and help however I can, even if just some rambling advice :stuck_out_tongue:

1 Like

I would recommend checking this out: https://gitlab.com/spockerdotnet/sdnsingletons/blob/develop/Assets/SDNSingletons/Scripts/MonoSingleton.cs

That’s interesting @traderain but I’ve always just done singletons with static instancing, and a few public methods and variable getters and setters, but your alternative does seem to be more fool proof. Perhaps would prevent accidental clones of game master scripts and stuff like that I suppose.

that script looks like a copycat from this. http://wiki.unity3d.com/index.php/Toolbox

Ahh yes, those are very similar!

Probably, its not my script so I don’t know but its a good script so doesn’t matter.

Nothing necessarily wrong with having alternative implementations available publicly for learning from, that’s for sure.

1 Like

There are a lot of questions going on your original post, @Not_Sure .

If you just need a global attack function, there’s no need for a singleton. Just make it a static class, and not a MonoBehaviour, with a method to process the attack:

public static class MyGlobalAttackClass {
    public static void ComputeAttack(Stats attacker, Stats defender) {...}
}

When the attacker registers a hit on the defender, call the method:

MyGlobalAttackClass.ComputeAttack(myStats, targetStats);

Is your Stats class different from your Controller class(es)? If so, I don’t see how the global attack function needs to be concerned about the controller at all. (Well, I can imagine possibilities such as for animation feedback, knockback, etc.)

But let’s say each character has at least three MonoBehaviours:

  • Stats
  • Weapon
  • Controller (perhaps with subclasses for PlayerController and AIController)

You could isolate Stats from Controller like this: (very abbreviated for illustration)

Controller:

void Update() {
    if (Input.GetButtonDown("Attack")) {
        GetComponent<Weapon>().Attack(target);
    }
}

Weapon:

public void Attack(GameObject target) {
    if (/*your code to detect hit*/) {
        MyGlobalAttackClass.ComputeAttack(GetComponent<Stats>(), target.GetComponent<Stats>());
    }
}
2 Likes

I can give you my example of how I’ve been doing things, after trying to organize things as best as possible I’ve come to this sort of structure -

Player,Enemy, Combat, Ability, AbilityProjectile, EnemyAI

Player.cs contains generic control of the player, movement, controls, etc, with references to combat and other components

Combat.cs is a class that any entity that can possibly be involved in combat uses, containing health, damage, other stats, as well as functions like ‘useAttack(str/int)/useAbility(str/int)’, ‘addDamage(int)’, ‘isAlive()’, etc. Combat also contains a list of abilities that can be spells or any type of attacks used by the player or enemies or items

Ability.cs contains definition of abilities/skills, and has stuff like ‘abilityType’, ‘abilityPower’, ‘abilityDuration’, ‘cooldownRemaining, cooldownMax’ etc, and contains CoRoutines useAbility() that will use the ability

AbilityProjectile.cs is generated/instantiated any time an ability is used (whether its actually melee or projectile), and its collision is used to detect if an attack hits or not, upon collision ‘applyAbilityEffects(enemyCombatCs,baseAbility)’ is called upon the collided object’s script

Enemy.cs contains generic control of the enemy, references to combat.cs and enemyAI.cs and everything is updated from update()

enemyAI.cs contains AI parameters (aggressiveness, patrolling, passive, patrol radius/paths, etc.) and functions updateAI that will update the enemy’s movement and attack based on its current AI states/commands that are continuously updated, but updateAI is called thru enemy.cs’s reference to this AIclass

This system is not perfect but it gives a general idea of how things can work

1 Like