Search Unity

events and code architecture

Discussion in 'Scripting' started by gibberingmouther, Nov 29, 2017.

  1. gibberingmouther

    gibberingmouther

    Joined:
    Dec 13, 2016
    Posts:
    259
    so i finished most of my inventory, not including crafting or randomized loot drops. for my next step i want to work on the actual meat of the game, starting with menus (and a hotkey bar). say you use the menu or hotkey bar to activate power attack. the actual code for power attack is with the code for attacking and whatnot. but i need the menu code to communicate with this power attack code and tell it to activate. would this best be done with events, and if so what would it look like? (just the events part.) any advice on code architecture relating to such things would also be appreciated. i'm about to make some pretty big steps and i don't want to be halfway through coding then realize my code structure was bad.
     
  2. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Can you post a simple example of what one attack looks like, your code?
     
  3. gibberingmouther

    gibberingmouther

    Joined:
    Dec 13, 2016
    Posts:
    259
    Code (csharp):
    1.  
    2. void Attack(GameObject enemy1)  // again, this just refers to one enemy. need to fix!
    3.         {
    4.             if (enemy_clicked == true)
    5.             {
    6.                 AttackEnemy(enemy1);
    7.             }
    8.         }
    9.  
    and
    Code (csharp):
    1.  
    2. void AttackEnemy(GameObject enemy1)
    3.         {
    4.             float xDiff = enemy1.transform.position.x - transform.position.x;
    5.             float yDiff = enemy1.transform.position.y - transform.position.y;
    6.             float zval = transform.position.z;
    7.             Vector3 attackangle = new Vector3(xDiff, yDiff, zval);
    8.             // animate
    9.             /*
    10.                  random 1 or 2
    11.                  if (...)
    12.                     if 1
    13.                         thrust
    14.                     if 2
    15.                         swing
    16.                   ...
    17.                  */
    18.             /*
    19.             // also need to do two weapon fighting and ranged.  much easier without animation controller!
    20.             */
    21.             float smallest, elements;
    22.             float[] angles;
    23.             angles = new float[4] { Vector3.Angle(Vector3.left, attackangle), Vector3.Angle(Vector3.right, attackangle), Vector3.Angle(Vector3.up, attackangle), Vector3.Angle(Vector3.down, attackangle) };
    24.             elements = 4;
    25.             smallest = angles[0];
    26.             for (var i = 1; i <= elements - 1; i++)
    27.             {
    28.                 if (angles[i] < smallest)
    29.                     smallest = angles[i];
    30.             }
    31.  
    32.             if (smallest == angles[0])
    33.             {
    34.                 Debug.Log("attackleft");
    35.                 animator.InterpolateAnimation("HALeft");
    36.             }
    37.             if (smallest == angles[1])
    38.             {
    39.                 animator.InterpolateAnimation("HARight");
    40.             }
    41.             if (smallest == angles[2])
    42.             {
    43.                 animator.InterpolateAnimation("HAUp");
    44.             }
    45.             if (smallest == angles[3])
    46.             {
    47.                 animator.InterpolateAnimation("HADown");
    48.             }
    49.  
    50.             // wait and only run this code that increments damage_taken once every N frames (N = 2 for now)
    51.             if (Time.time > nextActionTime && InAttackRange(3))//do animations separately? - yes
    52.             {
    53.                 if (attack_skill_hits.skill_hits(7) && !attack_skill_evades.skill_evades(5, 7, 9))
    54.                 {
    55.                     if (swinging)
    56.                     {
    57.                         damage_taken += swinging_thrusting.dmg_swinging(15) + 2;//+ weapon damage modifier + other modifiers(weapon specialization etc.);
    58.                     }
    59.                     else
    60.                     {
    61.                         damage_taken += swinging_thrusting.dmg_thrusting(15) + 1;// + weapon damage modifier + other modifiers(weapon specialization etc.);
    62.                     }
    63.                     Debug.Log(damage_taken);
    64.                 }
    65.                 nextActionTime = Time.time + period;
    66.             }
    67.         }
    68.  
    i haven't incorporated weapon equipping fully yet, so what this looks like is the hero karate chopping the enemy to death.
     
  4. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    So, let's say the 'Attack' is part of a referenced piece of equipment (or hands, whatever).
    Say equipment has an interface for Use/Execute (maybe not 'attack' if you have other options, like "use" or whatever).
    Hotkey bar/menu click -> lookup reference equipment + activate the interface, passing any needed arguments along with it.
    That would be a nice start, maybe.
     
    gibberingmouther likes this.
  5. gibberingmouther

    gibberingmouther

    Joined:
    Dec 13, 2016
    Posts:
    259
    i've used interfaces provided by unity but never written any of my own. are you saying i should use an interface instead of an event? not exactly sure what you are getting at. could you give me a brief pseudocode example?
     
  6. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Well, say you have : hands, sword, apple, spell. These could be for menu items/hot key entries.
    That makes sense, so far, right?

    Now, when you make a selection (a click or whatever), you can do 1 method from that. (in the inspector, this would be a unity event, let's say).

    However, now you want to perform probably different actions, based on what's in the menu item/hot key tray.

    So, that's the part I was referring to for using an interface.
    If you add an interface to each of these items, they share a commonality.
    Code (csharp):
    1.  
    2. interface IUseable {
    3.    void Use(GameObject go);
    4.   }
    5. public class Sword : IUseable {
    6.  
    7.  public void Use(GameObject go) {
    8.     print("I used my sword.");
    9.    }
    10. }
    11. public class Apple : IUseable {
    12.   public void Use(GameObject go) {
    13.    print("I ate an apple.");
    14.    }
    15. }
    16.  
    17. // clicked method/script.
    18. // I have no idea what your class of items is, but let's say it's GameItem
    19. GameItem item;
    20. public void MenuClick() {
    21.    IUseable used = item as IUseable;
    22.    if(used != null) used.Use(null); // well, obviously a bit more work is needed if you have a targetted enemy here and not null but ya..
    23.    }
    24.  
     
    gibberingmouther likes this.
  7. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Mind you, if every single item had "Use" you don't really need the interface. It could just be in the base class, of course.
     
  8. Fido789

    Fido789

    Joined:
    Feb 26, 2013
    Posts:
    343
    I would suggest you some kind of event aggregator. And if you'll supplement it with some dependency injection framework (Zenject), you will have killer combo.
     
    gibberingmouther likes this.
  9. gibberingmouther

    gibberingmouther

    Joined:
    Dec 13, 2016
    Posts:
    259
    what's an event aggregator?
     
  10. Fido789

    Fido789

    Joined:
    Feb 26, 2013
    Posts:
    343
    I wrote about it a few days ago here.
     
    gibberingmouther likes this.