Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

[WIP - Package] 2D Voxels\Tiles framework

Discussion in 'Works In Progress - Archive' started by Alessio89, Jan 29, 2015.

  1. Alessio89

    Alessio89

    Joined:
    Aug 8, 2014
    Posts:
    20
    Hi!
    In the last week my team and me were working at a prototype for our next project.
    At first we were going to make a 2D procedural sandbox game, following the style of games like Terraria and Starbound.

    I worked at a first prototype for it, but then we decided to take a different route, ditching completely the idea.
    However I was having a lot of fun building the prototype in unity and, since the project we finally decided to follow needed little coding, I kept working on the prototype, converting it in a framework for anyone who wants to build such a game without dealing with boring stuff such as: rendering, chunks management, simple water logic and so on.

    So I'm here to show you the work so far, keeping in mind that it's still all Work In Progress. I'm here for feedbacks :)

    How does this work?

    Once the package is imported, all you have to do to get up and running is to drop a ChunksManager gameobject in the scene and create a "player" (any object with the "Player" tag).
    At this point if you hit Play, the world is generated, starting from the root chunk expanding in all four directions recursively for a configurable range.

    Obviously it is very basic and default.



    How does it work, technically?
    The framework has these fundamental classes:
    • ChunksManager: Handles the creation and keeping track of chunks, layers and it also provides references to the most useful classes you might need to access quickly. It also makes sure that a chunk isn't created twice.
    • ChunkLogic: This is one of the Chunk Components. It handles everything that has to do with the logic of the chunk such as data handling, generation, updating the blocks and so on.
    • ChunkRenderer: This is another ChunkComponent. It handles the drawing of the chunk. The actual render instructions are in each block class, the ChunkRenderer just calls the Render method of the right block.
    • BaseBlock: The BaseBlock is an abstract class that contains everything a block needs to be used in game. (more on this later)
    • BlocksRegister: A static class that will link an ID to a block type, so that the AddBlock function knows what to instantiate given an ID. This might change soon however.

    Once the game starts, the ChunksManager will create a root chunk and the nearby chunks to give the world a "pre generation" to hide the generation of the chunks that will be generated at a later time.
    The chunks will update only if the player (that's why we need an object with the "Player" tag) is in a configurable range from it.

    Customization

    The framework is largely customizable: you can override blocks, generations, background layers, basically everything.

    Adding a new block requires (as of the current state) to know some basic coding. I will eventually build a user interface for those who don't want to mess with lines of code.

    The framework will come with a set of basic blocks such as EmptyBlock, DirtBlock, GrassBlock, StoneBlock, Water and Lava. By looking at how these work, you can easily figure out how to customize your blocks. I will put online a documentation with guides and tutorials as soon as the majority of the framework is stable and definitive.

    Some more screenshots before moving to more technical stuff:

    Default Generation that comes with the framework. You will be obviously able to customize this to any extent.


    Some details: (some of the sprites are placeholder)


    Adding a Custom Block

    Adding a Custom Block is pretty easy!
    All you need is to create a script which inherits from BaseBlock, write a constructor initializing the "type", "data" and "TextureUV" fields, override the Update method and you're done! Almost.

    The best way to show you is to create a block together. Let's create a "SnowBlock".

    Code (CSharp):
    1. public class SnowBlock : BaseBlock
    2. {
    3. public SnowBlock()
    4. {
    5.   type = 200; // The type is basically the ID that will be used
    6.   data = 0; // data is a byte value that can be used to store temporary values
    7.   TextureUV = new Vector2(0, 0); // The TextureUV is a Vector2 where the X and Y correspond to the X and Y in the atlas texture, starting from tthe bottom left.
    8. }
    9. public override void Update()
    10. {
    11.   // Do some logic here
    12. }
    13. }
    Some things to note.
    <type> is a byte value (this will be changed soon) that will be used as an ID for the block. When you will register the block (more on this later) you need to use the same ID as specified in the <type> value.
    <data> is a byte value used to store temporary values if needed, keeping the blocks scripts clean. You can however use how many variables you want in your script.
    <TextureUV> is a Vector2 where the X and Y coordinates correspond to the coordinates in the Texture Atlas. Let's make an example.
    If this is out texture (not made by me, but the guy at http://studentgamedev.blogspot.no/) and we want to give the SnowBlock the texture that is 4 blocks from the right, at the bottom row, the vector will be (0,3).
    If we wanted to use the top right texture, it would be (3,3), the bottom left would be (0,0).


    After writing our SnowBlock script, we need to register it. This will be eventually be done through an user interface, but for now in the BlocksRegister.cs file, we need to add a line in the Initialization method:

    Code (CSharp):
    1.  
    2. RegisterNewBlock (200, typeof(SnowBlock));
    3.  
    And now we're done! We can now use the SnowBlock by calling the AddBlock method of a given chunk like this:
    Code (csharp):
    1.  
    2. thisChunk.AddBlock(4, 3, 200);
    3.  
    And the framework will do the rest.

    - This thread is under construction and will be filled with more info as soon as humanely possible :) -

    The framework still needs a lot of work, that's why I'm opening this thread. I want to hear what people expects from this kind of tools, if there's anything that you think could be done better and any kind of feedback really.

    I will try to keep this post updated with everything I do, so expect to see more!

    P.S.: I'm trying my best, but my english is not perfect :)
     
    theANMATOR2b likes this.
  2. Alessio89

    Alessio89

    Joined:
    Aug 8, 2014
    Posts:
    20
    Wow! It's been some time since an update!
    I started working in a Game Developement company in Milan, Forge Reply, and between moving and working I had little time to actually do something on the system!
    But here I am with an update!

    I added and tweaked a basic "Water" block, using cellular automata, which can be used as a sample in the package to understand how to actually make fluids. It's not finished yet, it lacks the pressure simulation, but I'm quite satisfied with how it's coming up.
    Here's a video of it in action:


    One thing I forgot to mention: all the sprites are made by Francesco Segala (
    Francesco Segala - 2D and concept art).

    Also, I recently submitted on the Asset Store an editor extensions I made for a project, a Node Based Dialogue System. It's currently under review for the store and it's the first version, I will keep updating it for free on the store :)

    I will now keep on working on this framework to improve performance and write some utility to build a nice 2D Procedural game :)
     
    theANMATOR2b likes this.