Grim Legions – a turn-based strategy game

We’re currently working on a turn-based strategy game in Unity3d called Grim Legions. It’s a relatively simple game (much simpler than Crown of Conquest anyway), but still a lot of fun.

You get to control units that move around a hex-based map trying to capture towns. Each turn, the towns recruit more units. The aim of the game is simply to wipe out your enemy (destroy all their troops and capture all their towns). There can be up to 4 players (currently only 1 human player, but multi-player is planned), and you can make alliances with other players.

The start of a game - with a unit in the top right

The start of a game – with a unit in the top right

There are three different types of troop: infantry, archers and cavalry. There’s not much difference between these types, archers are just better than infantry, and cavalry better than archers. Unlike a lot of other games, you can combine multiple troop types in one unit (or “legion”), and you can split and merge them as much as you like.

One of the features we’re really happy with is the map generation. It is randomized, but you have a lot of control over it. E.g. if you get sick of your units taking ages to move through the mountains, you can just generate a map without mountains. You can also decide how much of the map you want to be water (which no troops can move through), from 0% to 60%. There are also 3 map sizes to choose from. This means – despite the relatively simple gameplay – there are quite a few different scenarios. You can end up spending a lot more time playing this game than you think!

Selecting options for map generation

Selecting options for map generation

We’re about 60-70% done, so should be ready to release in the next few weeks. It’ll be available for Windows, Linux, and WebGL (Mac release will be possible too if people are interested).

Creating a resizeable (endless) scrollview in Unity3d

In recent versions of Unity, a “Scrollview” UI element has been introduced. It’s very useful, but one thing that wasn’t obvious (to me, at least) was how to use it for something that has potentially infinite content. In my case, I have a message window which has text added to it at various points during the game. I wanted that text to be added to the bottom of a scroll view, but have the previous text still accessible via the vertical scroll bar.

Googling how to do this turned up a number of results. But none of them quite had the full picture of how to get it to work. So I figured I’d write this post to hopefully help future googlers, even though it’s actually pretty simple.

First, a couple of assumptions:

  • I’ve tested this in Unity 5.4, but it should work about as far back as 4.6)
  • These instructions are for a text only scrollview, but it can probably be easily adapted to other types of content

Ok, so here’s the instructions.

First add a Scrollview to your scene (obviously as a child of a Canvas). You’ll notice it comes with a bunch of objects, as shown in the screenshot below:

scrollview

The main one we’re really interested in is “Content”. If you click on it, you’ll see it’s just an empty RectTransform. To make it into something that we can add text to, you’ll need to either click ‘Add Component’ and add a Text component, or delete it and replace it with a Text component at the same place in the hierarchy. If you do the latter (which I did, because my Text components are Prefabs, so I can keep them consistent), you’ll need to click on the ‘ScrollView’ element, and drag the new Text object into the ScrollView’s ‘Content’ variable (as seen below).

scroll_rect_content

(You’ll also need to make sure the ‘Pivot’ settings on the Content object’s RectTransform are set to X=0, Y=1. This makes sure it sits at the top of the ScrollView object, and is the default for the Content object that’s created with the ScrollView).

Now click back onto the Content object, click Add Component, and add a ‘Content Size Fitter’ component. Set its Vertical Fit option to ‘Preferred Size’.

content_size_fitter

And that’s pretty much it! When you add text to the Content object, it will grow to fit the text. The Scroll View will then let you scroll around to see the text you’re interested in. That may be enough for some people, but there are a couple of things to tidy up (which I needed in my case), so I’ll explain those below.

Preventing Horizontal Scroll

You probably don’t want the Scroll View to scroll horizontally, so click on it, and uncheck the ‘Horizontal’ scroll bar. It’s likely harmless to leave this on (as your Text object, by default, will wrap text anyway), but it’s not necessary.

Adding Text Programmatically

The automatic resizing is only really useful if you’re adding text dynamically. It’s pretty straightforward to do this, but I’ll put it here for completeness. You just need to append text to the Text object. I have something like this:

string msgText = textObject.GetComponent ().text;
if (msgText != "")
    msgText += "\n";

msgText += newMessage;

textObject.GetComponent ().text = msgText;

This adds a new line before each new message, which is probably what you want.

Keep latest text visible

Each time you add a new message, you probably want it displayed. But by default, the Scroll View will be at top, and the user may move it around. So to ensure new messages are always seen, do this after adding a message:

Canvas.ForceUpdateCanvases();
scrollViewObject.GetComponent().verticalNormalizedPosition = 0f;

The first line forces the Canvas to do an update. This means the message you’ve added will now be taken into account by the UI system. The second line then scrolls to the bottom. And that should be all you need!

Final Thoughts

I haven’t needed to do this, but it should be quite easy to adapt the above to do resizeable/endless scroll with other types of content. Content Size Fitter can be put on any kind of UI object. Your Content object could be a Grid Layout, for instance, and you could add things into the grid at run time. This should mean it grows as necessary, and the older content scrolled off the screen.

Anyway, feel free to give my feedback on this post and let me know if it was useful.