Search Unity

[RELEASED] Turn Based Strategy Framework

Discussion in 'Assets and Asset Store' started by michal-zetkowski, Jul 2, 2019.

  1. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Regarding Spells, adding new GridState is the first thing that comes to my mind. I see that you have a pretty good understanding of the framework already :)

    I agree that CellGrid could be divided into two or more classes. As for GridState, I don't like it for a few reasons. First of all, the name CellGridState doesn't make much sense. Basically what it does, is disabling and enabling user interaction with the game. I think that spliting CellGrid and extracting this state somewhere else might help. This is a minor issue though, the worst thing is that with this system, AI and Human interaction with the game is completly separated. Take your case for example - if you want to make a "speed" based system, you need to code it separately for AI and Human players (well, I guess that GridState is only a part of the problem here). It would be great if I could come up with a unified system.

    Recently I was asked to code a very basic tic-tac-toe project that would include both AI and Human players. I tried hard to come up with a different approach, but ended up going with similar design. I had separate classes for storing game state and game controller though. There was also a GameState system with just two subclasses - BoardInteractionEnabled and BoardInteractionDisabled. In the end I was quite happy with it, but I guess that it can be done better. I guess I worked with this design for so long that I can't see some obvious flaws in my resoning. I would be great if someone could show me how to approach it in a better way, because I'm sure there is a better way :)
     
  2. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    I see that you are using MyUnit script. It was made for the purpose of example scenes and if you want to use them with your models then you will need to make some changes. The lines that you commented out is a part of it.

    Regarding units dropping below grid - take a look at "offset" field in MyUnit. If you set it to 0 then it should be fine.
     
  3. Jon_Brant

    Jon_Brant

    Joined:
    Mar 22, 2018
    Posts:
    56
    Hum, yeah I didn't really think the CellGridState name seemed off until you pointed it out. It makes sense with it currently coupled, I'd say.

    As far as the AI, I can't comment too much as I've never done an AI, but I think it makes perfect sense that I'd have to completely rework it. I am completely changing the flow of the game. I'm just thankful that there IS an AI. Honestly it's one of the main reasons I bought the kit.

    But yeah, I DEFINITELY get being stuck in a mode of thought and using the same design patterns repeatedly. I'd say that's pretty normal. Don't take my feedback as criticism. Every asset can always be better. You did an extremely good job. It can just always be better
     
  4. Bellatorpoeta

    Bellatorpoeta

    Joined:
    Feb 25, 2020
    Posts:
    1
    Hi! Really love your product. It has saved me dozens of hours. Right now, I'm trying to implement a cover system and I have code set up for line of sight and cover like so.


    Code (CSharp):
    1. public virtual bool IsUnitAttackable(Unit other, Cell sourceCell)
    2.     {
    3.         //supercover line code for LOS
    4.         var p0 = other.Cell.OffsetCoord; var p1 = sourceCell.OffsetCoord;
    5.         var dx = p1.x - p0.x; var dy = p1.y - p0.y;
    6.         var nx = Math.Abs(dx); var ny = Math.Abs(dy);
    7.         var sign_x = dx > 0 ? 1 : -1; var sign_y = dy > 0 ? 1 : -1;
    8.  
    9.         var p = new Vector2(p0.x, p0.y);
    10.         var points = new List<Vector2>();
    11.         for (int ix = 0, iy = 0; ix < nx || iy < ny;)
    12.         {
    13.             if ((0.5+ix) /nx == (0.5 + iy) / ny)
    14.             {
    15.                 //next step is diagonal
    16.                 p.x += sign_x;
    17.                 p.y += sign_y;
    18.                 ix++;
    19.                 iy++;
    20.                 if (Cell.IsCover == true)
    21.                 {
    22.                     return false;
    23.                 }
    24.             }
    25.             else if ((0.5+ix) / nx < (0.5+iy)/ny)
    26.             {
    27.                 //next step is horizontal
    28.                 p.x += sign_x;
    29.                 ix++;
    30.                 if (Cell.IsCover == true)
    31.                 {
    32.                     return false;
    33.                 }
    34.             }
    35.             else
    36.             {
    37.                 //next step is vertical
    38.                 p.y += sign_y;
    39.                 iy++;
    40.                 if (Cell.IsCover == true)
    41.                 {
    42.                     return false;
    43.                 }
    44.             }
    45.             points.Add(new Vector2(p.x, p.y));
    46.         }      
    47.  
    48.         if (sourceCell.GetDistance(other.Cell) <= AttackRange)
    49.             return true;
    50.  
    51.         MarkAsReachableEnemy();
    52.         return false;
    53.     }
    I added a bit of code in Cell to make obstacles be identified as cover, in the same place where it shows a cell is taken.

    The problem is that it doesn't seem to work. Units can still target each other if cover is in the way. Right now I'm just trying to make it so cover stops all targeting but I hope to adjust it to make it so cover just decreases chance to hit. One step at a time though. Any comments you can give me on why it doesn't work?
     
  5. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    I didn't take it as criticism, and event if it was I wouldn't mind :)
     
  6. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    You definatelly have the right idea, this code belongs to IsUnitAttackable. It would be easiest for me if you could export your project and send it to me. It's hard to debug just by looking at the code.
     
  7. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    The following code used to work in TBSFv1.2.1. In the current version I'm getting some really strange rotations. I've spent about an hour so far and couldn't fix it. Please experiment with this, I'm sure that this is the way to go but there is a small issue that I fail to see (please let me know if you figure this out)

    Code (CSharp):
    1. protected virtual IEnumerator MovementAnimation(List<Cell> path)
    2.     {
    3.         isMoving = true;
    4.         path.Reverse();
    5.         foreach (var cell in path)
    6.         {
    7.             Vector3 destination_pos = new Vector3(cell.transform.localPosition.x, transform.localPosition.y, cell.transform.localPosition.z);
    8.             while (transform.localPosition != destination_pos)
    9.             {
    10.                 transform.localPosition = Vector3.MoveTowards(transform.localPosition, destination_pos, Time.deltaTime * MovementAnimationSpeed );
    11.                 Vector3 newDir = Vector3.RotateTowards(transform.forward, destination_pos - transform.position, Time.deltaTime * MovementAnimationSpeed, 0.0f);
    12.                 transform.rotation = Quaternion.LookRotation(newDir);
    13.                 Debug.DrawRay(transform.position, newDir, Color.red);
    14.                 yield return 0;
    15.             }
    16.         }
    17.         isMoving = false;
    18.     }
    Regarding turning the unit towards enemy, I would put the code in Unit.AttackHandler. Unfortunately in the current version this method is not virtual, so you will need to modify it in base class.
     
  8. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Nice video :). Instead of tags I would make subclasses for 'Alien' and 'Enemy' and put this code there, or use Strategy design pattern (encapsulate the code in AlienAnimationHandler and EnemyAnimationHandler, both classes would implement AnimationHandler, add AnimationHandler field to Unit and assign appropriate implementation - but I guess that this is an overkill, the first option seems simpler)
     
  9. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Sorry about that, it seems to be some unintended consequence. I'll try figuring this out, but can't say when because I'll be traveling in the following days.
     
  10. ZanesTheArgent

    ZanesTheArgent

    Joined:
    Jul 6, 2019
    Posts:
    2
    Hey, i'm interested in also doing a multi-tile units thing, but i'm a bit weak on the coding game as of now. Mind in sharing what you scribbled so far?
     
  11. Banksy

    Banksy

    Joined:
    Mar 31, 2013
    Posts:
    376
    Hi ya Zanes… Let me know if you manage to work out movement in terms of have a unit turn towards the enemy unit for attack and defence.

    fingers crossed we might see this implemented into the base project.
     
    Last edited: Jul 2, 2020
  12. Banksy

    Banksy

    Joined:
    Mar 31, 2013
    Posts:
    376
    Can anyone recommend a site that has tutorials focusing on turn based tile game play.. or even a few links to YouTube videos would be greatly appreciated
     
  13. Jon_Brant

    Jon_Brant

    Joined:
    Mar 22, 2018
    Posts:
    56
  14. Banksy

    Banksy

    Joined:
    Mar 31, 2013
    Posts:
    376
    wow... thanks so much for the link Jon_Brant. hopeful this will help ease the pain of so much trial and error.. taking a look now.

    I am wondering if TBSF uses A* Path Finding ?
     
  15. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Hey, sorry for delayed replies, I'm still traveling and don't have much time. Regarding this whole rotation mess - I can either revert some of the changes that I made in v2.0 so the prefabs are in more natural position and easy to rotate, or figure out how to solve rotating in current version. I feel that the first option would be better, but It could cause issues for people who created levels with the current version.
     
  16. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    It uses mostly Dijkstra pathfinding and a bit of A* pathfinding.
     
    Last edited: Jul 4, 2020
  17. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
  18. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    I used this resource a lot while working on the framework, you might find it useful

    https://www.redblobgames.com/
     
  19. Jon_Brant

    Jon_Brant

    Joined:
    Mar 22, 2018
    Posts:
    56
    Try using Debug.Log( this.GetComponent<Animator>().GetCurrentAnimatorStateInfo(0).length) to make sure its length is what you think it is. Destroy(gameObject, seconds) will wait seconds before destroying. So that part looks good

    Also, A LOT of the questions you're asking are about Unity general coding, not about the kit. You really should be asking questions pertaining to the kit. It's not his job to teach you Unity. Not trying to be rude, but it's rude to spam the author with these questions having nothing to do with his asset.

    The Unity discord is VERY active. You can ask most of these in #General-Unity, or #General-code. You'll get a faster response, and not spam this thread. Here's a link to the discord. You can run it directly in your browser: https://discord.gg/YRaHM6
     
  20. Banksy

    Banksy

    Joined:
    Mar 31, 2013
    Posts:
    376
    Yeah I thought these were fairly broad Unity questions... sorry about that.

    Newbie wrestling with code... guess I'll move on now Sorry
     
  21. Meltedmen1983

    Meltedmen1983

    Joined:
    Jul 4, 2020
    Posts:
    1
    Hello! I have a problem buying in Asset Store. I paid 15 dollars but not received framework. What should I do ? maybe this program mistake. I can send screenshots
     
  22. Jon_Brant

    Jon_Brant

    Joined:
    Mar 22, 2018
    Posts:
    56
    If the purchase went through, you should be able to see "Open In Unity" instead of "Add to cart" in the asset store. If you do, you can open a project and click "Open in unity" and it should open the package manager in Unity, where you can download it into your project
     
  23. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
  24. thomas_superFASTgames

    thomas_superFASTgames

    Joined:
    Jul 15, 2017
    Posts:
    23
    Are we able to define how a unit moves? Say, to have a unit that can only move horizontally and/or vertically?
     
  25. Jon_Brant

    Jon_Brant

    Joined:
    Mar 22, 2018
    Posts:
    56
    I feel like you couldn't do that without rewriting the pathing algorithm. When it's searching neighbor nodes, make the restriction there. I don't have it open at the moment to check if you can inherit from and override the base pathfinder though
     
  26. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Well, you need to restrict neighbours in pathing algorithm, but there is a dedicated method for this in Unit script :) Just override IsCellTraversable method in your derieved script like this:

    Code (CSharp):
    1. public override bool IsCellTraversable(Cell cell)
    2. {
    3.         return base.IsCellTraversable(cell) &&
    4.             (cell.OffsetCoord.x == Cell.OffsetCoord.x
    5.             || cell.OffsetCoord.y == Cell.OffsetCoord.y);
    6. }
    upload_2020-7-6_8-10-40.png
     
    Jon_Brant likes this.
  27. Banksy

    Banksy

    Joined:
    Mar 31, 2013
    Posts:
    376
    Am still unsure about the movement system being used for this asset. I've had a friend at work (Unity teacher ) go over the code and he simply says it really needs to be changed as its simply a little "weird" if that's a tech term.. without sounding rude :)

    Michael could you please send me the old method of movement so I can have another go at unit direction / rotation.
     
  28. Banksy

    Banksy

    Joined:
    Mar 31, 2013
    Posts:
    376
  29. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Wow, looks good already. I will send you the previous version, could you contact me by email at crookedhead@outlook.com?
     
  30. Banksy

    Banksy

    Joined:
    Mar 31, 2013
    Posts:
    376
    Thanks for that Michael. Now I understand the issues faced with updating the current setup.. For example the Grid Helper needs to be factored in. It's not as simple as swapping out Unit.cs and making a few adjustments to each unit.

    note: I'm only focusing on Example 1 here.

    Hhmm..
     
  31. Banksy

    Banksy

    Joined:
    Mar 31, 2013
    Posts:
    376


    Having a little FUN
     
  32. MikaelEriksson

    MikaelEriksson

    Joined:
    Jul 10, 2018
    Posts:
    3
    Hello,
    This seems like a nice kit. Is there some way to let the units have a current direction? (E.g on a hex grid a unit points to one of the six directions) and take that in consideration for movement? What I want to do is that a unit have to spend movement points to turn and also might have to move a certain number of times in a straight line before turning.

    Best regards
     
  33. BenoitMenard

    BenoitMenard

    Joined:
    Jul 5, 2018
    Posts:
    1
    Hello!

    This framework looks wonderful for what I'm trying to achieve. I've been through the FAQ and documentation and I think I'll have access to the features required. But I just want to double check with you prior to going ahead.

    Made in 2D.
    The main portion of the game happens in a semi open world with multiple areas to travel between.
    Enemies sprites are scattered around and will chase you if within distance. If they collide into the player sprite a battle scene will begin. Which will bring us to your framework/battlefield.

    So what needs to happen for all of this is the following:

    A menu option to open up the grid to place your team and formation, without enemies. And plan how you battle. So that every engagement it will pull that information and place your units where you have them put automatically. So that way when you unlock more heros as you progress. You can customize your team.

    Same goes for enemies. Depending on what enemy/sprite collided. A preset formation of enemies is placed on their side of the field that is also predetermined. So all kinds of enemies will have different formations that are pre established.

    Depending on the results of the battle scene. We are sent back to the game world and a screen will pop up either saying you lost/died or the experience/loot earned from the battle.

    I also wonder if it's possible to instantiate a timer for some battles. That if you dont win within a certain time limit. You automatically lose.

    Other options are:
    Different map sizes and types(tilepaint). I believe I've seen in the examples of other games you can edit different scenes however you like. They just need to be called upon I imagine? Have different presets created and when a certain one is needed it is pulled based off the sprite collider/location in the world the player is in.

    The area of effect that is a out of box solution. When it hits the unit it simply looks for nearby cells and passes the same values/animations.

    I believe that's the most of it. The rest is covered or clearly stated that it is possible. If I think of anything else I'll ask :)

    Thanks for your time,
    Benoit
     
  34. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Hey, sorry for delayed reply. This feature is not available out-of-the-box, but can be added easily. Earlier this year I was working on a project for a client and coded something similar.

    First of all, you should add a new field to your derived Unit class (an enum that would have six values). Next you would need to include that in game logic of course, which would be just a bit more complicated, but nothing too complex. Let me know if you want to implement it and have any issues.
     
  35. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Hey, let me answer the questions that are framework-specific :)

    First issue that I see is that you will need some kind of deployment phase. This is not included in the framework, but I've seen a few times that users managed to code it themselves. I would be happy to help if you have any issues.

    Regarding map sizes and types - sure, you can have maps with different sizes and tiles. I imagine you would want the grid to have different look depending on where the encounter happens in your world. You can achieve this by either creating preset-levels for each type of terrain in your world (easier), or create a more roboust solution that would generate the map on runtime (harder)

    Lastly, area of effect attacks - not available out-of-the-box but I've seen users adding it.

    The rest of the questions are not framework-specific and I don't see any issues with them :)
     
  36. Gamingbir

    Gamingbir

    Joined:
    Apr 1, 2014
    Posts:
    195
    for some reason, it is giving me some package manager error after I imported the plugin. I am using unity 2019.4.4f1

    Library\PackageCache\com.unity.package-manager-ui@2.0.7\Editor\AssemblyInfo.cs(7,12): error CS0246: The type or namespace name 'UxmlNamespacePrefix' could not be found (are you missing a using directive or an assembly reference?)
     
  37. Gamingbir

    Gamingbir

    Joined:
    Apr 1, 2014
    Posts:
    195
    I found the solution when importing your framework it ask to upgrade unity package manager. If you just skip it works fine. So don't upgrade.
     
  38. Banksy

    Banksy

    Joined:
    Mar 31, 2013
    Posts:
    376
    Wondering if anyone has found a solution for rotating a unit in the direction it moves & then face the enemy unit on attacking ?
     
  39. MikaelEriksson

    MikaelEriksson

    Joined:
    Jul 10, 2018
    Posts:
    3
    Thank you for the answer, I have bought the kit and will do some experimenting :)
     
  40. Sehadet

    Sehadet

    Joined:
    Feb 25, 2020
    Posts:
    4
    Hello,

    This asset looks really neat and I'm thinking of purchasing it. I just have one question.

    Does the framework support a way for a unit to continue moving after it has attacked and for a unit to potentially attack multiple times per turn?

    Thanks :)
     
  41. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Hey,

    Each unit has the following two fields - MovementPoints and ActionPoints. The first indicates how far the unit can move, the other how many attacks it can perform each turn. If you set ActionPoints to more than 1, the unit will be able to attack, move and attack again (considering it has enough MovmentPoints left) :)

    One thing to note - if the unit has MovementPoints left, but run out of ActionPoints it will be unable to move any further in this turn. It would be pretty easy for you to change it if you don't like it.
     
  42. Sehadet

    Sehadet

    Joined:
    Feb 25, 2020
    Posts:
    4
    Ah, cool!

    I bought the asset and I'm already liking it.

    I'm new to coding so it'll probably take me a while to change all the bits to my liking, but I'm sure that it will be a much shorter while than if I had to figure everything from scratch so thank you for making this asset. :)
     
  43. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Let me know if you have any questions :)
     
  44. Banksy

    Banksy

    Joined:
    Mar 31, 2013
    Posts:
    376
    Anyone manage to get their player unit to rotate in the direction they move ??
     
  45. Sehadet

    Sehadet

    Joined:
    Feb 25, 2020
    Posts:
    4
    Gladly! :D

    I'm wanting to make it so that the unit stats(movement, action, health) for some units in a TBS framework scene are based on variables from a previous non-TBSF based scene.

    I assume that they way to do this is to store those variables in some dontdestroyonload object and then have the specific Unit subclass script refer to those variables to set the stats.

    I figured that if this works for just simple values it will work for variables as well so I put this into the "Generic Unit" script in the Lumberjacks vs Soldiers example.

    Code (CSharp):
    1. public void Reset()
    2.         {
    3.             MovementPoints = 1;
    4.             HitPoints  = 1;
    5.         }
    I expected that this will make all the lumberjacks and all the soldiers have 1 hp and move only 1 square. But it did nothing and the stats for the units still all fully derive from the write in menus in the inspector. I tried doing the same with "TotalHitPoints" as well but it was not accessible.

    I'm now at a bit of a loss as in what to try next. Could you please advise me on how to achieve what I want?

    Thank you! :)
     
  46. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Yeah, you should try changing TotalMovementPoints and TotalHitPoints. While TotalMovementPoints is protected and should be accessible from derived classes, setter of TotalHitPoints indeed is private. Try changing it to protected :)
     
  47. Sehadet

    Sehadet

    Joined:
    Feb 25, 2020
    Posts:
    4
    Hi, thanks :)

    I got it working by first moving the thing into initialise override which made HitPoints start changing. Then TotalMovementPoints was also private so I changed it to protected and then it started to work as well. :)
     
  48. Quiet_Apples_Studios

    Quiet_Apples_Studios

    Joined:
    Jan 27, 2020
    Posts:
    17
    In Example 1, I've tried to implement a system where the unit will sacrifice some HP on attacking someone else.
    The problem is despite this reducing their health to 0, they do not die, not only that but the UI is not updating.
    Code (CSharp):
    1.         protected override AttackAction DealDamage(Unit unitToAttack)
    2.         {
    3.             HitPoints -= 35;
    4.             return base.DealDamage(unitToAttack);
    5.         }
    Figured it out by using but I've come into another problem, I do not want my attack to be influenced by defence, I'm thinking a enum would be best but I'd like to know what would be the best way to implement different types of attacks.
     
    Last edited: Aug 6, 2020
  49. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Good point, in the current implementation for a unit to die, it needs to be attacked by another unit. I could probably decouple this somehow for future releases to facilitate use cases such as yours. The GUI wasn't updating because it waits for UnitAttack event to be invoked.

    Regarding your second issue, you could override Defend method with someting like this to cancel out the defence factor:
    Code (CSharp):
    1. protected override int Defend(Unit aggressor, int damage)
    2. {
    3.        return base.Defend(aggressor, damage) + DefenceFactor
    4. }
    If you want to get some enum envolved then I guess you will need to extend the methods like Defend with another parameter.
     
  50. Neil2TheKing

    Neil2TheKing

    Joined:
    Sep 14, 2017
    Posts:
    15
    Thank you for the Asset! it's great. I am relatively new to unity and am having trouble with the add_unit method. I feel like I'm supposed to call it from the Unit script, but Unit doesn't have a reference to CellGrid as far as I can tell. Could you show me an example of a wolf unit that summons four more wolves to adjacent Tiles (it's calling the pack). Thanks so much!