Search Unity

Uniblocks: cube-based infinite voxel terrain engine

Discussion in 'Assets and Asset Store' started by RawLionWorkshop, Feb 2, 2014.

  1. JasonBricco

    JasonBricco

    Joined:
    Jul 15, 2013
    Posts:
    956
    Yes, each chunk is a mesh and so each chunk being rendered is a draw call. If you're rendering that chunk with multiple materials (in the form of a submesh), then it will have 1 draw call for each material being used, per chunk.

    The way you reduce draw calls is either stop rendering them or batch them together into even larger meshes (combine groups of chunks together into 1 mesh, for example. But you would have to be careful to not go over the vertex limit.)

    As for the 'stop rendering them' idea, some form of occlusion culling could be used to not render chunks that are blocked off by closer chunks (say, by a mountain). Frustum culling already occurs in Unity.

    Note that Unity won't automatically batch together meshes with the same material if they have too many vertices, which chunks typically do.
     
  2. RawLionWorkshop

    RawLionWorkshop

    Joined:
    Jan 29, 2014
    Posts:
    206
    That should be possible, but I think you will need to rebuild the mesh every time you want to change the materials, so you'd have to load each chunk twice (once when it's far away, and again when you come closer to it).

    Normally when you build a mesh, it is split into submeshes depending on the material index in the block settings, so if you want to apply the same material to all blocks you'll need to override this setting during the mesh building process. All of this is done inside ChunkMeshCreator, search for "submesh" and replace the references to the VSubmeshIndex with a 0 (only for distant chunks of course). Then you can safely replace the chunk's materials with just one material which will be used for all blocks in that chunk.

    But, again, you will need to rebuild the mesh (using all the materials this time) when you come close to the chunk, and rebuild it again when you go out of range. This will increase loading times, and it's possible that it would actually reduce overall performance instead of improving it.


    Other than that, one easy way to reduce draw calls is to just use bigger chunks. It's pretty much the same as batching - a 32x32x32 chunk is eight 16x16x16 chunks batched into one mesh - that's eight times less drawcalls.

    You should make your chunks as big as you can as long as they don't lag your game when you update the mesh (chunks that are too big take too long to update in a single frame, causing the game to freeze until the mesh is built).

    By the way, you don't need to worry about going over the vertex limit with big chunks since Uniblocks should automatically split meshes that go over the limit.
     
  3. Firlefanz73

    Firlefanz73

    Joined:
    Apr 2, 2015
    Posts:
    1,316
    Thank you both a lot for those hints :)

    I'll try and Play around, I just removed some more materials and it is getting better now.
     
  4. Firlefanz73

    Firlefanz73

    Joined:
    Apr 2, 2015
    Posts:
    1,316
    It hangs or is extremly slow when I use more than 16, which is my current chunk side length.
     
  5. Firlefanz73

    Firlefanz73

    Joined:
    Apr 2, 2015
    Posts:
    1,316
    Just an idea for somedbody who might have the same problems that on lower PCs it renders too slow:
    I decrease the camera view far:

    Code (CSharp):
    1.             if (Globals.FPS < 20 && Camera.main.farClipPlane > 80)
    2.                 Camera.main.farClipPlane --;
    3.             if (Globals.FPS > 30 && Camera.main.farClipPlane < 125)
    4.                 Camera.main.farClipPlane ++;
    5.             else if (Globals.FPS > 45 && Camera.main.farClipPlane < 150)
    6.                 Camera.main.farClipPlane ++;
    7.             else if (Globals.FPS > 60 && Camera.main.farClipPlane < 250)
    8.                 Camera.main.farClipPlane ++;
    9.  
    The FPS can be gotten from a "HUDPFS" script found on the unity wiki or via google or from other scripts. If anybody has a better idea or knows how to improve, please let me know!


    Now I reduced my materials in the chunk object a lot.
    But I Need items, which do not Need to be voxels but sometimes spawned as own Independent gameobjects just to collect.

    Is it okay to add meshes for identification in the block Editor? OR will it slowdown somewhere?
    They do not appear in the chunks itself, but it would be much easier for spawning and identification if I could give them a voxel number and a mesh in the block Editor. No materials in the chunk object, they have their own.

    Would that be okay? Have a nice Weekend :)
     
  6. RawLionWorkshop

    RawLionWorkshop

    Joined:
    Jan 29, 2014
    Posts:
    206
    Remember to also reduce the chunk spawn distance when you increase the chunk size. Bigger chunks will cover more voxels, so having the same number of chunks spawned means you way more blocks to render with bigger chunks.

    Sure, you can store a mesh reference in the block prefab. It won't slow anything down if you're not actually using it as a custom mesh in the chunks.
     
  7. Firlefanz73

    Firlefanz73

    Joined:
    Apr 2, 2015
    Posts:
    1,316
    Hello,

    it has gotten very quiet here in this Topic :)

    Are there any plans for an update? Maybe with some Little Performance improvement?
    Since I reduced materials and made a dynamic camera distance, the Rendering is better, but the spawning still is slow. Maybe a Little spawning in own thread improvement ? ;)
     
  8. Firlefanz73

    Firlefanz73

    Joined:
    Apr 2, 2015
    Posts:
    1,316
    And one question:

    in GenerateVoxelData I add premade Buildings on random positions. In These houses there are Special npcs.

    As Long as I did not save my world it was perfect. Sine I am using loading and saving now, for once created chunks GenerateVoxelData is not called anymore, right? So my houses are still there and my npcs are missing, because they are spawned when adding the blocks of that Building to the world, called by GenerateVoxelData.

    How do I spawn my npcs? Just Keep it the way they are, and everybody that once was spawned muss be added to a list? How can I spawn stuff that is right now spawned from GenerateVoxelData?

    Thanks a lot and have a nice Weekend :)
     
  9. jimmi1331

    jimmi1331

    Joined:
    Feb 7, 2016
    Posts:
    2
    Hi.

    First off, thanks. This is a very intuitive product and seems to perform very well for my purposes.

    I have a quick question (probably due to me being still a learner with unity). Is there a guide somewhere that covers using custom meshes in Uniblocks? While I've had no issue importing new textures to use with the standard mesh, and am able to assigning custom meshes via the block editor, I'm finding it impossible to figure out how to connect custom meshes to entries in the texture sheet.

    Sorry if this is a daft question, but help would be appreciated.

    Thanks
     
  10. Firlefanz73

    Firlefanz73

    Joined:
    Apr 2, 2015
    Posts:
    1,316
    Hi Jimmy,

    open the block Editor. Open a block inside it.
    There is a "material index". This is the index number of the chunk material in the chunk (the texture sheet). Set it and don't Forget to apply :)
     
    jimmi1331 likes this.
  11. jimmi1331

    jimmi1331

    Joined:
    Feb 7, 2016
    Posts:
    2
    Thanks Firlefanz73, perfect solution, and exactly where I was going wrong. Now, onward to discover new problems :)
     
  12. RawLionWorkshop

    RawLionWorkshop

    Joined:
    Jan 29, 2014
    Posts:
    206
    Sorry, I can't say anything about an update right now. There are plans for further performance upgrades in the future, but nothing specific at the moment.

    Well, presumably when loading the world, you also want to load the previous positions of npcs, instead of generating new ones every time, right? That means you will have to save and load them along with the rest of the world. Uniblocks only handles terrain, so for saving and loading npcs you might need to write your own solution.

    It could be a good idea to add them to some list, storing their positions and other persistent data, and save this list between sessions. You could also tie the saved npcs to their individual chunks somehow (for example, having a separate list for each chunk), so that you can load them at the same time as their parent chunk is loaded.

    Another idea, if you don't need to store any extra data other than position and type of npc, you can assign an npc type to a voxel id. Then, when saving the world, you place a voxel with that id at the position of each npc, and when loading, for each voxel of that id you spawn the npc of the corresponding type at the voxel's position. That way you can save the positions of npcs directly inside the terrain data.
     
  13. RawLionWorkshop

    RawLionWorkshop

    Joined:
    Jan 29, 2014
    Posts:
    206
    Custom meshes use their UVs to get the texture, and the UVs are relative to the entire texture sheet, not limited to any specific block entry on it. So in order to use a specific part on the texture sheet, you will need to adjust the UVs to fit the texture sheet you're using.

    This might be a bit awkward for pre-made meshes with already existing textures and UVs, but if you're making meshes for Uniblocks from scratch, with this system you're not limited to just one block's texture; you can mix textures from the entire texture sheet, or textures bigger than the standard block size, in each custom mesh, by unwrapping the UVs onto the whole texture sheet.

    You can also assign a different material for each mesh like Firlefanz73 said, but only do this if you don't have very many custom meshes. Having too many materials will kill your performance (each extra material is one extra draw call per chunk). This is why it is highly recommended to use texture sheets rather than separate materials.
     
  14. Endzone

    Endzone

    Joined:
    Dec 18, 2014
    Posts:
    119
    Just had a quick question, Does anyone know an easy solution for instantiating a prefab into the world when the terrain is being generated ? im trying to instantiate an oblesk but its a prefab (not made from blocks) and im not sure exactly how to go about getting it instantiated whilst the terrain is loading ive come up with a solution to make it be placed in game like any other block but as for instantiating it when the terrain is being generated im kinda lost :S
     
  15. RawLionWorkshop

    RawLionWorkshop

    Joined:
    Jan 29, 2014
    Posts:
    206
    You could use a system which assigns a specific voxel id to your prefab, similar to what I described two posts above. For example, let's say you have a voxel id 20 which is an empty block (transparent, no mesh, etc). Now, put a check inside the SetVoxel which checks whether the voxel being set is 20, and if so, instantiate your prefab at that voxel's position.
    SetVoxel is called during loading and generating data, so your prefabs will be placed as the chunks load or generate.

    You can also do this after a chunk has loaded instead. Go through all voxels in a chunk whenever one finishes loading, and if a voxel has the id assigned to your prefab, instantiate it.
     
    Endzone and Firlefanz73 like this.
  16. Firlefanz73

    Firlefanz73

    Joined:
    Apr 2, 2015
    Posts:
    1,316
    Thanks a lot maap! I will instantiate them in SetVoxel :)
     
  17. Endzone

    Endzone

    Joined:
    Dec 18, 2014
    Posts:
    119
    Hey maap thanks for the awesome reply it was extremely helpfull :) but this brings me to another question i have how do i go about getting a voxels position in my terrain generator script ? i know i need to use VoxelInfo but in the terrain generator script no matter what i do i cant seem to gain access to the VoxelInfo script to get a voxels position ?
    This is the pieace of code i normally would use in DefaultVoxelEvents script to instantiate a prefab:
    Code (CSharp):
    1. GameObject Prefab = (GameObject)Instantiate(Resources.Load("Prefab"), transform.position = voxelInfo.chunk.VoxelIndexToPosition (voxelInfo.index), transform.rotation = voxelInfo.chunk.transform.rotation ) as GameObject;
    But since i cant seem to gain access to VoxelInfo in my terrain generator script im a little lost as to how i go about getting the voxels position
     
  18. RawLionWorkshop

    RawLionWorkshop

    Joined:
    Jan 29, 2014
    Posts:
    206
    You can convert the local index of the current voxel to absolute world position using Chunk.VoxelIndexToPosition(x,y,z)

    The example terrain already does this, in this line:
    Vector3 voxelPos = chunk.VoxelIndexToPosition(x,y,z); // get absolute position for the voxel
    so you can just get the world position from voxelPos if you're using the example generator, or copy and paste this line into your custom generator script.
     
  19. Endzone

    Endzone

    Joined:
    Dec 18, 2014
    Posts:
    119
    Yea i tryed using voxelPos before i made the post but for some weird reason its giving me a whole heap of chunk errors where the chunks dont spawn coprrectly and it makes huge holes appear in the terrain
    this is my code to make my prefab spawn and as i said its giving me holes in the terrain :/
    Code (CSharp):
    1. // obelisk pass
    2.                     if (setToGrass && ObeliskCanFit(x,y,z) && currentHeight > 11 ) {
    3.                         if (Random.Range (0.0f, 2.0f) < 0.009f) {
    4.                                 chunk.SetVoxelSimple (x,y,z, 114);
    5.                                GameObject SpawnPrefab= (GameObject)Instantiate(Resources.Load("Prefab"), transform.position = voxelPos, transform.rotation = chunk.transform.rotation) as GameObject;
    6.                         }
    7.                     }
     
    Last edited: Feb 17, 2016
  20. Firlefanz73

    Firlefanz73

    Joined:
    Apr 2, 2015
    Posts:
    1,316
    I once got holes in Terrain because I used voxel numbers that did not exist.
     
  21. Firlefanz73

    Firlefanz73

    Joined:
    Apr 2, 2015
    Posts:
    1,316
    Is there a way to not render custom meshes or at least some of them (like gras) if they are far away?

    I have a dynamic far Clip for the camera (I decrease it if low fps) but gras etc. I would like to render only if it is near.

    Any idea? Thanks! :)
     
  22. Endzone

    Endzone

    Joined:
    Dec 18, 2014
    Posts:
    119
    i wish that i could say the same .. aha im using correct voxel ID's :/
     
  23. Firlefanz73

    Firlefanz73

    Joined:
    Apr 2, 2015
    Posts:
    1,316
    Put a try .. catch around every chunk method and put some logging into the catch block.

    If a Problem occurs, I bet you will find it this way! I did the same.

    Or Change your Settings in your Debugger to halt on every error.
     
  24. RawLionWorkshop

    RawLionWorkshop

    Joined:
    Jan 29, 2014
    Posts:
    206
    It would be helpful to know what errors specifically you're getting.
    Getting the position from voxelPos shouldn't cause any errors by itself, so I'm pretty sure there must be some mistakes elsewhere, but I can't really help any further without knowing all of your code...


    The only way I can think of, is that you can have the grass and other custom meshes use a different material from the rest of the terrain, then remove the material from chunks that are far away and add the material again when the chunks get closer. This should make your custom meshes invisible (because they don't have the material they need) and will reduce the number of draw calls for far chunks, but I don't know whether it will actually improve performance, since reassigning the materials array for the chunks constantly might be pretty costly.
     
  25. Firlefanz73

    Firlefanz73

    Joined:
    Apr 2, 2015
    Posts:
    1,316
    Thanks for the idea maap!

    Which will be more performant you think?

    Lava with some emissive lighting factor 2 for lighting near neighbor blocks, or make them have a real own light (like I do for torches)? Or a better idea for glowing Lava? Maybe Gold could also glow a bit that would look good :)
     
  26. Endzone

    Endzone

    Joined:
    Dec 18, 2014
    Posts:
    119
    I get no errors at all the code seems to be fine(the code i quoted above is what im trying to use to instantiate the prefab when its block is placed when the terrain is generating) but when i use the code i showed above to instantiate a prefab where the prefabs suppost to be in the cunk the whole chunk is just a hole in the terrain.? i get no console errors or anything its just whenever i use that code in my terrain generator script it just breaks the terrain ...
    Is their anyway you can make a simple script maap,? just so that when the terrain generates a sertin block it will place a prefab where that block is ? i have been stuck on this for almost 2 weeks and cant seem to find a solution that dosent break something... :/

    Code (CSharp):
    1. if (setToGrass && ObeliskCanFit(x,y,z) && currentHeight > 11 ) {
    2.     if (Random.Range (0.0f, 2.0f) < 0.009f) {
    3.             chunk.SetVoxelSimple (x,y,z, 114);
    4.             GameObject SpawnOblisk=(GameObject)Instantiate(Resources.Load("Magic_small_floating_obelisk2"), transform.position = voxelPos, transform.rotation = chunk.transform.rotation) as GameObject;
    5.  
    6.     }
    7. }
    i managed to make the oblesks spawn at one point but they where spawning where ever they liked and not on the block like it was suppost to :l ..
     
    Last edited: Feb 21, 2016
  27. RedEyeFox

    RedEyeFox

    Joined:
    Jan 8, 2013
    Posts:
    27
    hi maap!
    [sorry for my bad english i hope you will understand me]
    Yesterday i buy your voxel engine and i check the multiplayer feature, but this will not help for my project, i have an multiplayer shooter that uses photon for the network, i don't want a map that will have synchronization and the map will not be editable in the game, the idea is a map editor that will save the map and after that the player will be abel to play the map with friends, everything is ready but one thing i can't do, what data i can send to other players that will load the map, its that possible? thanks, and by the way this is the best voxel engine for unity i hope you will continue working on it.
     
  28. RawLionWorkshop

    RawLionWorkshop

    Joined:
    Jan 29, 2014
    Posts:
    206
    Emissive lighting sounds like a better option, because with individual lights you might end up having way too many of them in the scene, which is not good for performance. It's just a guess though; it would be best to test both options.


    Okay, looking closer at your code, your Instantiate line actually edits the position and rotation of the chunk GameObject, not the instantiated prefab. Your chunks aren't empty, they're just moved somewhere else whenever that line is called.

    Also, one thing I forgot to mention is that voxelPos is offset by seed in the default generator script, so you shouldn't actually use it directly unless you change that. You can instead just get the position using VoxelIndexToPosition again.

    Basically just replace your line with this and it should work:
    GameObject SpawnOblisk=(GameObject)Instantiate(Resources.Load("Magic_small_floating_obelisk2"), chunk.VoxelIndexToPosition(x,y,z), chunk.transform.rotation) as GameObject;
     
  29. RawLionWorkshop

    RawLionWorkshop

    Joined:
    Jan 29, 2014
    Posts:
    206
    If you use the default Uniblocks networking, all players will automatically download the map that is saved on the server, so all you need to do is edit and save your map on the server. That would be the easiest solution.

    If you don't want to use the default Uniblocks networking, check the UniblocksServer and UniblocksClient scripts to see how sending the map is handled, so that you can implement it in your networking solution.

    It's pretty complicated and the best thing to do would be to read the scripts carefully, but to break it down simply - the client loads chunks as normal, and when a chunk is loaded, it requests its data from the server using the SendVoxelData function. SendVoxelData compresses a chunk's data into a string, then sends the string as a byte array to the client, who then receives it with UniblocksClient's ReceiveVoxelData and passes it to the chunk.

    As far as I know Photon networking is pretty similar to the default Unity networking, so it might be possible to reuse most of the code as it is.


    If you don't want the players to edit the terrain, you can remove the block placing and removing functions from the DefaultVoxelEvents (OnMouseDown is where it happens), and then you don't need to worry about synchronizing the terrain changes between players.
     
  30. Endzone

    Endzone

    Joined:
    Dec 18, 2014
    Posts:
    119
    Thanks maap, awesome Help :D
     
  31. Endzone

    Endzone

    Joined:
    Dec 18, 2014
    Posts:
    119
    Hello, So i was wondering if anyone had any ideas on how to keep a train / cart on a track and add a force to it efficiently?, at the moment im using just the mesh collider on my track and on the cart it has 4 box colliders on either side of the rail where the trains "wheels" would be to essentially keep it from coming off the track but this dosent seem to be very effective when i add a force to it in a sertin direction the train usually gets stuck.. and this method also wouldn't be very effective when it came to turning corners so im kinda lost on what to do .. if anyone has any ideas i would love to hear them im honestly lost on what to do at this point haha :S Carts.jpg
     
  32. Firlefanz73

    Firlefanz73

    Joined:
    Apr 2, 2015
    Posts:
    1,316
    Looks nice. :)

    I can guess: Add a component called "Constant force" to it? I think that is meant to be used in such a case. But I have no experience in using it. If nobody knows here, you should look for some other Forum, I guess this has nothing to do with UniBlocks anmyore ;-)
     
  33. Firlefanz73

    Firlefanz73

    Joined:
    Apr 2, 2015
    Posts:
    1,316
    Hello maap or anybody who might know,

    like suggested before I spawn my important non player characters from SetVoxel methods for some Special data.

    Seems to work good, but when it has been spawned before and reloaded I get to this Special method:

    public void SetVoxelSimple(int rawIndex, ushort data)

    How do I get the Vector3 with real world Location in this case?

    Seems to work perfect for the other ones, I just do not know how to get the X, Y, Z from this one.

    Please help and have a nice weekende, thanks :)

    Firlefanz
     
  34. Endzone

    Endzone

    Joined:
    Dec 18, 2014
    Posts:
    119
    Hey, Thanks i will look into it :)
     
  35. RawLionWorkshop

    RawLionWorkshop

    Joined:
    Jan 29, 2014
    Posts:
    206
    This should convert the raw index to the local 3d index:
    Code (CSharp):
    1. int x = rawIndex % SideLength;
    2. int y = (rawIndex / SideLength) % SideLength;
    3. int z = rawIndex / (SideLength * SideLength);
    then you can use these x,y,z values to get the absolute position using the chunk's VoxelIndexToPosition(x,y,z).


    Keeping a train on tracks using just the physics engine could be tricky. I would consider using a different method, like for example hardcoding the movement so that it follows the curve of the track regardless of physics. Also try googling some tutorials on train / rail movement, there are probably many good solutions already available.
     
    Firlefanz73 likes this.
  36. witcher101

    witcher101

    Joined:
    Sep 9, 2015
    Posts:
    516
    Hi
    I just wanted to ask does this works on webgl and webplayer.
    In your assest page you have written that saving and loading doesnt work in webgl and webplayer.
     
  37. Firlefanz73

    Firlefanz73

    Joined:
    Apr 2, 2015
    Posts:
    1,316
    Works perfect, thanks maap.

    I works perfect when I let it be added like others voxels still: VoxelData[rawIndex]=data;

    Very good! One last question in this context pelase:

    I set the collider of my Monster / NPC voxels to None. How do I turn off the renderer for it (should be seen in Editor mode but not in Play mode). Set the material Color to transparent somehow or can I turn this single renderer off or something?

    If I do not add it to voxeldata it is not stored anymore and won't be added when loaded next time...

    Thanks a lot maap! :)

    Firlefanz
     
  38. Endzone

    Endzone

    Joined:
    Dec 18, 2014
    Posts:
    119
    Thanks maap i have since started coding it and yes i googled around for a little bit couldnt find a whole lot that was usefull for me so i have just started hard coding its movement and using the constant force component :)
     
  39. Kobaltic1

    Kobaltic1

    Joined:
    Jan 22, 2015
    Posts:
    183
    Any chance of upgrading to unet?
     
  40. RawLionWorkshop

    RawLionWorkshop

    Joined:
    Jan 29, 2014
    Posts:
    206
    You can use a transparent material, but a better way would be to use an empty texture from your main texture sheet (for example, with the default texture sheet setting the texture to x7 y7 will make the block invisible). This way you don't need to use any extra materials (which would increase your drawcalls).

    Yes, but probably not very soon. I'm afraid I can't give any specific details on future updates at this point.
     
    Firlefanz73 likes this.
  41. Firlefanz73

    Firlefanz73

    Joined:
    Apr 2, 2015
    Posts:
    1,316
    Very good idea, thanks a lot!
     
  42. Firlefanz73

    Firlefanz73

    Joined:
    Apr 2, 2015
    Posts:
    1,316

    I only have 4x4 textures in each texture Atlas. but I still can see it... it seems to work Modulo ;-)
    Shall I make a mini-mesh or 0 Vertices mesh or something?

    Or check the "Custom mesh" but set the mesh itself to None?
     
  43. RawLionWorkshop

    RawLionWorkshop

    Joined:
    Jan 29, 2014
    Posts:
    206
    In this case an empty mesh with 0 vertices would be the best option.
    I think custom mesh enabled with the mesh set to none will give you errors when updating chunks, but a mesh with no vertices should work fine.
     
    Firlefanz73 likes this.
  44. Safebox

    Safebox

    Joined:
    Mar 20, 2014
    Posts:
    8
    I have two questions:
    First of all I don't if it's been asked before but how would you import a greyscale image as a heightmap & generate terrain based on the values in the image? I tried using several variations of the following code but when generating the terrain it lags then drops to 2fps forcing me to close the program entirely. Code:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. namespace Uniblocks{
    5.  
    6.     public class DataEx : TerrainGenerator {
    7.  
    8.     public Texture2D datImg;
    9.  
    10.     // Use this for initialization
    11.         public override void GenerateVoxelData () {
    12.         int d = 0;
    13.         for (int x = 0; x < datImg.width; x++){
    14.             for (int y = 0; y < datImg.height; y++){
    15.             Debug.Log(datImg.GetPixel(x,y).r * 255);
    16.                 int p = (int)(datImg.GetPixel(x,y).r * 255);
    17.                 GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
    18.                 cube.transform.position = new Vector3(x,p,y);
    19.                 Index pos = Engine.PositionToChunkIndex(cube.transform.position);
    20.                 chunk.SetVoxelSimple(pos,1);
    21.                     Destroy(cube);
    22.                 d++;
    23.             }
    24.         }
    25.     }
    26.     }
    27. }

    Second question, is it possible to move a chunk (or several in this case) to a new position? Let's say I had a Hub location at (0,0,0) with the entrance to other worlds at (3,5,7), (2,1,8), etc. Would it be possible to relocate the hub world beside these entrances at any given time either by switching blocks with chunks already present there or by replacing existing blocks in the desired chunk & clearing the previous blocks' location?
     
  45. RawLionWorkshop

    RawLionWorkshop

    Joined:
    Jan 29, 2014
    Posts:
    206
    First of all, you should probably remove the Debug.Log from the loop, since it's actually really bad for performance if you run it many times per frame.

    Secondly, there is no need to create a new GameObject for every pixel (again, very bad for performance). You can probably just set the voxel directly:

    chunk.SetVoxelSimple (x,p,y, 1)

    This should work if you have you have a separate image for each chunk, so the x and y pixel coordinates are relative to the chunk, not the world.

    However, if you have one big image that covers many chunks, you'll have to apply an offset value to the coordinates depending on the chunk index (chunk index * chunk size). You add this offset when looking up the pixels, so that for example chunk 0,0,0 checks pixels from 0 to 15, chunk 1,0,1 checks pixels from 16 to 31, etc. (assuming chunk size is 16).

    Then you also have to consider the height - if the absolute p value is outside the chunk's range, you can't set it from inside that chunk's terrain generator. So you check if the height value of the pixel is within the vertical range of the chunk (by adding the offset to the local index) and ignore the pixel if it's not.

    Here's some example code that does what I explained here, you'll probably need to add some add some stuff to it but it should be a good starting point:
    Code (CSharp):
    1.         public Texture2D datImg;
    2.      
    3.         public override void GenerateVoxelData () {
    4.      
    5.      
    6.            int offsetX = chunk.ChunkIndex.x * chunk.SideLength;
    7.            int offsetY = chunk.ChunkIndex.y * chunk.SideLength;
    8.            int offsetZ = chunk.ChunkIndex.z * chunk.SideLength;
    9.      
    10.         for (int x = 0; x < chunk.SideLength; x++){
    11.             for (int y = 0; y < chunk.SideLength; y++){
    12.          
    13.                 // get height value from the image
    14.                 int p = (int)(datImg.GetPixel(x + offsetX , y + offsetZ).r * 255);
    15.              
    16.                 // check if the pixel height is in range of this chunk
    17.                 if (p >= offsetY && p < offsetY + chunk.SideLength) {
    18.                     chunk.SetVoxelSimple(x, p-offsetY, y, 1); // convert the absolute height to local index and set the voxel
    19.                 }
    20.              
    21.             }
    22.         }


    I'm not really sure what you want to do here... You can't move the chunks themselves, since their index is tied to the world location. You can replace the blocks at a specific location by destroying the chunks and reloading them using data from a different world (change the currently active world using Engine.SetWorldName("new name")).

    And I guess you could also move all voxels from one location to another by just manually iterating through all the voxels you want to move and copying them to a different location (using Chunk.SetVoxel with the same voxel id and a new index), if that's what you're looking for.
     
  46. Safebox

    Safebox

    Joined:
    Mar 20, 2014
    Posts:
    8
    Thanks for the quick response, that was exactly what I was looking for thank you. The second problem I was encountering is no longer a problem, I found a work-around using a different asset. Again thanks for your help, great asset.
     
  47. taw

    taw

    Joined:
    Mar 31, 2014
    Posts:
    3
    Hi some help please.. I have just installed this package and to have a quick look i opened the Demo scene.. all that happens is the player is floating in the air and i can not move. i am using Unity 5.2.0.f3 any help please
    Thanks
     
  48. Firlefanz73

    Firlefanz73

    Joined:
    Apr 2, 2015
    Posts:
    1,316
    Hi Maap,

    is it possible there is still a Problem with the collider when I use rotated meshes?

    I have a stair case voxel with mesh collider. One direction works perfect, a rotated Version does not work (I cannot climb up).

    Could you please have a look?

    Thanks a lot,

    Firlefanz
     
  49. RawLionWorkshop

    RawLionWorkshop

    Joined:
    Jan 29, 2014
    Posts:
    206
    Just hit space to unlock the player movement in the demo scene!

    Are you using the latest version of Uniblocks (1.4.1)? The colliders should work fine with rotated meshes with the newest version. I checked what I could, everything seems to work correctly...

    Do you get collider problems with other meshes as well? Also, can you check whether the collider is being built at all? You should be able to tell the shape of the collider by the green outlines when you select the chunk in the scene view. It would be helpful to know what exactly is happening to the collider. It's possible that your block is set to use a cube collider instead of a mesh collider, for example.
     
  50. Safebox

    Safebox

    Joined:
    Mar 20, 2014
    Posts:
    8
    Another question; is there a limit chunk distance? I'm at a chunk at 8080 X & Z but it stops generating after that. It might be something to do with my heightmap but I thought I'd ask while I mess around with the script.