• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
Question by Hez · Nov 12, 2015 at 11:01 PM · c#minecraftblocks

C# Better block world loading, generating and saveing

I have been working on this game for a few weeks, and I have gotten flat world generation, world save and world loading working, but it is slow. Moving and loading chunks will pause the game with lag, as will saving chunks. I am wondering if anyone is capable and willing to help, maybe I am doing things the slow way? maybe this would work on a better and faster computer then mine.

This is meant to be a rpg style game, so not too much focus is going to be put on building, but I still want some save-ability and world creation. I want people to make custom maps and share them.

sorry for the mess of code

This is in my move script

     public static void CheckChunks (){
 
         Vector3 PosDis = Vector3.zero;
         
         
         while (PosDis.y < 3){
             while (PosDis.z < 3){
                 while (PosDis.x < 3){
 
                     P = PlayerChunk + PosDis;
                     N = PlayerChunk - PosDis;
 
                     if (N.y < 0){N.y = 0;}
                     
                     string[] ChunkName = new string[]{
                         
                         P.x.ToString() + "." + P.y.ToString() + "." + P.z.ToString() + ".",
                         P.x.ToString() + "." + P.y.ToString() + "." + N.z.ToString() + ".",
                         P.x.ToString() + "." + N.y.ToString() + "." + P.z.ToString() + ".",
                         P.x.ToString() + "." + N.y.ToString() + "." + N.z.ToString() + ".",
                         N.x.ToString() + "." + P.y.ToString() + "." + P.z.ToString() + ".",
                         N.x.ToString() + "." + P.y.ToString() + "." + N.z.ToString() + ".",
                         N.x.ToString() + "." + N.y.ToString() + "." + P.z.ToString() + ".",
                         N.x.ToString() + "." + N.y.ToString() + "." + N.z.ToString() + "."
                         
                     };
 
                     CheckChunksNum = new Vector3[]{
                         new Vector3(P.x , P.y , P.z) ,
                         new Vector3(P.x , P.y , N.z) ,
                         new Vector3(P.x , N.y , P.z) ,
                         new Vector3(P.x , N.y , N.z) ,
                         new Vector3(N.x , P.y , P.z) ,
                         new Vector3(N.x , P.y , N.z) ,
                         new Vector3(N.x , N.y , P.z) ,
                         new Vector3(N.x , N.y , N.z) 
 
                     };
                     int count = 0;
                     while (count < 7){
                         if (!GameCore.ChunkLoaded.Contains (ChunkName[count])) {
                             Chunks.StartChunk(CheckChunksNum[count].x,CheckChunksNum[count].y,CheckChunksNum[count].z);
 
                         }
                         count++;
                     }
                     
                     PosDis.x += 1;
                     
                 }
                 PosDis.x = 0;
                 PosDis.z += 1;
             }
             PosDis.x = 0;
             PosDis.z = 0;
             PosDis.y += 1;
             
         }
     }


this in the move script update

         TimeToCheck += 1 * Time.deltaTime;
             if (TimeToCheck > 0.005f) {
 
 
                 if (transform.position.y > 0) {
                     CheckChunks ();
                     TimeToCheck = 0;
                 }
             }


this is the whole of my chunk loading and generating script

 using UnityEngine;
 using System.Collections;
 using System.Collections.Generic;
 
 
 public class Chunks : MonoBehaviour {
         
     
     public static string[] SortChunk;
     public static string[] SortBlocks;
     public static string[,] HoldChunks = new string[196,14];
     public static  string[,]  ThisBlock = new string[196,14];
     public static Vector3 ChunkNumbers = Vector3.zero;
     public static GameObject ThisObject;
 
     // Use this for initialization
     void Start () {
         LoadChunk();
         ThisObject = gameObject;
     }
     
     public void LoadChunk (){
         
         float X14Sect = Mathf.Floor(GameCore.PlayerLocation.x / 14);
         float Y14Sect = 0;
         float Z14Sect = Mathf.Floor(GameCore.PlayerLocation.z / 14);
         
         StartChunk(X14Sect,Y14Sect,Z14Sect);
         
         
         Vector3 AddToSect = Vector3.zero;
         bool OutAddToSect = false;
         float Switched = 0;
         float MultiplyerX = 1;
         float MultiplyerZ = 1;
         
         
         while (!OutAddToSect) {
             
             while (Switched <= 2){
                 while (AddToSect.x != (4 * MultiplyerX)) {
                     StartChunk (X14Sect + AddToSect.x, Y14Sect + AddToSect.y, Z14Sect + AddToSect.z);
                     AddToSect.x += MultiplyerX;
                 }
                 AddToSect.x = 0;
                 Switched += 1;
                 MultiplyerX *= -1;
             }
             
             Switched = 0;
             MultiplyerX = 1;
             MultiplyerZ = 1;
             AddToSect = Vector3.zero;
             
             while (Switched <= 2){
                 while (AddToSect.x != (4 * MultiplyerX)){                
                     while (AddToSect.y <= 7) {
                         StartChunk (X14Sect + AddToSect.x, Y14Sect + AddToSect.y, Z14Sect + AddToSect.z);
                         AddToSect.y += 1;
                     }
                     AddToSect.y = 0;
                     AddToSect.x += MultiplyerX;
                 }
                 AddToSect.y = 0;
                 AddToSect.x = 0;
                 Switched += 1;
                 MultiplyerX *= -1;
             }
             
             Switched = 0;
             MultiplyerX = 1;
             MultiplyerZ = 1;
             AddToSect = Vector3.zero;
             
             while (Switched <= 3){
                 while (AddToSect.x != (4 * MultiplyerX)){                
                     while (AddToSect.y <= 7) {
                         while (AddToSect.z != (4 * MultiplyerZ)) {
                             StartChunk (X14Sect + AddToSect.x, Y14Sect + AddToSect.y, Z14Sect + AddToSect.z);
                             AddToSect.z += MultiplyerZ;
                         }
                         AddToSect.z = 0;
                         AddToSect.y += 1;
                     }
                     AddToSect.z = 0;
                     AddToSect.y = 0;
                     AddToSect.x += MultiplyerX;
                 }
                 if (MultiplyerX == -1){ MultiplyerZ = -1; }
                 AddToSect.z = 0;
                 AddToSect.y = 0;
                 AddToSect.x = 0;
                 Switched += 1;
                 MultiplyerX *= -1;
             }
             
             AddToSect = Vector3.zero;
             OutAddToSect = true;
             //end while
         }
         
         
         
     }
     
     public static void StartChunk (float ChunkNumberx, float ChunkNumbery, float ChunkNumberz){
         string ChunkName = ChunkNumberx.ToString () + "." + ChunkNumbery.ToString () + "." + ChunkNumberz.ToString ();
         ChunkNumbers = new Vector3 (ChunkNumberx,ChunkNumbery,ChunkNumberz);
         if (!GameCore.ChunkLoaded.Contains (ChunkName)) {
             
 
             bool SkipStart = false;
             
             
             try {
                 
                 float SetX = ChunkNumberx * 14;
                 float SetY = ChunkNumbery * 14;
                 float SetZ = ChunkNumberz * 14;
                 string text = "";
                 try {
 
 
                     text = System.IO.File.ReadAllText ( Core.StaticWorldSaveLocation + @"\Dem\Soul\Land\" + ChunkNumberx.ToString () + "." + ChunkNumbery.ToString () + "." + ChunkNumberz.ToString () + ".dat");
                     
                 }
                 catch
                 {
                     GenChunck(ChunkNumbers);
                     SkipStart = true;
                 }
                 
                 if (!SkipStart){
                     GameCore.ChunkLoaded.Add (ChunkName);
                     GameObject ChunckCoreObject;
                     
                     SortChunk = text.Split ('-');
                     
                     ChunckCoreObject = (GameObject)Instantiate(Core.StaticChunk, new Vector3 (ChunkNumberx * 7f,ChunkNumbery * 7f,ChunkNumberz * 7f), Quaternion.Euler (0,0,0));
                     ChunckCoreObject.name = ChunkName;
                     ChunckCoreObject.GetComponent <ChunkCore> ().ChunkNumber = new Vector3 (ChunkNumberx, ChunkNumbery, ChunkNumberz);
                     
                     int SortTrys = 0;
                     
                     while (SortTrys < 14) {
                         
                         int setChunkDat = 0;
                         SortBlocks = SortChunk [SortTrys].Split (',');
                         
                         while (setChunkDat < 196) {
                             
                             HoldChunks [setChunkDat, SortTrys] = SortBlocks [setChunkDat];
                             setChunkDat += 1;
                         }
                         
                         SortTrys += 1;
                         //end setting chunk
                     }
                     
                     ThisBlock = (HoldChunks);
                     
                     int blockcount;
                     SortTrys = 0;
                     while (SortTrys < 14) {
                         int setChunkDatInt = 0;
                         
                         while (setChunkDatInt < 196) {
                             
                             if (int.Parse (ThisBlock [setChunkDatInt, SortTrys]) > 0) {
                                 int xR = Random.Range (0, 4);
                                 int yR = Random.Range (0, 4);
                                 int zR = Random.Range (0, 4);
                                 int RowNum = setChunkDatInt / 14;
                                 int CollomNum = 14 * RowNum;
                                 GameObject Block = (GameObject)Instantiate (Core.StaticBricks [int.Parse (ThisBlock [setChunkDatInt, SortTrys])], new Vector3 (((setChunkDatInt - CollomNum) + SetX) * 0.5f, (SortTrys + SetY) * 0.5f, (RowNum + SetZ) * 0.5f), Quaternion.Euler (90 * xR, 90 * yR, 90 * zR));
                                 Block.GetComponent <CubeCore> ().CubeChunkCore = ChunckCoreObject;
                                 Block.GetComponent <CubeCore> ().CubeChunk = ChunkName;
                                 Block.GetComponent <CubeCore> ().FromLoad = true;
                                 Block.GetComponent <CubeCore> ().CubeLine = new Vector2 (setChunkDatInt, SortTrys);
                                 ChunckCoreObject.GetComponent <ChunkCore> ().ChunkBlocks[setChunkDatInt, SortTrys] = ThisBlock [setChunkDatInt, SortTrys];
                                 ChunckCoreObject.GetComponent <ChunkCore> ().CubeList[setChunkDatInt, SortTrys] = Block.gameObject;
                             }
                             else{
                                 ChunckCoreObject.GetComponent <ChunkCore> ().ChunkBlocks[setChunkDatInt, SortTrys] = "0";
                                 
                             }
                             
                             setChunkDatInt += 1;
                             
                         }
                         SortTrys += 1;
                         //end spawning blocks
                     }
                 }
             } catch {GenChunck(ChunkNumbers);
             }
         } 
     }
 
     public static void GenChunck(Vector3 ChunkNumber){
         
         int counter = 0;
         int countery = 0;
         bool CanSave = false;
         string[,] ChunkBlocks = new string[196,14];;
     
         if (ChunkNumber.y < 1) {
             while (counter<196) {
             
                 ChunkBlocks [counter, 0] = "1";
             
                 counter++;
             }
             countery = 1;
             while (countery < 14) {
                 counter = 0;
                 while (counter<196) {
                     ChunkBlocks [counter, countery] = "0";
                     counter++;
                 }
                 countery++;
             }
         
         } 
     
         if (ChunkNumber.y > 0) {
             while (countery < 14) {
                 counter = 0;
                 while (counter<196) {
                     ChunkBlocks [counter, countery] = "0";
                 
                     counter++;
                 }
                 countery++;
             }
         }
                         
         string SaveBlocks = "";
         int SortTrys = 0;
         
         while (SortTrys < 14 ) {
             
             int setChunkDat = 0;
             
             while (setChunkDat < 195) {
                 
                 
                 SaveBlocks += ChunkBlocks[setChunkDat,SortTrys] + ",";
                 setChunkDat += 1;
             }
             SaveBlocks += ChunkBlocks[setChunkDat,SortTrys] + "-";
             SortTrys += 1;
             //end setting chunk
         }
 
         System.IO.File.WriteAllText( Core.StaticWorldSaveLocation + @"\Dem\Soul\Land\" + ChunkNumber.x + "." + ChunkNumber.y + "." + ChunkNumber.z + ".dat", SaveBlocks);
 
         StartChunk (ChunkNumber.x,ChunkNumber.y,ChunkNumber.z);
 
     }
     
     // Update is called once per frame
     void Update () {
         
         
         
         
         //end update
     }
 }
 

this is my chunk registration script

 using UnityEngine;
 using System.Collections;
 
 
 
 public class ChunkCore : MonoBehaviour {
 
     public string[,] ChunkBlocks = new string[196,14];
     public Vector3 ChunkNumber;
     public GameObject[,] CubeList = new GameObject[196,14]; 
 
 
 
     // Use this for initialization
     void Start () {
 
     }
 
 
 
 
 
     public void SaveChunk(){
 
         string SaveBlocks = "";
         int SortTrys = 0;
         
         while (SortTrys < 14 ) {
             
             int setChunkDat = 0;
             
             while (setChunkDat < 196) {
                  
 
                 SaveBlocks += ChunkBlocks[setChunkDat,SortTrys] + ",";
                 setChunkDat += 1;
             }
             SaveBlocks += "-";
             SortTrys += 1;
             //end setting chunk
         }
 
           System.IO.File.WriteAllText( Core.StaticWorldSaveLocation + @"\Dem\Soul\Land\" + transform.name + ".dat", SaveBlocks);
 
 
     
     }
 
     float DelayChunkGen = 0;
 
     // Update is called once per frame
     void Update () {
 
         DelayChunkGen += 1 * Time.deltaTime;
 
         if (DelayChunkGen > 1.5) {
 
         }
 
     }
 }
 

this is my cube registration script

 using UnityEngine;
 using System.Collections;
 
 public class CubeCore : MonoBehaviour {
     
     public string CubeName;
     public bool FromLoad;
     
     public float CubeNumber;
     public float CubeWeight;
     public float CubeBurn;
     public float CubeBreak;
     public string CubeChunk;
     public Vector2 CubeLine;
     public GameObject CubeChunkCore;
     
     static public string staticCubeName;
     
     static public float staticCubeNumber;
     static public float staticCubeWeight;
     static public float staticCubeBurn;
     static public float staticCubeBreak;
     
     
     // Use this for initialization
     void Start () {
         staticCubeName = CubeName;
         staticCubeNumber = CubeNumber;
         staticCubeWeight = CubeWeight;
         staticCubeBurn = CubeBurn;
         staticCubeBreak = CubeBreak;
         //try{
 
         
         if (!FromLoad){
             try{
             
             
             Vector3 ChunkName = new Vector3 (Mathf.Floor((transform.position.x )/ 7f) , Mathf.Floor(transform.position.y / 7f), Mathf.Floor(transform.position.z / 7f));
             CubeChunk =    ChunkName.x.ToString() + "." + ChunkName.y.ToString() + "." + ChunkName.z.ToString();
             CubeChunkCore = GameObject.Find(CubeChunk);
 
                 CubeLine = new Vector2 (Mathf.Floor((Mathf.Abs(CubeChunkCore.transform.position.x - transform.position.x) + (Mathf.Abs(CubeChunkCore.transform.position.z - (transform.position.z))*14))/0.5f), Mathf.Floor(Mathf.Abs(CubeChunkCore.transform.position.y - transform.position.y)/0.5f));
             if (!GameCore.ChunkLoaded.Contains(CubeChunk)){
                 HardBreak();}    
 
             if (CubeChunkCore.GetComponent <ChunkCore> ().ChunkBlocks[(int) CubeLine.x,(int) CubeLine.y] == "0"){
                 
                 try {
                     CubeChunkCore.GetComponent <ChunkCore> ().ChunkBlocks[(int) CubeLine.x,(int) CubeLine.y] = CubeNumber.ToString();
                     CubeChunkCore.GetComponent <ChunkCore> ().CubeList[(int) CubeLine.x,(int) CubeLine.y] = gameObject;
                 }catch{}
                 
                 
                 if (!GameCore.SaveChunks.Contains(CubeChunkCore)){
                     GameCore.SaveChunks.Add(CubeChunkCore);
                 }
             } else{
                 HardBreak();
             }
 
             }catch{HardBreak();}
         }
         
     }
     
     
     public void Break(bool IsDroping){
         if (CubeNumber > 2){
         CubeChunkCore.GetComponent <ChunkCore> ().ChunkBlocks[(int) CubeLine.x,(int) CubeLine.y] = "0";
             Destroy (gameObject);
             
             if (!GameCore.SaveChunks.Contains(CubeChunkCore)){
                 GameCore.SaveChunks.Add(CubeChunkCore);
             }
         }
     }
     public void HardBreak(){
         Destroy (gameObject);
         //CubeChunkCore.GetComponent <ChunkCore> ().ChunkBlocks[(int) CubeLine.x,(int) CubeLine.y] = "0";
         if (!GameCore.SaveChunks.Contains(CubeChunkCore)){
             GameCore.SaveChunks.Add(CubeChunkCore);
         }
     }
 
     public void OverRide(){
         CubeChunkCore.GetComponent <ChunkCore> ().ChunkBlocks[(int) CubeLine.x,(int) CubeLine.y] = "0";
     }
     // Update is called once per frame
     void Update () {
         
     }
 }
 

game core script

 using UnityEngine;
 using System.Collections;
 using System.Collections.Generic;
 
 public class GameCore : MonoBehaviour {
 
     public static Vector3 PlayerLocation = new Vector3 (1,10f,3);
     public static List<string> ChunkLoaded = new List<string> ();
     public static float VewingDis = 5;
     public static int StaticSeed;
     public static float BrushSize = 1;
     public static float PlayerHight = 1.708f;
     public static GameObject PlayerObject;
 
     public int Seed = 500;
     public float GameTimerSave = 0;
     public float SaveTime = 2;
     static public List<GameObject> SaveChunks = new List<GameObject>();
     static public bool RunSaveAll = false;
 
     void Start () {
 
         StaticSeed = Seed;
 
     }
     
 
     void Update () {
         GameTimerSave += 1 * Time.deltaTime;
     
         if (RunSaveAll) {
             SaveAll();
             RunSaveAll = false;
         }
 
         if (GameTimerSave >= SaveTime) {
             SaveAll();
             GameTimerSave = 0;
         }
 
     }
 
 
 
     public static void SaveAll(){
         try{
             foreach (GameObject UnsavedChuncks in SaveChunks)
             {
                 UnsavedChuncks.GetComponent <ChunkCore> ().SaveChunk();
             }
 
             SaveChunks.Clear();
         }catch{
         }
 
     }
 
 }
 

Comment

People who like this

0 Show 4
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Hez · Nov 12, 2015 at 11:52 PM 0
Share

you know, listing all the scrips needed for this to work makes me think maybe I should combined a few scrips.

avatar image ijidau Hez · Nov 12, 2015 at 11:58 PM 1
Share

Wowzers... I don't think anyone is going to take the time to read and figure that out. Can you do a screen grab and post a video of the result? This might help us understand what you are trying to achieve, from which we can hopefully point you in the right direction.

avatar image Hez ijidau · Nov 13, 2015 at 12:06 AM 0
Share

My computer can't run most screen capture, and the problem is fps going to 0, so yes a screen shot is what I am seeing, idk if it will help :( I am slowly starting to think it is a lack of good computer problem, also I save to a file directly under C:\, and I am stating to suspect that it may be a part of the problem, and I am trying to fix that now.

also, I AM saveing 20 5.3kb files, and I think that might also have an effect.

Show more comments

1 Reply

  • Sort: 
avatar image
Best Answer

Answer by JoshuaMcKenzie · Nov 13, 2015 at 01:59 AM

Your code is not documented very well so its a little difficult to pick up, Looking at your CheckChunks() function it appears that when you call this function you're checking a 7x7 grid of chunks and you attempt on checking them 200 times a second. Do you really need to check that many chunks? How big are they? Do you really need to check them that frequently? can you get away with checking a 3x3 once every... say 5 seconds?

You're also attempting to save all Chunks every 2 seconds, thus you're constantly writing to the disc when most times you don't need to. A chunk should be saved when its unloaded and when its changed (you can wait up to 10-20 seconds after the most recent change before attempting a save, long enough to reduce overhead and short enough that won't frustrate the player due to a potential crash).

I see that you are using many Try/Catches in your code. While they can work, they can be noticeably slower, especially if iterated over several times a second. It is better if you can structure your code where a try catch is never needed

I see your writing to file as a Plaintext file which for heavy data objects can slow down Saving and loading, and if its constantly creating new files that has overhead to it as well. If you're going to be loading and saving a lot of data frequently I would recommend a different approach, I would recommend looking into Scriptible Objects and the Live Tutorial. Even though the tutorial itself admits to being boring in the first half, the information it provides is pretty relevant to your performance issues as Scriptible Objects are similar to Databases in the sense that they are able to load/save volumes of data pretty quickly.

I have only seen a tiny portion of your game so I can't fathom how much work you may actually need to fix your issues, it may even be the issues your having are also due to some other code you haven't shown.

Using the Profiler is the easiest way at finding where the performance bottlenecks are.

Comment
ijidau
Hez

People who like this

2 Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Hez · Nov 13, 2015 at 03:14 AM 0
Share

I have failed to provide vital information in a drastic oversight, despite that you have helped me. ty

Unity Answers is in Read-Only mode

Unity Answers content will be migrated to a new Community platform and we are aiming to launch a public beta on June 13. Please note, Unity Answers is now in read-only so we can prepare for the final data migration.

For more information and updates, please read our full announcement thread in the Unity Forum.

Follow this Question

Answers Answers and Comments

32 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

15625 blocks are making my game lag? Increase performance? 3 Answers

Multiple Cars not working 1 Answer

Distribute terrain in zones 3 Answers

Ingame Texture Switcher 1 Answer

Setting Prefab with Code Returns NULL 2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges