roadTopStartX = Random.Range(5, 10); // Path's x position which creation begins
roadTopStartY = Random.Range(8, 12); // Path's y position which creation begins
roadTopLength = Random.Range(4, 9); // Path's length
for (int i = 0; i < roadTopLength; i++)
{
GameObject tile = GameObject.Find("Tile" + (roadTopStartX + i) + " " + roadTopStartY); //I created grid whose tile's name Tile X Y like Tile 0 0
GameObject road = Instantiate(roadPrefab, tile.transform.position, tile.transform.rotation);
road.name = "Road"+ " " + (roadTopStartX + i) + " " + roadTopStartY;
roads.Add(road);
}
It is how i create random path on 2d grid, do you know better solution because when thinks become more complex gameobject.find becomes suffer for me
i found a more reliable solution: (thanks to derHugo)
public GameObject findTile(int x,int y)
{
GameObject findTilex = GameObject.Find("Tile" + (tileX + x) + " " +
(tileY + y));
return findTilex;
}
Example how i get neighbour tiles
public void getNeighbours()
{
if (findTile(0, 1) != null)
{
upper = findTile(0, 1);
}
if (findTile(0, -1) != null)
{
below = findTile(0, -1);
}
if (findTile(1, 0) != null)
{
right = findTile(1, 0);
}
if (findTile(-1, 0) != null)
{
left = findTile(-1, 0);
}
if (findTile(1, 1) != null)
{
rightCrossTop = findTile(1, 1);
}
if (findTile(1, -1) != null)
{
rightCrossUnder = findTile(1, -1);
}
if (findTile(-1, 1) != null)
{
leftCrossTop = findTile(-1, 1);
}
if (findTile(-1, -1) != null)
{
leftCrossBottom = findTile(-1, -1);
}
}
Related
I am using the following to download assetbundle and it works in first scene. But when in second scene, the same code doesn't work - the uwr.downloadedbytes return 0. If I restart the app and go straight to the second scene, it works. Strange things is when I go back to the first scene from second scene, the code works as well. I want to know what is going wrong, is it something to do with unload(false) in the first scene?
private IEnumerator DownloadBundles()
{
AssetBundleList = new List<string>();
m_AssetBundle = new List<AssetBundle>();
m_InstantiatedModels = new List<GameObject>();
yield return StartCoroutine(DownloadBundle(1));
}
private IEnumerator DownloadBundle(int i)
{
string platform = "Android";
string bundleURL = data.url + data.id + "/" + platform + "/" + data.id + "assetbundles" + i.ToString();
using (UnityWebRequest uwr = UnityWebRequestAssetBundle.GetAssetBundle(bundleURL, (uint)data.assetBundleVersion, 0))
{
AsyncOperation asyncOp = uwr.SendWebRequest();
while (!asyncOp.isDone)
{
if (m_ProgressText.gameObject.activeSelf)
{
m_ProgressText.text = "Loading " + (i == 1 ? "" : "More ") + "Models... " + ((int)(asyncOp.progress * 100)).ToString() + "%";
}
yield return null;
}
if (uwr.error != null)
{
throw new UnityException("AssetBundle DownloadHandler had an error: " + uwr.error);
}
else
{
Debug.Log(uwr.downloadedBytes.ToString());
AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(uwr);
string[] assetBundleList1 = bundle.GetAllAssetNames();
assetBundleDownloaded.Add(i);
object[] golist = bundle.LoadAllAssets();
for (int k = 0; k < golist.Length; k++)
{
GameObject go = Instantiate(golist[k] as GameObject, Vector3.zero, Quaternion.identity);
go.SetActive(false);
m_InstantiatedModels.Add(go);
}
m_AssetBundle.Add(bundle);
yield return null;
}
}
}
So in my quest to make a game like the very popular zigzag game, I am stuck at randomly generating platforms. The platforms generate randomly in X,-X,Z,-Z directions. I have written my code where it generates the platforms. I might have taken a very long approach (alternative approaches if any)
void Start ()
{
lastPos = platform.transform.position;
size = platform.transform.localScale.x;
InvokeRepeating("SpawnXZ",1f,0.2f);
}
void SpawnX()
{
Vector3 pos = lastPos;
pos.x += size;
lastPos = pos;
Instantiate(platform, pos, Quaternion.identity);
}
void SpawnZ()
{
Vector3 pos = lastPos;
pos.z += size;
lastPos = pos;
Instantiate(platform, pos, Quaternion.identity);
}
void SpawnNegX()
{
Vector3 pos = lastPos;
pos.x -= size;
lastPos = pos;
Instantiate(platform, pos, Quaternion.identity);
}
void SpawnNegZ()
{
Vector3 pos = lastPos;
pos.z -= size;
lastPos = pos;
Instantiate(platform, pos, Quaternion.identity);
}
void SpawnXZ()
{
int rand = Random.Range(0, 6);
if (rand < 3)
{
SpawnX();
}
else if(rand >= 3)
{
SpawnZ();
}
if(--counter == 0) { CancelInvoke("SpawnXZ"); };
if(counter == 0)
{
counter = 25;
int r = Random.Range(0,2);
if(r == 0)
{
InvokeRepeating("SpawnNegXZ",0f,0.2f);
}
else
{
InvokeRepeating("SpawnXNegZ",0f,0.2f);
}
}
}
void SpawnNegXZ()
{
int rand = Random.Range(0, 6);
if (rand < 3)
{
SpawnNegX();
}
else if(rand >= 3)
{
SpawnZ();
}
if(--counter == 0) { CancelInvoke("SpawnNegXZ"); };
if(counter == 0)
{
counter = 25;
int r = Random.Range(0,2);
if(r == 0)
{
InvokeRepeating("SpawnXZ",0f,0.2f);
}
else
{
InvokeRepeating("SpawnNegXNegZ",0f,0.2f);
}
}
}
void SpawnXNegZ()
{
int rand = Random.Range(0, 6);
if (rand < 3)
{
SpawnX();
}
else if(rand >= 3)
{
SpawnNegZ();
}
if(--counter == 0) { CancelInvoke("SpawnXNegZ"); };
if(counter == 0)
{
counter = 25;
int r = Random.Range(0,2);
if(r == 0)
{
InvokeRepeating("SpawnXZ",0f,0.2f);
}
else
{
InvokeRepeating("SpawnNegXNegZ",0f,0.2f);
}
}
}
void SpawnNegXNegZ()
{
int rand = Random.Range(0, 6);
if (rand < 3)
{
SpawnNegX();
}
else if(rand >= 3)
{
SpawnNegZ();
}
if(--counter == 0) { CancelInvoke("SpawnNegXNegZ"); };
if(counter == 0)
{
counter = 25;
int r = Random.Range(0,2);
if(r == 0)
{
InvokeRepeating("SpawnNegXZ",0f,0.2f);
}
else
{
InvokeRepeating("SpawnXNegZ",0f,0.2f);
}
}
}
I have clubbed xz, -xz , x -z and -x -z. I call platform spawning in X and Z direction first, then switching to -XZ or x -Z and so on. But there are 2 main issues.
PS : those small black squares are nothing but diamonds (ignore them).
They either form a 2X2 block or overlap each other.
How do I avoid these? or is there a simpler way of generating platforms that I am missing.
You need an array to indicate which tiles are occupied:
bool[,] tiles = new bool[N,N];
or a dictionary
Dictionary<XZ, bool> tiles = new Dictionary<XZ, bool>();
public struct XZ { public int X; public int Z; }
whenever a tile is spawned check the value to see if it is possible to spawn or not:
void SpawnXZ()
{
int x = (int) (lastpos.x / size);
int z = (int) (lastpos.z / size);
int rand = Random.Range(0, 6);
if (rand < 3 && !tiles[x + 1, z])
{
SpawnX();
tiles[x + 1, z] = true;
}
else if(rand >= 3 && && !tiles[x, z + 1])
{
SpawnZ();
tiles[x, z + 1] = true;
}
else
{
...
}
Note that this code will not work, and it's just a starting point for you to develop it further.
When I uncomment the line "ConnectMaze(maze)" in the Start() method, Unity instantly stops responding when I hit play. None of the Debug.Log statements show up in the console. If I comment out that specific line, I am able to see the Debug.Log statements in the console and Unity does respond. I am thinking that there could be an infinite loop in the ConnectMaze while loop, however wouldn't the Debug.Log statements prior to the loop still show up in the console? Below is the code that is causing the issue.
using UnityEngine;
using System.Collections;
public class MazeBase : MonoBehaviour {
public const int mazeLength = 11;
private int[,] maze = new int[mazeLength,mazeLength];
private int numWalls;
// Use this for initialization
void Start () {
Debug.Log ("Initialize Start");
InitializeMaze (maze);
Debug.Log ("Initialize End");
Debug.Log ("Connectivity Start");
ConnectMaze (maze);
Debug.Log ("Connectivity End");
MazeGenerator.Generate (transform,maze);
}
// Update is called once per frame
void Update () {
}
private void CreateMazeBlock(){
Vector3 mousePos = Input.mousePosition;
mousePos.z = 10;
Vector3 cameraPos = Camera.main.ScreenToWorldPoint (mousePos);
int cameraPosX = (int)Mathf.Round (cameraPos.x);
int cameraPosZ = (int)Mathf.Round (cameraPos.z);
if (maze [cameraPosX, cameraPosZ] != 1) {
maze [cameraPosX, cameraPosZ] = 1;
MazeGenerator.GenerateSingleBlock (transform, cameraPosX, cameraPosZ);
}
}
private void DeleteMazeBlock(){
Vector3 mousePos = Input.mousePosition;
mousePos.z = 10;
Vector3 cameraPos = Camera.main.ScreenToWorldPoint (mousePos);
int cameraPosX = (int)Mathf.Round (cameraPos.x);
int cameraPosZ = (int)Mathf.Round (cameraPos.z);
if (maze [cameraPosX, cameraPosZ] == 1) {
maze [cameraPosX, cameraPosZ] = 0;
MazeGenerator.DeleteSingleBlock (cameraPosX, cameraPosZ);
}
}
private void InitializeMaze(int[,] maze){
for (int i = 0; i < mazeLength; i++) {
for (int j = 0; j < mazeLength; j++) {
if (i == 0 || i == mazeLength - 1 || j == 0 || j == mazeLength - 1) {
maze [i, j] = -1;
numWalls++;
} else if (Random.Range (0, 100) < 50) {
bool createWall = true;
//Following if statements prevent a 2x2 square of walls
if (IsWall (maze, i - 1, j - 1) && IsWall (maze, i - 1, j) && IsWall (maze, i, j - 1)) {
createWall = false;
}else if (IsWall (maze, i - 1, j + 1) && IsWall (maze, i - 1, j) && IsWall (maze, i, j + 1)) {
createWall = false;
}else if (IsWall (maze, i + 1, j - 1) && IsWall (maze, i + 1, j) && IsWall (maze, i, j - 1)) {
createWall = false;
}else if (IsWall (maze, i + 1, j + 1) && IsWall (maze, i + 1, j) && IsWall (maze, i, j + 1)) {
createWall = false;
}
if(createWall){
maze [i, j] = -1;
numWalls++;
}
}
}
}
}
private bool IsWall(int[,] maze, int i, int j){
return maze [i, j] < 0;
}
private void ConnectMaze(int[,] maze){
Debug.Log ("GetNextTile Start");
ArrayList startTile = GetNextTile (maze,0);
Debug.Log ("GetNextTile End");
int startX = (int)startTile[0];
int startZ = (int)startTile[1];
int numberOfFloods = 1;
Debug.Log ("Flood Fill 1 Start");
int numFound = FloodFill(maze,startX,startZ,numberOfFloods);
Debug.Log ("Flood Fill 1 End");
while (numFound != (mazeLength * mazeLength) - numWalls) {
ArrayList nextWallTile = GetNextTile (maze, 1);
int wallX = (int)nextWallTile[0];
int wallZ = (int)nextWallTile[1];
maze [wallX, wallZ] = 0;
numWalls--;
numberOfFloods++;
int numFound2 = FloodFill(maze,startX,startZ,numberOfFloods);
if(numFound2 == (mazeLength*mazeLength)-numWalls){
break;
}
if (numFound2 - numFound > 1) {
numFound = numFound2;
} else {
maze [wallX, wallZ] = 2;
numWalls++;
}
int temp = (mazeLength * mazeLength) - numWalls;
Debug.Log ("Number of empty tiles: " + temp);
Debug.Log ("Number of tiles found: " + numFound);
}
}
private int FloodFill(int[,] maze, int x, int z,int value){
int numEmptyTilesFound = 0;
if (x < 0 || z < 0 || x >= mazeLength || z >= mazeLength) {
return 0;
}
if (maze [x, z] == -1 || maze [x, z] == value) {
return 0;
}
maze [x, z] = value;
numEmptyTilesFound++;
numEmptyTilesFound += FloodFill (maze, x - 1, z, value);
numEmptyTilesFound += FloodFill (maze, x + 1, z, value);
numEmptyTilesFound += FloodFill (maze, x, z - 1, value);
numEmptyTilesFound += FloodFill (maze, x, z + 1, value);
return numEmptyTilesFound;
}
private ArrayList GetNextTile(int[,] maze,int value){
int startX = 0;
int startZ = 0;
bool search = true;
for (int i = 0; i < mazeLength; i++) {
for (int j = 0; j < mazeLength; j++) {
if (maze [i, j] == value) {
startX = i;
startZ = j;
search = false;
}
if(!search){
break;
}
}
if(!search){
break;
}
}
ArrayList startingPoint = new ArrayList ();
startingPoint.Add (startX);
startingPoint.Add (startZ);
return startingPoint;
}
}
I am learning about Kinect and I have a problem. I want to write to a text file the coordinate of joints of the skeleton but i don't know how to do that. Can anybody help me ?
If you are using the SDK:
using System.IO;
StreamWriter writer = new StreamWriter(#path);
int frames = 0;
...
void AllFramesReady(object sender, AllFramesReadyEventArgs e)
{
frames++;
using (SkeletonFrame sFrame = e.OpenSkeletonFrameData())
{
if (sFrame == null)
return;
skeletonFrame.CopySkeletonDataTo(skeletons);
Skeleton skeleton = (from s in skeletons
where s.TrackingState == SkeletonTrackingState.Tracked
select s);
if (skeleton == null)
return;
if (skeleton.TrackingState == SkeletonTrackingState.Tracked)
{
writer.Write("{0} {1}#", frames, timestamp);//I dont know how you want to do this
foreach (Joint joint in skeleton.Joints)
{
writer.Write(joint.Position.X + "," + joint.Position.Y + "," joint.Position.Z + ",");
}
writer.Write(Environment.NewLine);
}
}
}
This takes the joints of a detected skeleton, and writes them to a file without specifying their relative joint, but it is in the default order of the joint types. Note this is the distance from the kinect sensor.
Thank you, but it has one problem with 'skeletons'in this line:
Skeleton skeleton = (from s in skeletons where s.TrackingState == SkeletonTrackingState.Tracked select s);
System.IO.FileStream fs = new System.IO.FileStream(#"F:\Kinect Install\SkeletonBasics-WPF\Coordinates.txt", FileMode.Append, FileAccess.Write, FileShare.None);
int frame = 0;
Skeleton[] skeletons = new Skeleton[0];
public void AllFramesReady(object sender, AllFramesReadyEventArgs e)
{
StreamWriter sw = new StreamWriter(fs);
frame++;
using (SkeletonFrame sFrame = e.OpenSkeletonFrame())
{
if (sFrame == null) return;
sFrame.CopySkeletonDataTo(skeletons);
Skeleton skeleton = (from s in skeletons where s.TrackingState == SkeletonTrackingState.Tracked select s);
if (skeleton == null)
return;
if (skeleton.TrackingState == SkeletonTrackingState.Tracked)
{
foreach (Joint joint in skeleton.Joints)
{
sw.WriteLine(joint.Position.X + "," + joint.Position.Y + "," + joint.Position.Z + ",");
}
//writer.Write(Environment.NewLine);
sw.Flush();
sw.Close();
}
}
}
I'm creating my first non-console game in Visual C#.
I have a player which is a picturebox, and obstacles which are also pictureboxes.
Now when I create an obstacle (picturebox) at a random position, I would like to check if it already touches an other obstacle.
Here's what I have now:
Picturebox obstacles = new Picturebox[20];
for (int i = 0; i < obstacles.Length; i++)
{
DateTime date = DateTime.Now;
Random randomNumber = new Random(date.Second * (date.Minute / 2) ^ 2 + date.Hour * 123 + (i ^ 9 + i / 2));
obstacles[i] = new PictureBox();
obstacles[i].Image = Properties.Resources.es;
obstacles[i].Size = new Size(25, 50);
obstacles[i].Location = new Point(randomNumber.Next(640 - obstacles[i].Image.Width), randomNumber.Next(topBar.Height, 480 - obstacles[i].Image.Height));
if (IsTouching(obstacles[i], player))
{
i--;
}
else
{
bool tmp = true;
for (int j = 0; j < obstacles.Length; j++)
{
if (obstacles[j] != null && j != i)
{
if (IsTouching(obstacles[j], obstacles[i]))
{
tmp = false;
break;
}
}
}
if (tmp)
{
Controls.Add(obstacles[i]);
}
else
{
i--;
}
}
}
So that's my way, but I know it's not really effective, so any better ideas, cause it takes a while (~5 seconds) to create those obstacles.
And here's my IsTouching method, which also kinda sucks, anyone have better ideas?
private bool IsTouching(PictureBox obj1, PictureBox obj2)
{
Point[] obj1Points = new Point[(obj1.Width * obj1.Height) - ((obj1.Width - 2) * (obj1.Height - 2))];
int count = 0;
for (int x = obj1.Left + 1; x < obj1.Left + obj1.Width - 1; x++)
{
obj1Points[count] = new Point(x, obj1.Top);
obj1Points[count + 1] = new Point(x, obj1.Top + obj1.Height);
count += 2;
}
for (int y = obj1.Top; y < obj1.Top + obj1.Height; y++)
{
obj1Points[count] = new Point(obj1.Left, y);
obj1Points[count + 1] = new Point(obj1.Left + obj1.Width, y);
count += 2;
}
Point[] obj2Points = new Point[(obj2.Width * obj2.Height) - ((obj2.Width - 2) * (obj2.Height - 2))];
count = 0;
for (int x = obj2.Left + 1; x < obj2.Left + obj2.Width - 1; x++)
{
obj2Points[count] = new Point(x, obj2.Top);
obj2Points[count + 1] = new Point(x, obj2.Top + obj2.Height);
count += 2;
}
for (int y = obj2.Top; y < obj2.Top + obj2.Height; y++)
{
obj2Points[count] = new Point(obj2.Left, y);
obj2Points[count + 1] = new Point(obj2.Left + obj2.Width, y);
count += 2;
}
for (int obj2Point = 0; obj2Point < obj2Points.Length; obj2Point++)
{
for (int obj1Point = 0; obj1Point < obj1Points.Length; obj1Point++)
{
if (obj2Points[obj2Point].X == obj1Points[obj1Point].X && obj2Points[obj2Point].Y == obj1Points[obj1Point].Y)
{
return true;
}
}
}
return false;
}
What it does: Checks if the given two parameters edges touch each other. So basically just a collision-detection, anyone have any ideas, cause I'm kinda new at this stuff?
If we assume that all the obstacles are solid (i.e. 2 obstacles touch if the other is inside the other), you can use the following method:
private bool IsTouching(PictureBox p1, PictureBox p2)
{
if (p1.Location.X + p1.Width < p2.Location.X)
return false;
if (p2.Location.X + p2.Width < p1.Location.X)
return false;
if (p1.Location.Y + p1.Height < p2.Location.Y)
return false;
if (p2.Location.Y + p2.Height < p1.Location.Y)
return false;
return true;
}
I tested your current IsTouching method and found out that it fails in some corner cases, such as in this one (it claims they are not touching although they are). My method works in these corner cases too.
There is one simple line of code for this but it might also fail for some corner pieces sometimes.
if(player1.Bounds.IntersectWith(player2.Bounds){
//Do something
}
Replace player1 with the name of the picture box and the same with player2 ofc.