Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

[RELEASED] Turn Based Strategy Framework

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

  1. Quiet_Apples_Studios

    Quiet_Apples_Studios

    Joined:
    Jan 27, 2020
    Posts:
    17
    I just wanted to know if there was a way to call an attack twice, so not just allowing the player to attak twice but to attack twice.
    Im trying to create a follow up system where if a certain condition is met they attack twice instead of once.

    I'd also like to get the run down on how I could implement a retaliation system where if they attack me (and i am in range) I attack them (not just dealing damage to the foe).

    thanks for the help again
     
  2. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Thanks, nice to hear that you like it :). It would be convenient to create a script derived from CellGridState and spawn your unit in OnCellClicked method. CellGridState classes have a field with reference to CellGrid, so you don't need to worry about that. You will need to trigger you spawning ability somehow (with a button for example), and then assign your CellGridState implementation to CellGrid.CellGridState.

    You can start by modifying one of existing CellGridState classes, like CellGridStateWaitingForInput class. Try it out and if it's still confusing for you then let me know.
     
  3. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Hmm, this sounds like good use case for AttackActionPerformed (you could trigger another attack there), but the problem is that this function doesn't have reference to unit that was attacked. You can try adding this parameter, the method that calls AttackActionPerformed has reference to the unit, so it would not be a problem to pass it.

    The same goes for your second questions, you could use DefenceActionPerformed to trigger counterattack, but again, it doesn't have reference to unit that attacked. Try adding this parameter like in the previous case.

    I would be interested to know if that worked out, so please let me know if you can :)
     
  4. Banksy

    Banksy

    Joined:
    Mar 31, 2013
    Posts:
    376
    Anyone manage to get a unit to rotate in the direction of travel ??

    I'm under the impression the latest version of TBSFs "Custom Unit Generator " which relies on the unit prefab to be positioned horizontally to allow for flipping once play starts. This pre-positioning of the prefab is problematic for animations applied to character units.

    Hope in the next update this can be rectified.
     
    Last edited: Aug 11, 2020
  5. Neil2TheKing

    Neil2TheKing

    Joined:
    Sep 14, 2017
    Posts:
    15
    Banksy, try taking a look at the MovementAnimation() function in Unit. It calculates the direction the unit needs to move, so you can use that info to tell your code which direction to turn your unit!

    Hi Michal, I mostly got it figured out. I created a method in Unit that is called from CellGridState. CellGridState passes forward a reference to cellgrid to help add the new unit properly. This works as long as the old Unit and the new Unit use different prefabs. For instance a magician can spawn a rabbit, a chicken can spawn an egg, but spawning a wolf from a wolf causes a bug where the new wolf's Movement Points equal 0. I I got around this by creating two prefabs, wolf1 and wolf2, but i was wondering if there is a more elegant solution. Here is my code


    //sourceCell is the cell on which to create the new unit. cellgrid is the 1 cellgrid object
    public override void PerformAction(Cell sourceCell, CellGrid cellgrid)
    {
    //tell the code this action creates new unit instead of attacking
    if (actionType == ActionType.Create)
    {
    //unitToCreate is a public GameObject variable. it represents the prefab to create
    if (sourceCell.IsTaken||unitToCreate==null)
    {
    return;
    }
    //Issue: CreatedUnit can not use same prefab as this
    GameObject createdUnit = Instantiate(unitToCreate);
    sourceCell.IsTaken = true;
    createdUnit.transform.position = sourceCell.transform.position;
    createdUnit.GetComponent<Unit>().Cell = sourceCell;
    sourceCell.CurrentUnit = createdUnit.GetComponent<Unit>();
    createdUnit.GetComponent<Unit>().PlayerNumber = this.PlayerNumber;
    createdUnit.GetComponent<Unit>().Initialize();
    createdUnit.transform.SetParent(cellgrid.GetComponent<CustomUnitGenerator>().UnitsParent);
    createdUnit.name = createdUnit.GetComponent<Unit>().unitName;
    cellgrid.AddUnit(createdUnit.GetComponent<Transform>());
    this.canAct = false;

    }

    Also, what is your recommendation for transforming units? Suppose I wanted a magician to transform a duck into a dragon. What would you recommend? is there a way to do it without destroying the original gameobject?
     
  6. Banksy

    Banksy

    Joined:
    Mar 31, 2013
    Posts:
    376
    @Neil2TheKing

    Regarding rotation of a unit towards destination cell - its had us stumped for a while now and we simply had to put things on ice. I've looked over the MovementAnimation() method in Unit.cs and to date still no luck.

    Here's what I tried:

    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, cell.transform.localPosition.y, transform.localPosition.z);
    8.                 Vector3 newDir = Vector3.RotateTowards(transform.forward, destination_pos - transform.position, Time.deltaTime * MovementAnimationSpeed, 0.00f);
    9.        
    10.                 // MB      --- rotateDir could be called in my LookDir.cs
    11.                 //  rotateDir = newDir;
    12.  
    13.                 while (transform.localPosition != destination_pos)
    14.  
    15.                 {
    16.                     //  newDir.z = 0;
    17.                     //  newDir.y = 0;
    18.                      transform.rotation = Quaternion.LookRotation(newDir);          
    19.  
    20.                     transform.localPosition = Vector3.MoveTowards(transform.localPosition, destination_pos, Time.deltaTime * MovementAnimationSpeed);
    21.                     yield return 0;
    22.                 }
    23.             }
    24.  
    25.             IsMoving = false;
    26.             OnMoveFinished();
    -- EDIT ----

    On looking over this problem again.... perhpas a unit should look at the "destinationCell" that's mentioned in the Move(); method (below) instead of using "destination_pos" (above)

    Code (CSharp):
    1.   public virtual void Move(Cell destinationCell, List<Cell> path)
    2.         {
    3.             var totalMovementCost = path.Sum(h => h.MovementCost);
    4.             MovementPoints -= totalMovementCost;
    5.  
    6.             Cell.IsTaken = false;
    7.             Cell.CurrentUnit = null;
    8.             Cell = destinationCell;
    9.             destinationCell.IsTaken = true;
    10.             destinationCell.CurrentUnit = this;
    11.  
    12.             if (MovementAnimationSpeed > 0)
    13.             {
    14.                 StartCoroutine(MovementAnimation( path));
    15.             }
    16.             else
    17.             {
    18.                 transform.position = Cell.transform.position;
    19.             }
    20.  
    21.             if (UnitMoved != null)
    22.             {
    23.                 UnitMoved.Invoke(this, new MovementEventArgs(Cell, destinationCell, path));
    24.             }
    25.         }
    worth noting - a unit does move and turn... but they turn to face down screen and keeps that rotation pointing down screen.
     
    Last edited: Aug 28, 2020
  7. Neil2TheKing

    Neil2TheKing

    Joined:
    Sep 14, 2017
    Posts:
    15
    Try changing the second parameter to just destination_pos instead of the difference. Hopefully that works
     
  8. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282

    Hey, nice to hear that you made this work, but honestly I have no clue what is going on here. Do you have some custom code in Initialize method? If you could debug it further and provide some insights maybe I could help :). The code that you posted seems good.

    Regarding the other questions, anything goes, really. It's more a Unity question, the framework doesn't care much about the details (unless you destroy the unit, then you need to add it to the game with code similar to what you posted). I would probably approach it by just swapping the 3d model / sprite and extracting unit stats to a scriptable object or something else that could be passed to a Transform method and apply the stats there.
     
  9. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Nice to hear that you are still trying, no update from my part sadly.
     
  10. Banksy

    Banksy

    Joined:
    Mar 31, 2013
    Posts:
    376
    @Neil2TheKing OK I've tried as you recommeded... The unit does turn a bit towards the destination now.. but only for the first movement on the ORC unit.

    VIDEO - Note: I turned on Debug.DrawRay to show direction of rotation ( notice how it looks straight down )


    Code (CSharp):
    1.  
    2. protected virtual IEnumerator MovementAnimation(List<Cell> path)
    3.         {        
    4.             IsMoving = true;
    5.             path.Reverse();
    6.             foreach (var cell in path)
    7.             {
    8.                 Vector3 destination_pos = new Vector3(cell.transform.localPosition.x, cell.transform.localPosition.y, transform.localPosition.z);
    9.                 // MB (below):  destination_pos - transform.position
    10.                 Vector3 newDir = Vector3.RotateTowards(transform.forward, destination_pos, Time.deltaTime * MovementAnimationSpeed, 0.00f);
    11.          
    12.                 while (transform.localPosition != destination_pos)
    13.                 {
    14.                      transform.rotation = Quaternion.LookRotation(newDir);              
    15.                      Debug.DrawRay(transform.position, newDir, Color.red);          
    16.  
    17.                    transform.localPosition = Vector3.MoveTowards(transform.localPosition, destination_pos, Time.deltaTime * MovementAnimationSpeed);
    18.                
    19.                     yield return 0;
    20.                 }
    21.             }
    22.             IsMoving = false;
    23.             OnMoveFinished();
    24.         }
    25.  
     
    Last edited: Aug 30, 2020
  11. froztwolf_unity

    froztwolf_unity

    Joined:
    Nov 21, 2018
    Posts:
    20
    Hi there.
    Recently bought the framework, really liking it so far, saves me a ton of groundwork for prototyping.

    I was wondering if there is any additional documentation or information out there about how to change the game state?
    I would like to do things such as only allow players to move a single unit each turn, add scoring, change the game end conditions, etc.
    So far I'm finding it tricky to see where and how these things are currently managed, given how event-based everything is. Is this all currently done through the GUIControllers, or am I looking in the wrong place?
     
  12. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Hey, first of all, nice to hear that you like it :). I'm afraid that apart from the documentation there is not much else. I agree that it could use another chapter about game state management. I'll keep that in mind, but for the time being, you are welcome to ask questions here or by email.

    Secondly, GUI controller is not what you are looking for. It only displays information about units and handles interface buttons (well, you could argue that it takes part in game management because you can trigger turn transition with it, but that's about it)

    Regarding features that you asked for - take a look at EndTurn method in CellGrid script, and CellGridState script and its subclasses - this is where game management takes place. That would be a start, let me know if you get stuck or have further questions.
     
    Last edited: Sep 4, 2020
    froztwolf_unity likes this.
  13. quakenbake86

    quakenbake86

    Joined:
    Jun 18, 2020
    Posts:
    1
    oof. i just need a quick start guide. im still new and thought this framework might help me understand the types of games i want to move towards.
     
  14. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Hey, did you read the documentation? There is a tutorial chapter that will help you get started. You can find the documentation here
     
  15. Banksy

    Banksy

    Joined:
    Mar 31, 2013
    Posts:
    376
    still no luck... (busy with work )
     
  16. Neil2TheKing

    Neil2TheKing

    Joined:
    Sep 14, 2017
    Posts:
    15
    Hey Michael, got the transformation stuff implemented. How would you recommend saving turns? For instance, if i wanted to return the cellgrid to its state five turns ago, is there a best way to do that?

    Banksy, for changing direction, I recommend overriding the GetNeighbors function in cell. you can store the neighbors as Cell variables and access them from your Unit class. Here is what I did for squares. You can do something similar for hexes:

    List<Cell> neighbours = null;
    private Cell eastNeighbour;
    private Cell westNeighbour;
    private Cell northNeighbour;
    private Cell southNeighbour;
    public Cell GetEastNeighbor()
    {
    return eastNeighbour;
    }
    public Cell GetWestNeighbor()
    {
    return westNeighbour;
    }
    public Cell GetNorthNeighbor()
    {
    return northNeighbour;
    }
    public Cell GetSouthNeighbor()
    {
    return southNeighbour;
    }

    public override List<Cell> GetNeighbours(List<Cell> cells)
    {
    if (neighbours == null)
    {
    neighbours = new List<Cell>(4);
    eastNeighbour= cells.Find(c => c.OffsetCoord == OffsetCoord + new Vector2(1,0));
    westNeighbour= cells.Find(c => c.OffsetCoord == OffsetCoord + new Vector2(-1, 0));
    northNeighbour= cells.Find(c => c.OffsetCoord == OffsetCoord + new Vector2(0, 1));
    southNeighbour= cells.Find(c => c.OffsetCoord == OffsetCoord + new Vector2(0, -1));
    if (eastNeighbour != null)
    {
    neighbours.Add(eastNeighbour);
    }
    if (westNeighbour != null)
    {
    neighbours.Add(westNeighbour);
    }
    if (northNeighbour != null)
    {
    neighbours.Add(northNeighbour);
    }
    if (southNeighbour != null)
    {
    neighbours.Add(southNeighbour);
    }
    }

    return neighbours;
    }

    I highly recommend youtube tutorials on this stuff. It takes a while to follow, but eventually the ball gets rolling
     
  17. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    This sounds like a good use case for 'command' design pattern, it's not implemented in the framework though (Actually, adding it could be a fun exercise). Other than that, you could add some kind of 'saveState' and 'restoreState' methods to CellGrid, where you would serialize and restore state of objects in the scene (just units should be enough).

    I would encourage you to implement 'command' pattern though, it should not be that hard and way more versatile.
     
  18. Banksy

    Banksy

    Joined:
    Mar 31, 2013
    Posts:
    376
    @Neil2TheKing Thanks for this insight.. I'll take a look over it tomorrow morning.
     
  19. Untrustedlife

    Untrustedlife

    Joined:
    Apr 21, 2020
    Posts:
    78
    Hey there! Been working with the asset and its great so far, though I have heavily modified some parts (eg i added a generate grid button to the ui so i could regenerate the map without clearing everything else from the scene and decoupled the grid generation code from the editor and such so i can generate maps during run time and now store grid coordinates and stuff for modifying the map at run time and so on but I do have some questions! one is more simple then the other three.

    (My game is 3d with a hex grid, btw)

    First question:
    I tried to run my game with only 1 player (the human player (Well a custom human player, with code basically identical to the one that the framework comes with)) but no matter what I change, even with a custom base unit class and such i still cant get the game to let me select and move my units when i'm the only player.(Even modifying the CellGrid code and the various state objects and stuff to make it not check for more then one player) That isn't a big issue i'm always going to have other "players" but i'm wondering if its something simple I missed.

    Second Question:
    Got any ideas for integrating player units that move on their own without human player input? (I want to have some indirect control in the game, but it doesn't seem like there's an obvious method of doing this without weirdness) ( Would I just make it loop through the indirectly controlled ones when play() is called in my human player?(actually now that i'm typing this that seems like the obvious solution heh))

    Third Question:
    Any starting points on how I would pull off having multiple separate grids in the game all running at the same time?
    I want to have an underground portion but if I can only have it loaded when looking at it its useless because i want players to be able to build underground bases to hide their activity from other players and such and to have underground dungeons players can move units around in while still playing on the main map.

    Fourth Question:
    How easy would it be for me to integrate a team that has units that can attack their own units? ( I want to have a "wildlife" team that sorta does their own thing)

    Also if you can point me to some fog of war conversations, i have fog of war but it doesn't play well with the grid (Its just a big plane with a lot of vertices that I dynamically alter the alpha of when parts of the map are explored, so I would prefer to have fog of war be part of the grid. (So I can block clicking and stuff)

    Anyway, thanks in advance, hope your weekend is going well and i eagerly await a response.
     
    Last edited: Sep 27, 2020
  20. Untrustedlife

    Untrustedlife

    Joined:
    Apr 21, 2020
    Posts:
    78
    I can help with this!

    I was able to get my units to turn towards the destination cell with this snippet! Hope it helps if you still needed it took me several hours to figure it out while hopped up on caffeine!
    I dont think our games are that much differnet, i'm also making a 3d strategy game with hex cells.

    I just put it in the move function right before the pathing happens.
    Presumably you could do this at every step in the path. Basically I get the rotation in radians, then convert it into degrees afterwards and correct for it flipping my x by 90 degrees. Also the multiplying by negative 1 is necessary because if you don't it rotates only between 0-180 degrees.
    Anyway, cheers, hope that helps.
     

    Attached Files:

    Last edited: Sep 27, 2020
    michal-zetkowski likes this.
  21. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Hey,

    Wow, that's a lot of questions :)

    1. The reason for this is that the game has hardcoded end game condition - it ends if there is only one player left. Unfortunatelly it is coded in a few different places. You will need to modify the following fragments:
    • Remove all from OnStateEnter method in CellGridState class
    • In EndTurn method from CellGrid remove the following lines
    Code (CSharp):
    1. if (Units.Select(u => u.PlayerNumber).Distinct().Count() == 1)
    2. {
    3.         return;
    4. }
    • Remove the following lines from OnUnitDestroyed method in CellGrid
    Code (CSharp):
    1. var totalPlayersAlive = Units.Select(u => u.PlayerNumber).Distinct().ToList();
    2. if (totalPlayersAlive.Count == 1)
    3. {
    4.       if (GameEnded != null)
    5.           GameEnded.Invoke(this, new EventArgs());
    6. }
    2. How about a custom Player class and adding some kind of field to your units (like 'isAutoContolled)? You could then loop through units belonging to the player (in Player.Play method) and in case of auto controlled units use some kind of AI and in case of human controlled units assign CellGridStateUnitSelected object with the unit as a paramter to CellGrid.GridState, so the unit can be controlled by the player as usual?

    3. Not sure what exactly you need, but I see two options:
    • you could just use grid generator multiple times to generate multiple grids - I think they would work independently without issues
    • you could generate a bigger map and divide it into multiple sectors that would basically act as separate grids (if you removed any connections between them)
    Either way, if you want to hide parts of the map from other players you can just deactivate game objects of what you want to hide. Should work fine.

    4. There are a few fail-safes that prevent units from the same team attacking each other. You should remove them
    • first of all, check out Unit.IsUnitAttackable. It returns false for same team units
    • next, there is CellGridStateUnitSelected.OnStateEnter - it will not consider same team units as attack targets (check out _unitsInRange list)
    • there will be a problem with CellGridStateUnitSelected.OnUnitClicked, because it considers clicking friendly unit as selecting it, not attacking
    • finally, AI does not consider friendly units as attack targets, check out NaiveAiPlayer.Play method
    Regarding fog of war, high-level idea would be as follows:
    • Add some kind of abstract MarkAsFogOfWar method to Cell class (implement it in your derived class)
    • Add a new field to cell that will store reference to unit that is occupying the cell
    • Check out visibility each turn before a player starts his turn and call MarkAsFogOfWar method on each cell that should not be visible, and deactivate gameobject of the unit that is occupying the cell
    It will probably be more complicated than it sounds, but the general idea seems good to me

    Let me know if that helped
     
  22. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Thanks for this :). @Banksy, could you check it out?
     
  23. Untrustedlife

    Untrustedlife

    Joined:
    Apr 21, 2020
    Posts:
    78
    Thanks for the response! Exactly what i needed, ill ask more questions as they arise.
     
  24. Untrustedlife

    Untrustedlife

    Joined:
    Apr 21, 2020
    Posts:
    78
    I was able to get fog of war implemented just fine so that's awesome! And also those earlier suggestions are great leads, i havent started on them yet.

    Alight here's one more question:
    How would you integrate towns/cities into the framework? Eg cities that can occupy a hex and probably also be attacked? Got any good starting points on that?
     
  25. cplungis

    cplungis

    Joined:
    Sep 11, 2019
    Posts:
    6
    Quick question - if a game ending condition were that the AI eliminated the human player, would you still need the code in OnStateEnter? I am thinking that the if statements would need to change to something like if (Units.Select(u => u.PlayerNumber).Distinct().Count() == 1 && PlayerNumber == 1) {...} to ensure that AI could win. I am assuming PlayerNumber 1 is the AI in this example.

    As I am looking to implement a capture the flag game, there would have to be an else to that to allow all the "flag" hexes to be captured. It seems like that else condition would also have to go in both OnStateEnter and EndTurn?
     
  26. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    First thing that comes to my mind would be to use units as cities. The advantage of this solution is that all systems are already in place, you would be able to attack the city (and easily add "capturing" mechanism), the city could provide buffs to other units (like healing when visiting) and this is the easiest and fastest way to do it. Just set movement points and attack range to 0 and any unit could act as perfectly normal city :). On the other hand, it's hackish which I don't really like, but If it works then why not (and I think it can work quite well)

    Another soultion would be to add cities 'natively', which would be a lot of work. Your questions made me think if it would be worth it to have some more "general" entity in the framework that could act as units / cities / etc and don't feel hackish. I would like to have such feature, but I don't think I will be able to work on it anytime soon.

    Lastly, you could kind of bypass the framework and just place object on the grid that would be your city and handle clicking / interaction in entirely different script. Integration with the framework could be done through some parameters stored in cell that the city is standing on. I don't really like this option.
     
    Last edited: Oct 3, 2020
  27. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    As I understand it, you would like to only end the game if the single remaining player is AI player, right? Your conditional statement is correct, but make sure that you have correct reference to PlayerNumber. Current player number is stored in CellGrid.CurrentPlayerNumber

    If you want to extend this end game condition, I believe you should add it in all the places that I listed in the post that you quoted. If you wonder how to keep track of captured cells, I would add a list to CellGrid and update it in OnMoveFinished method in Unit.

    Let me know if that helped
     
  28. redtroubadour

    redtroubadour

    Joined:
    Oct 9, 2019
    Posts:
    4
    Hello--does the asset support 2x2 GridCell units, like the varl characters in The Banner Saga? See image:



    If not, how would I begin to implement this? Thanks for your time.
     
  29. Untrustedlife

    Untrustedlife

    Joined:
    Apr 21, 2020
    Posts:
    78
    Thanks! Sorry for asking so many questions by the way!

    So i have to use units as buildings basically? Thats pretty gross, maybe i should add native support, any idea where to start on adding native support?
    I guess i would have to add some new grid states for that.

    Otherwise
    I would have to distinguish between "normal" units and buildings so that a unit could occupy the same cell as a building and also I would have to make cells distinguish between units and buildings probably.
    Sounds like a bit of a challenge but less of a challenge than native support to be fair. If I do it that way would it be best to do a new class with the framework's unit as its base class or should i use my current class with units as its base class and implement from there. (I have a MyGameUnit class with the ability to calculate whether they have attack advantages and such).
    I would also have to let the AI distinguish between them which I guess would mean just doing a linq query to grab units with the building base class or some kind of flag. (Though the ai is already kinda slow I haven't done any micro optimizations really aside from grabbing the grid and enemy units on play and moving away from linq queries in some places (I base dit on your NaiveAi) (Some pointers on how to optimize the AI would also be helpful, on a map the size of a huge civ map it takes like 3 seconds for it to do ai for only two other players, which is incredibly ludicrously slow)(Though i have optimized a bit since i last tested that size) (And the ai right now is just attacking enemies and positioning units on advantageous tiles when attacking (eg they wil move to a hill and attack down hill from that if they can because that grants a combat bonus, same with attacking from forests for a combat advantage and stuff (Its generalized so i can just add new tile types to an enum and it can calculate whethert hey have advantages from any tile using a switch statement where i define each tile's advantages), which actually makes the combat challenging :) )

    Heres a screenshot of the project so far btw.

    As you can see i have tooltips, fog of war, and alot of other stuff so far (I also have different faction types with different resources, in this case i am a cult) and i've been working on this for only about 2.5 weeks wouldn't have been able to do it as quickly without using your framework as a base. (I have modled, textured, and written the shaders for everything as well) the only unity store assets i'm using is the framework and easysave.

    upload_2020-10-12_2-0-2.png
    upload_2020-10-12_2-0-48.png
    upload_2020-10-12_2-1-38.png
     
    Last edited: Oct 12, 2020
  30. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Hey, sorry to say but there is no native support for units taking up multiple cells. Take a look at clearance based pathfinding linked below. I would start by implementing this algorithm (subclass IPathfinding interface in the project).

    https://harablog.wordpress.com/2009/01/29/clearance-based-pathfinding/
     
  31. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Wow, looks impressive. It makes me happy to see what users are able to achieve with the framework, thanks for sharing this :).

    I know that it sounds wrong to use units as cities but trust me, try it out. As I said before, I would go for a hybrid approach where you use units as cities but store some of the data in cell (for example any data regarding defence bonus or even a flag indicating that there is a city on this cell - that way you could easily distinguish it).

    Just uncheck 'isTaken' flag on the cell that the city is standing on and other units will be able to move there.

    I wouldn't advice to go for adding cities natively, unless the approach mentioned above fails. If you wanted to do it, then you should extend GridState classes with OnCitySelected, OnCityClicked methods etc. Alternatively, you could create some kind of abstract entity that could represent both cities and units in GridState classes. That would bring you closer to the first approach.

    Regarding AI, I can't relly say much. The bigger the map, the slower the AI will be, it is inevitable. Do some profiling and let me know what the bottleneck is, then I will be able to help you more :)

    BTW, if you managed to implement cities the way I described it, could you post the results? I would be really interested to see that.
     
  32. Panhypersebastos

    Panhypersebastos

    Joined:
    Feb 21, 2017
    Posts:
    44
    Hey, just grabbed this framework and so far it has been very useful.

    I've been able to get units added to the map mid game using the AddUnit() method, however right now you can just click any empty square and the unit gets added there.

    How would I go about restricting the available spawning locations for the new units to hexes that are adjacent to a player controlled city? (I am using a unit with zero movement points as a city).
     
  33. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Hey, good to hear that you implemented cities this way. How is it working for you so far?

    I would create another CellGridState for that purpose. In the last update I added a short chapter to documentation about GridStates, check it out. Or you can just do it your way :). Either way, you will need to have references to player-controlled cities (I assume you have a way to get them, if not, all units (so also your cities) are stored in CellGrid.Units list so you can grab it from there). Each city (actually unit) has a reference to a cell that it is occupying. With that reference you can query the cell for adjacent cells with cell.GetNeighbours. One thing to note here - GetNeighbours takes a list of all cells in the game as a parameters (you can grab it from CellGrid.Cells). Users sometimes have issues with this method and call it with empty list as parameter, therefore getting empty results. Does that make sense?
     
  34. Panhypersebastos

    Panhypersebastos

    Joined:
    Feb 21, 2017
    Posts:
    44
    Thanks, that works pretty well.

    Cities are working fine, though right now all I have them doing (aside from spawning units) is generating a set amount of gold each turn so there isn't much to go wrong. I will let you know if I implement some more complex logic for them.
     
  35. Untrustedlife

    Untrustedlife

    Joined:
    Apr 21, 2020
    Posts:
    78
    Nice to see someone else is making a 4x using this!
    I have not yet added cities, i've been making other changes. Adding standalone (And winnable :D ) scenarios, and implementing saving in a faster way/reworking tooltips and health bars and such
    (The below scenario is called High Ground) you have to take advantage of positional combat advantages to kill 24 enemy rogues with just two rangers. (If attacking down you get an advantage and so on)
    upload_2020-10-20_10-45-18.png upload_2020-10-20_10-44-1.png

    The rogue poking up from the hill in the fog of war is intended, if you are on a mountain or hill it will still draw you, so players can see what's on the top of mountains. Because its high up so it makes sense they would see something. Being on mountains and hills also grants a field of view advantage.
     
    Last edited: Oct 20, 2020
  36. thed-venth

    thed-venth

    Joined:
    Aug 13, 2014
    Posts:
    8
    really nice framework;)
    I already tried to learn something from the example scenes

    I want to ask something,
    is there idea how to Implement action list just something like FF Tactics
     
  37. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Hey,

    That depends on what options you would like to include in such a list. In case of options like move/act/wait/magic etc I would go for custom CellGridState classes. You can read about CellGridState in the new chapter in the documentation that is included in the current version of framework. Regarding options like Status, I would implement it in GUI script, you can check out sample scenes to see basic implementation of such option. Lastly, I would implement auto-battle by pluging in AI script to the current player.
     
  38. afoka

    afoka

    Joined:
    Jan 5, 2019
    Posts:
    1
    Hi,

    I'm aware that multiplayer is not supported by the framework itself, but anyway I wanted to ask if you know about someone achieving it or you maybe have ideas/suggestions on how to deal with it?

    Btw I really appreciate your work - it saves a lot of time.

    Thanks in advance.
     
  39. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Hey, sorry to say but I have no experience regarding multiplayer in Unity :(. If you decide to tackle it yourself and run into any issues, I'll be happy to help.
     
    afoka likes this.
  40. Untrustedlife

    Untrustedlife

    Joined:
    Apr 21, 2020
    Posts:
    78
    I was able to add buildings as units, i did have to change cell states a lot so it would know to prioritize units that are guarding buildings over buildings and stuff like that but it works fine. They also grant tax income. And a unit can occupy the same tile as a building and saving takes it into account so.
    upload_2020-11-1_14-11-39.png
     
  41. Untrustedlife

    Untrustedlife

    Joined:
    Apr 21, 2020
    Posts:
    78
    upload_2020-11-1_14-27-28.png Another screenshot
     
  42. Untrustedlife

    Untrustedlife

    Joined:
    Apr 21, 2020
    Posts:
    78
    the wildlife appears to have captured some villages lol upload_2020-11-1_14-30-48.png
     
  43. Untrustedlife

    Untrustedlife

    Joined:
    Apr 21, 2020
    Posts:
    78
  44. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Looking good :). BTW, you started quite a trend, I get asked a lot about this approach to cities implementation by email lately :). Good to see that it worked out for you.
     
  45. Panhypersebastos

    Panhypersebastos

    Joined:
    Feb 21, 2017
    Posts:
    44
    Hey,

    I want to rework the combat/damage system for my game so that there is potential for the attacking units to take damage. Is there a recommended way to do that with this framework?
     
  46. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Hey,

    I would code it either in Defend or DefenceActionPerformed method in Unit class. The problem with the first is that it is not virtual, the problem with the other is that it doesn't have a reference to a unit that was attacking. Either way you will have to modify existing code and I think I would go with option number 2. Just add the attacking unit as parameter to the declaration of DefenceActionPerformed and you will be able to code this feature in your subclasses.
     
  47. Untrustedlife

    Untrustedlife

    Joined:
    Apr 21, 2020
    Posts:
    78
    Cool, also i was able to optimize the AI significantly, so i don't have the slow AI issue anymore, the AI now also takes into account its own fog of war and only cares about tiles its explored/units it can see for all AI calculatitiopns so on my max size map which is larger then the max sized civ map, with 36 players it only takes like a second or two for all the players to finish their turns combined. SO :D I also hash things and treat buildings quite differnetly in the AI so its not just that change but i'm pretty happy with it.
     
  48. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Wow, that's pushing the limits right there :)
     
  49. tsoguojia

    tsoguojia

    Joined:
    Nov 17, 2020
    Posts:
    4
  50. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Hey, I would share it if I had it :). What issues were you having? I would suggest you start by modifying grid generator script using the resource that you linked (trust me, it's good). If you run into any problems, let me know here or by email.