Search Unity

Best way to network an ability script?

Discussion in 'Multiplayer' started by Fikule, Feb 27, 2018.

  1. Fikule

    Fikule

    Joined:
    Dec 25, 2014
    Posts:
    19
    I made an ability script without networking to get my head around it.

    It has one game object (NetworkBehaviour) that simply creates the ability script on Start. The ability script is not a mono or network behaviour, it's just a script.

    That script then creates the spell, adding targeting and effects, each as their own script.

    e.g. Fireball is something like this:

    A NetworkBehaviour Fireball object creates FireballScript.
    FireballScript creates a new spell with:
    TargetingLine (allows the player to select a line on the map as a target)
    EffectSelection (plays a graphical/audio effect when the spell is selected)
    EffectLineProjectile (instantiates a Projectile NetworkBehaviour and gives it starting data based on targeting information)
    The Projectile then also receives effects, such as:
    EffectOnHitDamage (damages the first target it hits)
    EffectOnHitDestroy (the projectile destroys itself when it hits something)

    All of these effects and targeting types are linked back to the original spell and all react to delegates on the spell, such as:

    OnHit()
    OnSelect()
    OnTarget()
    etc.

    This would hopefully let me create abilities pretty fast without adding many new scripts as development continues.

    So, now I need to network it and yeah, I can only instantiate gameobjects on a NetworkBehaviour with player authority. Right now, things like EffectLineProjectile are what creates the... well, the projectile. This is a script, so it's not even a MonoBehaviour, let alone a NetworkBehaviour.

    There are also about 20 delegates so far, triggering on each effect and target script during the spell's use.

    Here is the EffectLineProjectile script at the moment:
    Code (CSharp):
    1.     class EffectLineProjectile : BaseEffect
    2.     {
    3.         public GameObject Projectile { get; set; }
    4.         public override void OnSelect(TargetData player)
    5.         {
    6.             Debug.Log("OnSelect: EffectLineProjectile");
    7.         }
    8.  
    9.         public override void OnTarget(TargetData target)
    10.         {
    11.             if (Spell.SpellTargetting.TargetData.IsValid)
    12.             {
    13.                 DebugText.SetText("Valid Target");
    14.                 CreateLineProjectile();
    15.                 Debug.Log("Valid Target: " + target.MouseTarget.transform.position);
    16.             }
    17.             else
    18.             {
    19.                 Debug.Log("Invalid Target: " + target.MouseTarget.transform.position);
    20.             }
    21.         }
    22.  
    23.         public void CreateLineProjectile()
    24.         {
    25.             foreach (var item in Spell.SpellTargetting.TargetData.LineList)
    26.             {
    27.                 var obj = GameObject.Instantiate(Projectile);
    28.                 if (obj.GetComponent<Projectile>() != null)
    29.                 {
    30.                     obj.GetComponent<Projectile>().start = item.start;
    31.                     obj.GetComponent<Projectile>().end = item.end;
    32.                     obj.GetComponent<Projectile>().targetData = Spell.SpellTargetting.TargetData;
    33.                     obj.GetComponent<Projectile>().Spell = Spell;
    34.                     obj.GetComponent<Projectile>().Fire();
    35.                 }
    36.                 NetworkServer.Spawn(obj);
    37.             }
    38.         }
    39.     }
    (Yeah, pretty messy atm and being changed as I go, thus things like OnTarget not using the TargetData passed to it and setting Projectile variables manually instead of passing them along. Also worth noting, the NetworkServer.Spawn works on the server, not the client. I'm aware of this, but it seems relevant to where I'd want it called if only the server was calling this)

    Basically I think each effect or targeting will have one unique method that does it's action, such as CreateLineProjectile(). But that action needs to happen on the server, and with the player's TargetData (which is pretty big, as it needs to store enough generic data to cover any type of spell).

    So, I guess my question is, how could I get the server to call CreateLineProjectile with accurate TargetData?

    The top level object is still the NetworkBehaviour Fireball object which has a NetworkIdentity. So I have to assume all these scripts exist on the server as well as the client, but won't receive any updated information. But how can I, from inside this script, call a command that can have the server call back to the equivalent object on the server?

    And is there a way to do it dynamically so I don't need to create a new [Command] on the player for every new ability?

    TL;DR - I have scripts within scripts that have a method that the server needs to call

    If you need any more details, let me know. I realise it's pretty sparse
     
    Last edited: Feb 27, 2018