Instantiate a sprite using json data value (C# Unity) - c#

Here is my code :
BetBoard_Test.cs
//Scoreboard
[SerializeField] protected GameObject prefab_big_road = null;
[SerializeField] Transform pos_big_road = null;
string jsonString = "[1, 1, 1, 2, 1, 1, 1, 2, 1, 2, 1, 1, 1, 2, 1, 1]"; //sample data
private void Start()
{
ExampleClass dataParser = new ExampleClass();
dataParser.dataToParse = jsonString;
//Convert to Json
string exampleClassToJson = JsonUtility.ToJson(dataParser);
Debug.Log(exampleClassToJson);
ExampleClass obj = JsonUtility.FromJson<ExampleClass>(exampleClassToJson);
//Loop over it
for (int i = 1; i < obj.dataToParse.Length - 1; i += 3)
{
char indivisualChar = obj.dataToParse[i];
Debug.Log(indivisualChar);
}
WinLog();
}
IEnumerator WinLog_big_road()
{
DeleteChildrens(pos_big_road);
yield return new WaitForEndOfFrame();
int[] array_big_road = tzPlayInfo.Instance._BIG_ROAD_;
for (int i = 0; i < rh.Const._HISTORY_COUNT_ * rh.Const._HISTORY_HEIGHT_; i++)
{
if (array_big_road[i] == 0) continue;
int x = i % rh.Const._HISTORY_COUNT_;
int y = i / rh.Const._HISTORY_COUNT_;
float xl = 9.0f;
float yl = -8.0f;
GameObject o = Instantiate(prefab_big_road) as GameObject;
o.transform.SetParent(pos_big_road);
o.transform.localScale = Vector3.one; //(1,1,1)
o.transform.localPosition = new Vector3(x * xl, y * yl, 0f);
o.GetComponent<UISprite>().spriteName = array_big_road[i] == 1 ? "layout_player_bigline-01" : "layout_banker_bigline-01";
NGUITools.SetActive(o, true);
yield return new WaitForEndOfFrame();
}
yield break;
}
void DeleteChildrens(Transform t)
{
NGUITools.DestroyChildren(t);
}
public void WinLog()
{
StopCoroutine("WinLog_big_road");
StartCoroutine("WinLog_big_road");
}
}
[Serializable]
public class ExampleClass
{
public string dataToParse;
}
ConstantValue.cs
public const int _HISTORY_COUNT_ = 70;
public const int _HISTORY_HEIGHT_ = 6;
PlayInfo.cs
public int[] _BIG_ROAD_ = new int[Const._HISTORY_COUNT_ * Const._HISTORY_HEIGHT_ ];
What i am trying to achieve here is that see image
my jsonString="[1, 1, 2, 2, 1, 1, 1, 2, 1, 2, 1, 1, 1, 2, 1, 1]"; that is converted into json format needs to do it something like this for example
1 = blue circle
2 = red circle
just like that in the picture every value on my json data needs to be instantiated with the sprite that is equivalent to 1 and 2 which is i have this condition o.GetComponent<UISprite>().spriteName = array_big_road[i] == 1 ? "layout_player_bigline-01" : "layout_banker_bigline-01";
PS: I am very sorry if i couldn't explain it very well because english is not my native so i provided a picture. I am very sorry.
EDIT: I did it like this but the problem is that it's not getting what i want all the red which is 2 is the only appearing on the board
for (int i = 1; i < obj.dataToParse.Length - 1; i += 3)
{
char indivisualChar = obj.dataToParse[i];
int j = 0;
if(j < rh.Const._HISTORY_COUNT_ * rh.Const._HISTORY_HEIGHT_)
{
//lets increment it
j++;
//instantiate the sprite
GameObject o = Instantiate(prefab_big_road) as GameObject;
o.transform.SetParent(pos_big_road);
o.transform.localScale = Vector3.one; //(1,1,1)
int x = j % rh.Const._HISTORY_COUNT_;
int y = j / rh.Const._HISTORY_COUNT_;
float xl = 9.0f;
float yl = -8.0f;
o.transform.localPosition = new Vector3(x * xl, y * yl, 0f);
//o.GetComponent<UISprite>().spriteName = indivisualChar == 1 ? "layout_player_bigline-01" : "layout_banker_bigline-01";
if (indivisualChar == 1)
{
o.GetComponent<UISprite>().spriteName = "layout_player_bigline-01";
NGUITools.SetActive(o, true);
}
else
{
o.GetComponent<UISprite>().spriteName = "layout_banker_bigline-01";
NGUITools.SetActive(o, true);
}
}
//Debug.Log(indivisualChar);
}
EDITED: More information.
It just give me this
All of the sprites are in one place and the second problem of that is all the prefab that is cloned is always red (2)

I solve the issue about all game prefab that are instantiated is all red so what at i did here was like this.
char indivisualChar = obj.dataToParse[i];
int j = 0;
if (j < rh.Const._HISTORY_COUNT_ * rh.Const._HISTORY_HEIGHT_)
{
//lets increment it
j++;
//instantiate the sprite
GameObject o = Instantiate(prefab_big_road) as GameObject;
o.transform.SetParent(pos_big_road);
o.transform.localScale = Vector3.one; //(1,1,1)
int x = j % rh.Const._HISTORY_COUNT_;
int y = j / rh.Const._HISTORY_COUNT_;
float xl = 2.0f;
float yl = -22.0f;
o.transform.localPosition = new Vector3(x * xl, y * yl, 0f);
o.GetComponent<UISprite>().spriteName = indivisualChar == '1' ? "layout_player_bigline-01" : "layout_banker_bigline-01";
NGUITools.SetActive(o, true);
}
Thanks.

Related

Unity Trying to make a chess game but error messages really annoys me

Codes below:
using System;
using UnityEngine;
using UnityEngine.Serialization;
public class Chessboard : MonoBehaviour
{
[Header("Art")]
[SerializeField] private Material tileMaterial;
//Logic
private const int TILE_COUNT_X = 8;
private const int TILE_COUNT_Y = 8;
private GameObject[,] tiles;
private Camera currentCamera;
private Vector2Int currentHover = -Vector2Int.one;
private void Awake()
{
GenerateAllTiles(1, TILE_COUNT_X, TILE_COUNT_Y);
}
private void Update()
{
if (!currentCamera)
{
currentCamera = Camera.current;
return;
}
RaycastHit info;
Ray ray = currentCamera.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out info, 100, LayerMask.GetMask("Tile")))
{
// get the indexes of Tile i've hit
Vector2Int hitPosition = LookupTileIndex(info.transform.gameObject);
//If we are hovering a tile after not hovering any
if (currentHover == -Vector2Int.one)
{
tiles[hitPosition.x, hitPosition.y].layer = LayerMask.NameToLayer("Hover");
currentHover = hitPosition;
}
//If we were already hovering a tile, change the previous one
else if (currentHover != hitPosition)
{
tiles[currentHover.x, currentHover.y].layer = LayerMask.NameToLayer("Tile");
currentHover = hitPosition;
tiles[hitPosition.x, hitPosition.y].layer = LayerMask.NameToLayer("Hover");
}
}
else
{
if (currentHover != -Vector2Int.one)
{
tiles[currentHover.x, currentHover.y].layer = LayerMask.NameToLayer("Tile");
currentHover = -Vector2Int.one;
}
}
}
//Generate the board (useful)
private void GenerateAllTiles(float tileSize, int tileCountX, int tileCountY)
{
tiles = new GameObject[tileCountX, tileCountY];
for (int x = 0; x < tileCountX; x++)
for (int y = 0; y < tileCountY; y++)
tiles[x, y] = generate1tile(tileSize, x, y);
}
private GameObject generate1tile(float tileSize, int x, int y)
{
GameObject tileObject = new GameObject(string.Format("Tile X:{0}, Y:{1}", x, y));
tileObject.transform.parent = transform;
Mesh mesh = new Mesh();
tileObject.AddComponent<MeshFilter>().mesh = mesh;
tileObject.AddComponent<MeshRenderer>().material = tileMaterial;
Vector3[] vertices = new Vector3[4];
vertices[0] = new Vector3(x * tileSize, 0, y * tileSize);
vertices[1] = new Vector3(x * tileSize, 0, (y + 1) * tileSize);
vertices[2] = new Vector3((x + 1) * tileSize, 0, y * tileSize);
vertices[3] = new Vector3((x + 1) * tileSize, 0, (y + 1) * tileSize);
int[] tris = new int[]{0, 2, 1, 1, 2, 3};
mesh.vertices = vertices;
mesh.triangles = tris;
mesh.RecalculateNormals();
tileObject.layer = LayerMask.NameToLayer("Tile");
tileObject.AddComponent<BoxCollider>();
return tileObject;
}
private Vector2Int LookupTileIndex(GameObject hitInfo)
{
for(int x = 0; x < TILE_COUNT_X; x++)
for(int y = 0; y < TILE_COUNT_Y; y++)
if(tiles[x, y] == hitInfo)
return new Vector2Int(x, y);
return new Vector2Int(-1, -1); //Invalid
}
}
Error Message:
A game object can only be in one layer. The layer needs to be in the range [0...31]
UnityEngine.StackTraceUtility:ExtractStackTrace ()
Chessboard:generate1tile (single,int,int) (at Assets/scripts/Chessboard.cs:93)
Chessboard:GenerateAllTiles (single,int,int) (at Assets/scripts/Chessboard.cs:68)
Chessboard:Awake () (at Assets/scripts/Chessboard.cs:20)
I just get into Unity, so I might be missed some parts of it.
I tired using AI to config my problem, but it doesn't work. I am expecting i put my mouse on a tile, the tile change its color.
Here is the link to the tutorial I watched: https://www.youtube.com/watch?v=FtGy7J8XD90&list=PLmcbjnHce7SeAUFouc3X9zqXxiPbCz8Zp&index=2&ab_channel=Epitome

Out of Memory Exception in Unity generating Cube subdividing each face of the cube 4 times

I want to generate a cube and subdivide each face of the cube 4 times, in this way a cube of 6 faces will have 24 faces. I'm am trying doing this in Unity3d but its giving me Out of Memory Exception when I try executing it. I think it may be due to some bad efficient code, but I think I'm missing something because I'm trying to see if I can make it more efficient and I don't really see nothing very bad.
Here is my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class sphereMesh : MonoBehaviour
{
// Start is called before the first frame update
Mesh mesh;
List<Vector3> vertices = new List<Vector3>();
List<int> triangulos = new List<int>();
public int numeroSubdivisiones = 1;
static Vector3[] faceCubes = {
new Vector3(1, 1, 1), //0
new Vector3(-1, 1, 1), //1
new Vector3(-1, -1, 1), //2
new Vector3(1, -1, 1), //3
new Vector3(-1, 1, -1), //4
new Vector3(1, 1, -1), //5
new Vector3(1, -1, -1), //6
new Vector3(-1, -1, -1) //7
};
static int[][] facetriangulos = {
// Cara trasera
new int[]{0,1,2,3},
// Cara derecha
new int[]{5,0,3,6},
// Cara frontal
new int[]{4,5,6,7},
// Cara izquierda
new int[]{1,4,7,2},
// Cara arriba
new int[]{5,4,1,0},
// Cara abajo
new int[]{3,2,7,6},
};
void MakeFace(int dir)
{
vertices.AddRange(faceVertices(dir));
int vCount = vertices.Count;
triangulos.Add(vCount - 4);
triangulos.Add(vCount - 4 + 1);
triangulos.Add(vCount - 4 + 2);
triangulos.Add(vCount - 4);
triangulos.Add(vCount - 4 + 2);
triangulos.Add(vCount - 4 + 3);
}
void MakeCube()
{
vertices = new List<Vector3>();
triangulos = new List<int>();
for (int i = 0; i <6; i++)
{
MakeFace(i);
}
}
// Funcion que crea una cara de vertices
public static Vector3[] faceVertices(int dir)
{
Vector3[] fv = new Vector3[4];
for (int i = 0; i < fv.Length; i++)
{
// La direccion y la posicion del array
fv[i] = faceCubes[facetriangulos[dir][i]];
}
return fv;
}
// Modifica la lista de vertices y la actualiza
// De forma que un cuadrado da lugar a otros cuatro cuadrados
// T --> Top, D --> Down, L --> Left, R --> Right
// v --> Vertice
void subdividirCuadrado(Vector3 vTL, Vector3 vTR, Vector3 vDL, Vector3 vDR)
{
Vector3 vT = vT = Vector3.Lerp(vTR, vTL, 0.5f);
Vector3 vD = vD = Vector3.Lerp(vDR, vDL, 0.5f);
Vector3 vR = vR = Vector3.Lerp(vTR,vDR, 0.5f);
Vector3 vL = vL = Vector3.Lerp(vTL,vDL, 0.5f);
Vector3 vCenter = Vector3.Lerp(vR, vL, 0.5f);
int size = vertices.Count;
vertices.AddRange(new List<Vector3> {vT, vD, vL, vR, vTL, vTR, vDL, vDR, vCenter});
int tT = size + 0;
int tD = size + 1;
int tL = size + 2;
int tR = size + 3;
int tTL = size + 4;
int tTR = size + 5;
int tDL = size + 6;
int tDR = size + 7;
int tCenter = size + 8;
triangulos.AddRange(new List<int> {tL, tTL, tT});
triangulos.AddRange(new List<int> {tL, tT, tCenter});
triangulos.AddRange(new List<int> {tCenter, tT, tTR});
triangulos.AddRange(new List<int> {tCenter, tTR, tR});
triangulos.AddRange(new List<int> {tDL, tL, tCenter});
triangulos.AddRange(new List<int> {tDL, tCenter, tD});
triangulos.AddRange(new List<int> {tD, tCenter, tR});
triangulos.AddRange(new List<int> {tD, tR, tDR});
}
void subCubo()
{
for(int j = 0; j < numeroSubdivisiones; j++)
{
Debug.Log("AAAAA" + vertices.Count);
for (int i = 0; i < vertices.Count; i += 4)
{
subdividirCuadrado(vertices[i], vertices[i+1], vertices[i+2], vertices[i+3]);
/*
mesh.vertices[i][0] = mesh.vertices[i][0]/i;
mesh.vertices[i][1] = mesh.vertices[i][1]/i;
mesh.vertices[i][2] = mesh.vertices[i][2]/i;
mesh.vertices[i+1][0] = mesh.vertices[i+1][0]/i+1;
mesh.vertices[i+1][1] = mesh.vertices[i+1][1]/i+1;
mesh.vertices[i+1][2] = mesh.vertices[i+1][2]/i+1;
mesh.vertices[i+2][0] = mesh.vertices[i+2][0]/i+2;
mesh.vertices[i+2][1] = mesh.vertices[i+2][1]/i+2;
mesh.vertices[i+2][2] = mesh.vertices[i+2][2]/i+2;
mesh.vertices[i+3][0] = mesh.vertices[i+3][0]/i+3;
mesh.vertices[i+3][1] = mesh.vertices[i+3][1]/i+3;
mesh.vertices[i+3][2] = mesh.vertices[i+3][2]/i+3;
*/
}
}
}
void Awake()
{
mesh = GetComponent<MeshFilter>().mesh;
}
void Start()
{
MakeCube();
subCubo();
UpdateMesh();
}
// Update is called once per frame
void UpdateMesh()
{
mesh.Clear();
mesh.vertices = vertices.ToArray();
mesh.triangles = triangulos.ToArray();
mesh.RecalculateNormals();
}
}
I think this is infinity loop:
for (int i = 0; i < vertices.Count; i += 4)
{
subdividirCuadrado(vertices[i], vertices[i+1], vertices[i+2], vertices[i+3]);
You keep going through the loop until i is bigger than count of items in vertices.
During each iteration i is increased by 4, but there are 9 new items in vertices:
vertices.AddRange(new List<Vector3> {vT, vD, vL, vR, vTL, vTR, vDL, vDR, vCenter});
Therefore i is never bigger than vertices.count and thus the loop is infinite.
vertices.AddRange(new List { vT, vD, vL, vR, vTL, vTR, vDL, vDR, vCenter });
This line inside subdividirCuadrado()
You add 9 NEW vertices to the vertices list but its inside
for (int i = 0; i < vertices.Count; i += 4).
Result is the count keep going up and up and up. To infinity :)

Procedural world generation can't handle big maps

so, I'm making a terraria-like game in unity 2019 on windws 10 using c# which has procedurally generated tilemaps and i have this script attached to a grid:
using UnityEngine;
using AccidentalNoise;
using System.Collections.Generic;
using UnityEngine.Tilemaps;
using System;
public class CompileTerrain : MonoBehaviour
{
public TileBase dirtTile;
public TileBase grassTile;
public TileBase stoneTile;
public List<GameObject> fractalLayers = new List<GameObject>();
public Tilemap grid;
public int width;
public int height;
public float seed;
public int caveSmoothness = 2;
void Start()
{
grid.ClearAllTiles();
int touchCount = 0;
Vector3Int newPos;
double nx, ny;
ModuleBase combinedTerrain = CavesAndMountains((uint)seed);
List<Vector3Int> terrainCoords = new List<Vector3Int>();
SMappingRanges ranges = new SMappingRanges();
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
nx = (ranges.mapx0 + ((double)x / (double)width) * (ranges.mapx1 - ranges.mapx0)) * 3;
ny = (ranges.mapy0 + ((double)y / (double)height) * (ranges.mapy1 - ranges.mapy0)) * 3;
if (combinedTerrain.Get(nx, ny) > 0f)
{
terrainCoords.Add(new Vector3Int(x, height - y, 0));
}
}
}
List<Tuple<int, int>> neighbors = new List<Tuple<int, int>>() {Tuple.Create(1, 1), Tuple.Create(-1, -1),
Tuple.Create(0, 1), Tuple.Create(1, 0),
Tuple.Create(0, -1), Tuple.Create(-1, 0),
Tuple.Create(-1, 1), Tuple.Create(1, -1)};
for (int index = 0; index < terrainCoords.Count; index++)
{
if (index == terrainCoords.Count)
{
break;
}
touchCount = 0;
for (int posAdd = 0; posAdd < neighbors.Count; posAdd++)
{
newPos = new Vector3Int(terrainCoords[index].x + neighbors[posAdd].Item1, terrainCoords[index].y + neighbors[posAdd].Item2, 0);
touchCount += terrainCoords.Contains(newPos) ? 1 : 0;
}
if (touchCount < 2)
{
terrainCoords.Remove(terrainCoords[index]);
}
}
for (int j = 0; j < caveSmoothness; j++)
{
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
if (!terrainCoords.Contains(new Vector3Int(x, y, 0)))
{
touchCount = 0;
for (int posAdd = 0; posAdd < neighbors.Count; posAdd++)
{
newPos = new Vector3Int(x + neighbors[posAdd].Item1, y + neighbors[posAdd].Item2, 0);
touchCount += terrainCoords.Contains(newPos) ? 1 : -1;
}
if (touchCount > 1)
{
terrainCoords.Add(new Vector3Int(x, y, 0));
}
}
}
}
}
foreach (Vector3Int blck in terrainCoords)
{
grid.SetTile(blck, stoneTile);
}
terrainCoords.Sort((x, y) => x.x == y.x ? x.y.CompareTo(y.y) : x.x.CompareTo(y.x));
terrainCoords.Reverse();
TileBase selectedTile;
int depth = 0;
int lastx = 0;
int lasty = terrainCoords[0].y + 1;
foreach (Vector3Int blck in terrainCoords)
{
depth = blck.x != lastx ? 0 : depth;
lasty = blck.x != lastx ? blck.y + 1 : lasty;
selectedTile = depth < 4 ? grassTile : stoneTile;
selectedTile = 3 < depth && depth < 30 ? dirtTile : selectedTile;
grid.SetTile(blck, selectedTile);
lastx = blck.x;
depth += lasty - blck.y;
lasty = blck.y;
}
int layerNum = 1;
List<Vector3Int> posList = new List<Vector3Int>();
foreach (GameObject layer in fractalLayers)
{
GetPerlinLayer component = layer.GetComponent<GetPerlinLayer>();
for (int k = 0; k < component.populateCount; k++)
{
layerNum++;
foreach (Vector3Int pos in component.GetFractalCoords(width, height, (uint)(seed * layerNum)))
if (grid.GetTile(pos) != null && grid.GetTile(pos) != grassTile)
{
grid.SetTile(pos, component.defaultTile);
}
}
}
}
public static ModuleBase CavesAndMountains(uint seed)
{
AccidentalNoise.Gradient ground_gradient = new AccidentalNoise.Gradient(0, 0, 0, 1);
// lowlands
Fractal lowland_shape_fractal = new Fractal(FractalType.BILLOW, BasisTypes.GRADIENT, InterpTypes.QUINTIC, 2, 0.25, seed);
AutoCorrect lowland_autocorrect = new AutoCorrect(lowland_shape_fractal, 0, 1);
ScaleOffset lowland_scale = new ScaleOffset(0.125, -0.45, lowland_autocorrect);
ScaleDomain lowland_y_scale = new ScaleDomain(lowland_scale, null, 0);
TranslatedDomain lowland_terrain = new TranslatedDomain(ground_gradient, null, lowland_y_scale);
// highlands
Fractal highland_shape_fractal = new Fractal(FractalType.FBM, BasisTypes.GRADIENT, InterpTypes.QUINTIC, 4, 2, seed);
AutoCorrect highland_autocorrect = new AutoCorrect(highland_shape_fractal, -1, 1);
ScaleOffset highland_scale = new ScaleOffset(0.25, 0, highland_autocorrect);
ScaleDomain highland_y_scale = new ScaleDomain(highland_scale, null, 0);
TranslatedDomain highland_terrain = new TranslatedDomain(ground_gradient, null, highland_y_scale);
// mountains
Fractal mountain_shape_fractal = new Fractal(FractalType.RIDGEDMULTI, BasisTypes.GRADIENT, InterpTypes.QUINTIC, 8, 1, seed);
AutoCorrect mountain_autocorrect = new AutoCorrect(mountain_shape_fractal, -1, 1);
ScaleOffset mountain_scale = new ScaleOffset(0.3, 0.15, mountain_autocorrect);
ScaleDomain mountain_y_scale = new ScaleDomain(mountain_scale, null, 0.15);
TranslatedDomain mountain_terrain = new TranslatedDomain(ground_gradient, null, mountain_y_scale);
// terrain
Fractal terrain_type_fractal = new Fractal(FractalType.FBM, BasisTypes.GRADIENT, InterpTypes.QUINTIC, 3, 0.125, seed);
AutoCorrect terrain_autocorrect = new AutoCorrect(terrain_type_fractal, 0, 1);
ScaleDomain terrain_type_y_scale = new ScaleDomain(terrain_autocorrect, null, 0);
AccidentalNoise.Cache terrain_type_cache = new AccidentalNoise.Cache(terrain_type_y_scale);
Select highland_mountain_select = new Select(terrain_type_cache, highland_terrain, mountain_terrain, 0.55, 0.2);
Select highland_lowland_select = new Select(terrain_type_cache, lowland_terrain, highland_mountain_select, 0.25, 0.15);
AccidentalNoise.Cache highland_lowland_select_cache = new AccidentalNoise.Cache(highland_lowland_select);
Select ground_select = new Select(highland_lowland_select_cache, 0, 1, 0.5, null);
// caves
Fractal cave_shape = new Fractal(FractalType.RIDGEDMULTI, BasisTypes.GRADIENT, InterpTypes.QUINTIC, 1, 4, seed);
Bias cave_attenuate_bias = new Bias(highland_lowland_select_cache, 0.65);
Combiner cave_shape_attenuate = new Combiner(CombinerTypes.MULT, cave_shape, cave_attenuate_bias);
Fractal cave_perturb_fractal = new Fractal(FractalType.FBM, BasisTypes.GRADIENT, InterpTypes.QUINTIC, 6, 3, seed);
ScaleOffset cave_perturb_scale = new ScaleOffset(0.5, 0, cave_perturb_fractal);
TranslatedDomain cave_perturb = new TranslatedDomain(cave_shape_attenuate, cave_perturb_scale, null);
Select cave_select = new Select(cave_perturb, 1, 0, 0.75, 0);
return new Combiner(CombinerTypes.MULT, cave_select, ground_select) as ModuleBase;
}
}
which i have so graciously borrowed and modified from the fine folks at accidental noise, and i made an empty gameobject which i attached this script to:
using UnityEngine;
using AccidentalNoise;
using System.Collections.Generic;
using UnityEngine.Tilemaps;
public class GetPerlinLayer : MonoBehaviour
{
public TileBase defaultTile;
public float threshold = 0.5f;
public int populateCount = 5;
public List<Vector3Int> GetFractalCoords(int width, int height, uint seed)
{
double nx, ny;
ModuleBase combinedTerrain = new Fractal(FractalType.FBM, BasisTypes.GRADIENT, InterpTypes.QUINTIC, 6, 2, seed);
List<Vector3Int> fractalCoords = new List<Vector3Int>();
SMappingRanges ranges = new SMappingRanges();
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
nx = (ranges.mapx0 + ((double)x / (double)width) * (ranges.mapx1 - ranges.mapx0)) * 3;
ny = (ranges.mapy0 + ((double)y / (double)height) * (ranges.mapy1 - ranges.mapy0)) * 3;
if (combinedTerrain.Get(nx, ny) > threshold)
{
fractalCoords.Add(new Vector3Int(x, height - y, 0));
}
}
}
return fractalCoords;
}
}
and i attached different colored square sprites for each of those gameobjects, and saved them as a prefab. Once i had that prefab, i attached that to the fractalLayers list in my previous script to generate ores. And although it runs fine on a lower scale, I cant run it on a larger scale. And since there's no cure-all for making code run faster (aside from refactoring, which i don't know how to do), and i probably could've made parts of my code more efficient since I'm a novice, i would really like some insight from the eyes of a professional on how to make my code run better. I know i didn't explain everything about my project but its really just a bare-bones project those are the only scripts and unique parts about it, you can just infer what i did and fill in the blanks. Any help is appreciated. And if you could give me the extra push along with some information on the subject, I would love to have some videos recommended along with your insight to guide me along this process, since i am more of a visual learner. Thank you! =)
(For reference, it took me about 4 minutes to build this, with the settings shown here.)
So apparently my word generation method was fine, just the loop I was using to smoothen the terrain took too long.

Unity/C# - Change size of brush for painting terrain

I'm coding an runtime terrain editor for unity and got stuck.
At first I wanted just to paint with textrue the terrain. I found this code and it worked fine:
SCRIPT: TerrainPainter
void Paint(Vector3 point)
{
mapX = (int)(((point.x - terrainPosition.x) / terrainData.size.x) * heightmapWidth);
mapY = (int)(((point.z - terrainPosition.z) / terrainData.size.z) * heigtmapHeight);
splatmapData[mapY, mapX, 0] = element[0, 0, 0] = 0;
splatmapData[mapY, mapX, 1] = element[0, 0, 1] = 1;
terrain.terrainData.SetAlphamaps(mapX, mapY, element);
}
But now I want to paint with different sizes/thickness. I have another script, named Terrainmodifier, which I use to raise and lower the terrain. There I have this lines for raising:
SCRIPT: Terrainmodifier
public void RaiseTerrain(Terrain terrain, Vector3 location, float effectIncrement)
{
int offset = areaOfEffectSize / 2;
//--1--
Vector3 tempCoord = (location - terrain.GetPosition());
Vector3 coord;
coord = new Vector3(
(tempCoord.x / GetTerrainSize().x),
(tempCoord.y / GetTerrainSize().y),
(tempCoord.z / GetTerrainSize().z)
);
Vector3 locationInTerrain = new Vector3(coord.x * terrainHeightMapWidth, 0, coord.z * terrainHeightMapHeight);
// End --1--
// --2--
int terX = (int)locationInTerrain.x - offset;
int terZ = (int)locationInTerrain.z - offset;
// End --2--
// --3--
float[,] heights = targetTerrainData.GetHeights(terX, terZ, areaOfEffectSize, areaOfEffectSize);
for (int xx = 0; xx < areaOfEffectSize; xx++)
{
for (int yy = 0; yy < areaOfEffectSize; yy++)
{
heights[xx, yy] += (effectIncrement * Time.smoothDeltaTime);
}
}
targetTerrainData.SetHeights(terX, terZ, heights);
}
So I thought I could use this as an aid and transfer it. So I took GetAlphamaps() instead of GetHeights() and added the variable areaOfEffectSize.
SCRIPT: TerrainPainter
void Paint(Vector3 point)
{
// --1--
mapX = (int)(((point.x - terrainPosition.x) / terrainData.size.x) * heightmapWidth);
mapY = (int)(((point.z - terrainPosition.z) / terrainData.size.z) * heigtmapHeight);
// End --1--
// --2--
int terX = (int)mapX - (areaOfEffectSize / 2);
int terY = (int)mapY - (areaOfEffectSize / 2);
// End --2--
// --3--
splatmapData = terrainData.GetAlphamaps(terX, terY, areaOfEffectSize, areaOfEffectSize);
for(int xx = 0; xx < areaOfEffectSize; xx++)
{
for (int yy = 0; yy < areaOfEffectSize; yy++)
{
splatmapData[yy, xx, 1] = element[0, 0, 1] = 1;
}
}
terrain.terrainData.SetAlphamaps(terX, terY, element);
}
Hope sb can help me find my mistake. How can I change the size of my "brush"?
EDIT: I wrote comments into the code to see the transfered/related lines.
Oh guys, I did a stupid mistake. Solved this problem by passing the splatmapData into SetAlphamaps -.-
So the solution is:
[..]
for (int xx = 0; xx < areaOfEffectSize; xx++)
{
for (int yy = 0; yy < areaOfEffectSize; yy++)
{
splatmapData[yy, xx, 0] = 0;
splatmapData[yy, xx, 1] = 1;
}
}
terrain.terrainData.SetAlphamaps(terX, terY, splatmapData);

Unity custom shape generation objects in 2d

I new to Unity. I'm trying to re-write game from the site in Unity http://www.boxcar2d.com/index.html
So I found that I should work with Sprites. Now I am trying to dynamically generate an arbitrarily shaped "car". I need it to collide and interact with physics and gravity.
I tried to use Mesh but it seems like there is no way to turn Mesh into a Sprite and work with it like with physical object.
What kind of structures or approach should I use for creating those "cars" dynamically?
Here is my code so far if that somehow will be useful.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GenerateCar : MonoBehaviour {
public Material mat;
// Use this for initialization
void Start()
{
Mesh mesh = new Mesh();
Vector3[] vertices = new Vector3[6];
vertices[0] = new Vector3(0, 0);
vertices[1] = new Vector3(4, 1);
vertices[2] = new Vector3(3, -1);
vertices[3] = new Vector3(-1, -3);
vertices[4] = new Vector3(3, -6);
vertices[5] = new Vector3(0, 1);
//vertices[6] = new Vector3(width, height);
//vertices[7] = new Vector3(width, -height);
mesh.vertices = vertices;
mesh.triangles = new int[] { 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5, 0, 5, 1};
GetComponent<MeshRenderer>().material = mat;
GetComponent<MeshFilter>().mesh = mesh;
}
}
If you need to make arbitrary shapes that can't be made with just horizontally and vertically stretching sprites you make ahead of time, then sprites aren't suitable. A Mesh would be more practical.
If you can describe the shape you want to make as a polygon with a known ordered list of points, you can use the community Triangulator class to create a Mesh. There are other methods, but this is a community standby.
Whatever you use to make the Mesh, you will need to make sure there is also a PolygonCollider2D on the same object as the Mesh. You can use SetPath to create its outline using the same points as you fed into Triangulator. You will also need a Rigidbody2D to handle physics and collision for the body of the car. I've never worked with wheels but WheelJoint2D might be what you can use for the wheels.
Triangulator Usage Example
using UnityEngine;
public class PolygonTester : MonoBehaviour {
void Start () {
// Create Vector2 vertices
Vector2[] vertices2D = new Vector2[] {
new Vector2(0,0),
new Vector2(0,50),
new Vector2(50,50),
new Vector2(50,100),
new Vector2(0,100),
new Vector2(0,150),
new Vector2(150,150),
new Vector2(150,100),
new Vector2(100,100),
new Vector2(100,50),
new Vector2(150,50),
new Vector2(150,0),
};
// Use the triangulator to get indices for creating triangles
Triangulator tr = new Triangulator(vertices2D);
int[] indices = tr.Triangulate();
// Create the Vector3 vertices
Vector3[] vertices = new Vector3[vertices2D.Length];
for (int i=0; i<vertices.Length; i++) {
vertices[i] = new Vector3(vertices2D[i].x, vertices2D[i].y, 0);
}
// Create the mesh
Mesh msh = new Mesh();
msh.vertices = vertices;
msh.triangles = indices;
msh.RecalculateNormals();
msh.RecalculateBounds();
// Set up game object with mesh;
gameObject.AddComponent(typeof(MeshRenderer));
MeshFilter filter = gameObject.AddComponent(typeof(MeshFilter)) as MeshFilter;
filter.mesh = msh;
}
}
Triangulator source
using UnityEngine;
using System.Collections.Generic;
public class Triangulator
{
private List<Vector2> m_points = new List<Vector2>();
public Triangulator (Vector2[] points) {
m_points = new List<Vector2>(points);
}
public int[] Triangulate() {
List<int> indices = new List<int>();
int n = m_points.Count;
if (n < 3)
return indices.ToArray();
int[] V = new int[n];
if (Area() > 0) {
for (int v = 0; v < n; v++)
V[v] = v;
}
else {
for (int v = 0; v < n; v++)
V[v] = (n - 1) - v;
}
int nv = n;
int count = 2 * nv;
for (int m = 0, v = nv - 1; nv > 2; ) {
if ((count--) <= 0)
return indices.ToArray();
int u = v;
if (nv <= u)
u = 0;
v = u + 1;
if (nv <= v)
v = 0;
int w = v + 1;
if (nv <= w)
w = 0;
if (Snip(u, v, w, nv, V)) {
int a, b, c, s, t;
a = V[u];
b = V[v];
c = V[w];
indices.Add(a);
indices.Add(b);
indices.Add(c);
m++;
for (s = v, t = v + 1; t < nv; s++, t++)
V[s] = V[t];
nv--;
count = 2 * nv;
}
}
indices.Reverse();
return indices.ToArray();
}
private float Area () {
int n = m_points.Count;
float A = 0.0f;
for (int p = n - 1, q = 0; q < n; p = q++) {
Vector2 pval = m_points[p];
Vector2 qval = m_points[q];
A += pval.x * qval.y - qval.x * pval.y;
}
return (A * 0.5f);
}
private bool Snip (int u, int v, int w, int n, int[] V) {
int p;
Vector2 A = m_points[V[u]];
Vector2 B = m_points[V[v]];
Vector2 C = m_points[V[w]];
if (Mathf.Epsilon > (((B.x - A.x) * (C.y - A.y)) - ((B.y - A.y) * (C.x - A.x))))
return false;
for (p = 0; p < n; p++) {
if ((p == u) || (p == v) || (p == w))
continue;
Vector2 P = m_points[V[p]];
if (InsideTriangle(A, B, C, P))
return false;
}
return true;
}
private bool InsideTriangle (Vector2 A, Vector2 B, Vector2 C, Vector2 P) {
float ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy;
float cCROSSap, bCROSScp, aCROSSbp;
ax = C.x - B.x; ay = C.y - B.y;
bx = A.x - C.x; by = A.y - C.y;
cx = B.x - A.x; cy = B.y - A.y;
apx = P.x - A.x; apy = P.y - A.y;
bpx = P.x - B.x; bpy = P.y - B.y;
cpx = P.x - C.x; cpy = P.y - C.y;
aCROSSbp = ax * bpy - ay * bpx;
cCROSSap = cx * apy - cy * apx;
bCROSScp = bx * cpy - by * cpx;
return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f));
}
}

Categories