Unity3d: Random.Range() Not working the way I intended - unity3d

I'm spawning objects from a list and so-far i got them to find a parent object that's already live in the scene.The problem is Random.Range() isn't working like I want. I want the listed Objects to spawn to a random parent, instead, they're spawning to the they're parent relative to the order of the list.
Ex. 0,1,2,3,4,5,6,7,8,9 = Bad
Ex. 8,3,1,4,6,3,7,9,5,2 = Good
lol
var theRange = Random.Range(obj1.Length,obj1.Length);
for(var i: int = 0; i < theRange; i++){
var obj2 : GameObject = obj1[i];
if(obj2.transform.childCount == 0){
objfromList.transform.parent = obj2.transform;
objfromList.transform.localPosition = Vector3(0,-2,0);
}
}
Deeply thankful

Following up on my comment, it sounds like you just want a shuffle function. Here is a simple Fisher-Yates shuffle:
void shuffle(int[] a){
for(int i = a.Length-1; i>=0; i--){
int j = Random.Range(0,i);
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
}
void usage(){
int[] a = {0,1,2,3,4,5}; // assumes obj1.Length = 6
shuffle(a);
for(int i = 0; i < a.Length; i++){
GameObject obj2 = obj1[a[i]];
GameObject objFromList = GetNextObject(); // dummy method grabbing next list object
objFromList.transform.parent = obj2.transform;
objFromList.transform.localPosition = Vector3(0,-2,0);
}
}
This should get you part way to what you need. If the order of obj1 isn't important you can shuffle it directly instead of using a secondary array like a in my example.

Related

Holes in Mesh only showing from one side

For a sailing game I'm working on, I've added functionality to programmatically create damage holes in a mesh (e.g. cannonball holes in a sail). This is largely based on the method here (link to the example code here)
private void MessWithMesh() {
filter = this.transform.parent.gameObject.GetComponent<MeshFilter>();
mesh = filter.mesh;
filter.mesh = GenerateMeshWithHoles();
}
private IEnumerator GenerateTrisWithVertex() {
// Destroying the sail won't work until this has finished, but it only takes a second or two so I don't think anybody will notice.
trisWithVertex = new List<int>[origvertices.Length];
for (int i = 0; i <origvertices.Length; ++i)
{
trisWithVertex[i] = ArrayHelper.IndexOf(origtriangles, i);
yield return null;
}
yield return null;
}
Mesh GenerateMeshWithHoles()
{
float damageRadius = 1f;
Transform parentTransform = this.transform.parent.transform;
Hole[] holes = this.GetComponentsInChildren<Hole>();
foreach (Hole hole in holes) {
Vector3 trackPos = hole.transform.position;
float closest = float.MaxValue;
int closestIndex = -1;
int countDisabled = 0;
damageRadius = hole.diameter;
for (int i = 0; i <origvertices.Length; ++i)
{
Vector3 v = new Vector3(origvertices[i].x * parentTransform.localScale.x, origvertices[i].y * parentTransform.localScale.y, origvertices[i].z * parentTransform.localScale.z) + parentTransform.position;
Vector3 difference = v - trackPos;
if (difference.magnitude < closest)
{
closest = difference.magnitude;
closestIndex = i;
}
if (difference.magnitude < damageRadius)
{
for (int j = 0; j <trisWithVertex[i].Count; ++j)
{
int value = trisWithVertex[i][j];
int remainder = value % 3;
trianglesDisabled[value - remainder] = true;
trianglesDisabled[value - remainder + 1] = true;
trianglesDisabled[value - remainder + 2] = true;
countDisabled++;
}
}
}
// If no triangles were removed, then we'll just remove the one that was closest to the hole.
// This shouldn't really happen, but in case the hole is off by a bit from where it should have hit the mesh, we'll do this to make sure there's at least a hole.
if (countDisabled == 0 && closestIndex > -1) {
Debug.Log("Removing closest vertex: " + closestIndex);
for (int j = 0; j < trisWithVertex[closestIndex].Count; ++j)
{
int value = trisWithVertex[closestIndex][j];
int remainder = value % 3;
trianglesDisabled[value - remainder] = true;
trianglesDisabled[value - remainder + 1] = true;
trianglesDisabled[value - remainder + 2] = true;
}
}
}
triangles = ArrayHelper.RemoveAllSpecifiedIndicesFromArray(origtriangles, trianglesDisabled).ToArray();
mesh.SetTriangles(triangles, 0);
for (int i = 0; i <trianglesDisabled.Length; ++i)
trianglesDisabled[i] = false;
return mesh;
}
When a cannonball hits the sail, I add a Hole object at the location of the impact, and I call MessWithMesh. The holes are often generated correctly, but many times they're only visible from one side of the sail (it looks fully intact from the other side). It's often visible from the opposite side of the sail that the cannonball impacted (the far side, not the near side), if that's at all helpful. The ship I'm using is this free asset.
I'm not really familiar with meshes, so I don't really understand what's going on.

Traversing a game reel matrix column by column from left to right

I have a 3x5 matrix that acts as a game reel. First, I search through the game symbols that I am interested in (let's call them wild clones) and then I search through their children (to locate the game object that has the animation) and then I activate those animations.
private IEnumerator EnableWilds(float delayBetweenWildsAppear)
{
WildSymbol[] wilds = FindObjectsOfType<WildSymbol>();
GameObject[] symbols = new GameObject[wilds.Length];
for (int i = 0; i < wilds.Length; i++)
{
symbols[i] = wilds[i].gameObject;
}
for (int i = 0; i < symbols.Length; i++)
{
if ( symbols[i].name.Contains("(Clone)") )
{
int reelIndex = symbols[i].GetComponentInParent<GameReel>().ReelIndex;
int indexOnReel = symbols[i].GetComponent<WildSymbol>().IndexOnReel;
// ??
for (int j = 0; j < symbols[i].transform.childCount; j++)
{
if ( symbols[i].transform.GetChild(j).gameObject.name.Contains("MM_wild") )
{
symbols[i].transform.GetChild(j).gameObject.SetActive(true);
yield return new WaitForSeconds(delayBetweenWildsAppear);
}
}
}
}
}
I started thinking about how I can activate those wilds starting from the top left corner, and coming down the reel and moving on to the next reel and animating the wilds from top to bottom, etc...
So, I realized I need to get each symbol's reel index (i.e. column number) and index on reel (i.e. position on the reel) so I go Reel1 and then wild clone 1 and 2 and 3, and then Reel2 followed by wild clone 1 and 2 and 3, and so on...
I am trying to do this where I have put a // ?? but at this point, I am a bit lost, conceptually. I cannot figure out how to perform tghis traversal.
Could someone please help me with this?
Here is how I solved it myself, and then simplified it:
private IEnumerator DisableWilds(float delayBetweenWildsDisappear)
{
WildSymbol[] wilds = FindObjectsOfType<WildSymbol>();
wilds = wilds.Where( (item, index) => item.name.Contains("(Clone)") )
.OrderBy( x => x.GetComponent<WildSymbol>().IndexOnReel )
.OrderBy( x => x.GetComponentInParent<GameReel>().ReelIndex )
.ToArray();
for (int i = 0; i < wilds.Length; i++)
{
for (int j = 0; j < wilds[i].transform.childCount; j++)
{
if (wilds[i].transform.GetChild(j).gameObject.name.Contains("MM_wild"))
{
wilds[i].transform.GetChild(j).gameObject.SetActive(false);
yield return new WaitForSeconds(delayBetweenWildsDisappear);
}
}
}
}

Why subscriptions to IObservables taken from a Collection don't work (and what to do about it)

My goal is to create a bunch of observables from a source observable, so that I can subscribe to them individually.
When I do that manually (that is, creating each subSource manually), things work as expected: the values added to the original source propagate adequately to the subSources.
But when I create them in a loop, adding them to a List<IObservable<T>>, the subscriptions to elements taken from that list don't seem to be working:
class Program
{
static void Main(string[] args)
{
// using Subject for the sake of example
var source = new Subject<int>();
// manually creating each subSource
var source0 = source.Where((t, i) => i % 3 == 0);
var source1 = source.Where((t, i) => i % 3 == 1);
var source2 = source.Where((t, i) => i % 3 == 2);
// creating a List of subsources
List<IObservable<int>> sources = new List<IObservable<int>>();
int count = 3;
for (int i = 0; i < count; i++)
{
sources.Add(source.Where((v, ix) => ix % 3 == i));
}
// subscribing to one subSource from each group
source0.Subscribe(Console.WriteLine); // this works
sources[1].Subscribe(Console.WriteLine); // this doesn't
// feeding data
Observable.Range(0, 20).Subscribe(source);
Console.ReadKey();
}
}
The predicate of your Where clause references the loop variable i.
However, the predicate is tested when a value is published from source - not when the loop is iterated. By the that time, i has reached it's final value 3.
To fix this, create a new variable inside the loop to store the current value of i, and reference that in your Where predicate:
for (int i = 0; i < count; i++)
{
var j = i;
sources.Add(source.Where((v, ix) => ix % 3 == j)); // note use of j here
}
for (int i = 0; i < count; i++)
{
**var j = i;**
sources.Add(source.Where((v, ix) => ix % 3 == j));
}
Closures.

DbGeography polygon get points

I have a Polygon persisted on a SQL Server 2012 database as Sys.Geography type. How can I obtain all points for the Polygon?
I'm thinking to use AsText() method and parse the string, but maybe there is a better choice?
Found a way, here is an extension method:
public static IEnumerable<MyEntityWithLatAndLng> GetPointsFromPolygon(this System.Data.Entity.Spatial.DbGeography geo)
{
for (int i = 1; i < geo.PointCount; i++)
{
var p = geo.PointAt(i);
yield return new MyEntityWithLatAndLng(){ Latitude = p.Latitude.Value, Longitude = p.Longitude.Value };
}
}
I think Alexandre nearly has this correct, he is missing the last element of the polygon from the points list. See the updated code below.
public static IEnumerable<MyEntityWithLatAndLng> GetPointsFromPolygon(this System.Data.Entity.Spatial.DbGeography geo)
{
for (int i = 1; i <= geo.PointCount; i++)
{
var p = geo.PointAt(i);
yield return new MyEntityWithLatAndLng(){ Latitude = p.Latitude.Value, Longitude = p.Longitude.Value };
}
}
SqlGeography
class has a method STPolyFromText
which allows you to get polygon with array of points.
In C# for example:
SqlGeography poly = SqlGeography.STPolyFromText(
new SqlChars(yourEntity.geoColumn.WellKnownValue.WellKnownText),
yourEntity.geoColumn.CoordinateSystemId);
for (int i = 1; i <= poly.STNumPoints(); i++)
{
SqlGeography point = poly.STPointN(i);
//do something with point
}

Processing Code does not work

I started programming with Processing today and wrote a little programm that creates 10 random rectangles
Now I like to make them disappear when the mouse is over them, but my actual code is not working
I would apprechiate some tipps ...
import java.awt.Rectangle;
Rectangle rect[] = new Rectangle[10];
int xpos[] = new int[10];
int ypos[] = new int[10];
int size = 25;
boolean visible[] = new boolean[10];
void setup()
{
size(640,480);
frameRate(60);
smooth();
background(0);
stroke(255);
fill(255);
textAlign(CENTER);
textSize(200);
text("Catch", width/2, 280);
textSize(100);
text("them", width/2, 380);
// 10 Random positions for the rectangles
for (int i=0; i < 10; i++) {
xpos[i] = int(random (615));
ypos[i] = int(random (455));
visible[i] = true;
}
for (int i=0; i < 10; i++) {
rect[i] = new Rectangle(xpos[i],ypos[i],size,size);
}
}
void draw()
{
for (int i=0; i < 10; i++) {
if (visible[i] == true){
fill(255,0,0);
rect(rect[i].x,rect[i].y,rect[i].width,rect[i].height);}
else if (rect[i].contains(mouseX,mouseY)){
visible[i] = false; }
}}
Why else if? The way it is written, it will only check to see if the mouse is over a rect if visible[i] == false. They are all visible so it never gets executed.
Also to see the effect, you must call background(0); at the top of your draw method. Otherwise you never clear the screen to see the results.
You should also consider cleaning up your indentation and braces {} to make sure you are formatting the code in a consistent way. That would make it easier to read.