if (((float) (Math.Round(gameObject.transform.position.x, 1))) == ((float) (Math.Round(array[i].x, 1))) && (((float) (Math.Round(gameObject.transform.position.y, 1))) == (float) (Math.Round(array[i].y, 1))))
Hello! I am using C#, and the array is filled with vector positions. I am trying to see when an object gets to a certain position. This never triggers. Do you have any other tips how to do this?
You are comparing float values directly ... never do that. It leads to a problem with the floating point precision. float values are internally actually stored in increments of an Epsilon.
see e.g. from here
The nearest float to 16.67 is 16.6700000762939453125
The nearest float to 100.02 is 100.01999664306640625
or here for a broader explenation.
Use Vector3.Distance!
Preferably with a certain threshold distance. There is an example that looks exactly like what you want to do in Coroutines (in JavaScript but the difference to c# in this case is minimal)
public float threshold = 0.1f;
//...
if(Vector3.Distance(gameObject.transform.position, array[i]) <= threshold)
{
....
}
Adjust threshold so it has a value that is bigger than what the object can possibly move between two frames.
Or together with Mathf.Approximately
if(Math.Approximately(Vector3.Distance(object.transform.position, array[i]), 0.0f))
{
....
}
if your threshold is smaller than 0.00001 than you could also use
if(object.transform.position == array[i])
{
....
}
since == uses <= 0.00001 for equality.
But note: In the most cases the last two options will also fail because the opts for a moving GameObject to match an exact 3D position are almost 0 unless you set fixed values somewhere.
Vector3.Distance also works with a Vector2 as parameter since an implicit typecast to Vector3 exists.
Related
I'm trying to make a type of projectile with Rigidbody:
private void FiredAsProjectile(GameObject target)
{
Vector3 moveVector = Vector3.Zero;
float velMod = 8f // A placeholder value to later calculate with mass / velocity
if(target != null)
{
moveVector = (target.transform.position - transform.position);
m_rb.MovePosition(transform.position + moveVector * Time.deltaTime * velMod);
}
}
This is updated via FixedUpdate upon calling this method somewhere else. I have a few things I needed this to behave: to have velocity output and move to a position, not direction.
However, I'm getting a weird outcome. Even though this object moves as a kinematic rigidbody and its interpolation is set to None this object slows down before reaching the target vector as if it has interpolation. Let's say I wanted a bullet to be fired from the barrel and fly to a point in world instead of direction, that's what I wanted this object to behave like, but not quite so.
Am I missing something or misunderstanding something?
Is there a better way to move this kinematic rigidbody whilst still outputting rigidbody.velocity and still collide?
This happens because you don't Normalize the moveVector.
To explain why this happens, we'll suppose that Time.deltaTime = 0.01 every step:
At t0 time, let's say that the distance between the moving object (in x = 0) and the target object (x = 100) is 100.
The argument of MovePosition is 0 + 100*8*.01 = 8 and the object is moved accordingly to this new position (since you said it's Kinematic without interpolation)
At t1 time, moveVector = 100-8 = 92
The new argument now is 8 + 92*8*.01 = 15.36
Notice that between t0 and t1 you moved 8 units, whereas between t1 and t2 you moved only 7.36 units. So, the more your moving object is near the target object, the less you'll move the object, giving the effect of "slowing down" (and moreover it'll never reach the target object, you'll stop at a distance equal to the minimum floating number precision).
In order to fix this, you just need to normalize the moveVector, i.e. making its module fixed every step. So, just add this line:
moveVector = (target.transform.position - transform.position);
moveVector.Normalize();
m_rb.MovePosition(transform.position + moveVector * Time.deltaTime * velMod);
and the distance moved every step will always be the same regardless of distance.
Check the following gif: https://i.gyazo.com/72998b8e2e3174193a6a2956de2ed008.gif
I want the cylinder to instantly change location to the nearest empty space on the plane as soon as I put a cube on the cylinder. The cubes and the cylinder have box colliders attached.
At the moment the cylinder just gets stuck when I put a cube on it, and I have to click in some direction to make it start "swimming" through the cubes.
Is there any easy solution or do I have to create some sort of grid with empty gameobjects that have a tag which tells me if there's an object on them or not?
This is a common problem in RTS-like video games, and I am solving it myself. This requires a breadth-first search algorithm, which means that you're checking the closest neighbors first. You're fortunate to only have to solve this problem in a gridded-environment.
Usually what programmers will do is create a queue and add each node (space) in the entire game to that queue until an empty space is found. It will start with e.g. the above, below, and adjacent spaces to the starting space, and then recursively move out, calling the same function inside of itself and using the queue to keep track of which spaces still need to be checked. It will also need to have a way to know whether a space has already been checked and avoid those spaces.
Another solution I'm conceiving of would be to generate a (conceptual) Archimedean spiral from the starting point and somehow check each space along that spiral. The tricky part would be generating the right spiral and checking it at just the right points in order to hit each space once.
Here's my quick-and-dirty solution for the Archimedean spiral approach in c++:
float x, z, max = 150.0f;
vector<pair<float, float>> spiral;
//Generate the spiral vector (run this code once and store the spiral).
for (float n = 0.0f; n < max; n += (max + 1.0f - n) * 0.0001f)
{
x = cos(n) * n * 0.05f;
z = sin(n) * n * 0.05f;
//Change 1.0f to 0.5f for half-sized spaces.
//fmod is float modulus (remainder).
x = x - fmod(x, 1.0f);
z = z - fmod(z, 1.0f);
pair<float, float> currentPoint = make_pair(x, z);
//Make sure this pair isn't at (0.0f, 0.0f) and that it's not already in the spiral.
if ((x != 0.0f || z != 0.0f) && find(spiral.begin(), spiral.end(), currentPoint) == spiral.end())
{
spiral.push_back(currentPoint);
}
}
//Loop through the results (run this code per usage of the spiral).
for (unsigned int n = 0U; n < spiral.size(); ++n)
{
//Draw or test the spiral.
}
It generates a vector of unique points (float pairs) that can be iterated through in order, which will allow you to draw or test every space around the starting space in a nice, outward (breadth-first), gridded spiral. With 1.0f-sized spaces, it generates a circle of 174 test points, and with 0.5f-sized spaces, it generates a circle of 676 test points. You only have to generate this spiral once and then store it for usage numerous times throughout the rest of the program.
Note:
This spiral samples differently as it grows further and further out from the center (in the for loop: n += (max + 1.0f - n) * 0.0001f).
If you use the wrong numbers, you could very easily break this code or cause an infinite loop! Use at your own risk.
Though more memory intensive, it is probably much more time-efficient than the traditional queue-based solutions due to iterating through each space exactly once.
It is not a 100% accurate solution to the problem, however, because it is a gridded spiral; in some cases it may favor the diagonal over the lateral. This is probably negligible in most cases though.
I used this solution for a game I'm working on. More on that here. Here are some pictures (the orange lines in the first are drawn by me in Paint for illustration, and the second picture is just to demonstrate what the spiral looks like if expanded):
I have a voxel based game in development right now and I generate my world by using Simplex Noise so far. Now I want to generate some other structures like rivers, cities and other stuff, which can't be easily generated because I split my world (which is practically infinite) into chunks of 64x128x64. I already generated trees (the leaves can grow into neighbouring chunks), by generating the trees for a chunk, plus the trees for the 8 chunks surrounding it, so leaves wouldn't be missing. But if I go into higher dimensions that can get difficult, when I have to calculate one chunk, considering chunks in an radius of 16 other chunks.
Is there a way to do this a better way?
Depending on the desired complexity of the generated structure, you may find it useful to first generate it in a separate array, perhaps even a map (a location-to-contents dictionary, useful in case of high sparseness), and then transfer the structure to the world?
As for natural land features, you may want to google how fractals are used in landscape generation.
I know this thread is old and I suck at explaining, but I'll share my approach.
So for example 5x5x5 trees. What you want is for your noise function to return the same value for an area of 5x5 blocks, so that even outside of the chunk, you can still check if you should generate a tree or not.
// Here the returned value is different for every block
float value = simplexNoise(x * frequency, z * frequency) * amplitude;
// Here it will return the same value for an area of blocks (you should use floorDiv instead of dividing, or you it will get negative coordinates wrong (-3 / 5 should be -1, not 0 like in normal division))
float value = simplexNoise(Math.floorDiv(x, 5) * frequency, Math.floorDiv(z, 5) * frequency) * amplitude;
And now we'll plant a tree. For this we need to check what x y z position this current block is relative to the tree's starting position, so we can know what part of the tree this block is.
if(value > 0.8) { // A certain threshold (checking if tree should be generated at this area)
int startX = Math.floorDiv(x, 5) * 5; // flooring the x value to every 5 units to get the start position
int startZ = Math.floorDiv(z, 5) * 5; // flooring the z value to every 5 units to get the start position
// Getting the starting height of the trunk (middle of the tree , that's why I'm adding 2 to the starting x and starting z), which is 1 block over the grass surface
int startY = height(startX + 2, startZ + 2) + 1;
int relx = x - startX; // block pos relative to starting position
int relz = z - startZ;
for(int j = startY; j < startY + 5; j++) {
int rely = j - startY;
byte tile = tree[relx][rely][relz]; // Get the needing block at this part of the tree
tiles[i][j][k] = tile;
}
}
The tree 3d array here is almost like a "prefab" of the tree, which you can use to know what block to set at the position relative to the starting point. (God I don't know how to explain this, and having english as my fifth language doesn't help me either ;-; feel free to improve my answer or create a new one). I've implemented this in my engine, and it's totally working. The structures can be as big as you want, with no chunk pre loading needed. The one problem with this method is that the trees or structures will we spawned almost within a grid, but this can easily be solved with multiple octaves with different offsets.
So recap
for (int i = 0; i < 64; i++) {
for (int k = 0; k < 64; k++) {
int x = chunkPosToWorldPosX(i); // Get world position
int z = chunkPosToWorldPosZ(k);
// Here the returned value is different for every block
// float value = simplexNoise(x * frequency, z * frequency) * amplitude;
// Here it will return the same value for an area of blocks (you should use floorDiv instead of dividing, or you it will get negative coordinates wrong (-3 / 5 should be -1, not 0 like in normal division))
float value = simplexNoise(Math.floorDiv(x, 5) * frequency, Math.floorDiv(z, 5) * frequency) * amplitude;
if(value > 0.8) { // A certain threshold (checking if tree should be generated at this area)
int startX = Math.floorDiv(x, 5) * 5; // flooring the x value to every 5 units to get the start position
int startZ = Math.floorDiv(z, 5) * 5; // flooring the z value to every 5 units to get the start position
// Getting the starting height of the trunk (middle of the tree , that's why I'm adding 2 to the starting x and starting z), which is 1 block over the grass surface
int startY = height(startX + 2, startZ + 2) + 1;
int relx = x - startX; // block pos relative to starting position
int relz = z - startZ;
for(int j = startY; j < startY + 5; j++) {
int rely = j - startY;
byte tile = tree[relx][rely][relz]; // Get the needing block at this part of the tree
tiles[i][j][k] = tile;
}
}
}
}
So 'i' and 'k' are looping withing the chunk, and 'j' is looping inside the structure. This is pretty much how it should work.
And about the rivers, I personally haven't done it yet, and I'm not sure why you need to set the blocks around the chunk when generating them ( you could just use perlin worms and it would solve problem), but it's pretty much the same idea, and for your cities too.
I read something about this on a book and what they did in these cases was to make a finer division of chunks depending on the application, i.e.: if you are going to grow very big objects, it may be useful to have another separated logic division of, for example, 128x128x128, just for this specific application.
In essence, the data resides is in the same place, you just use different logical divisions.
To be honest, never did any voxel, so don't take my answer too serious, just throwing ideas. By the way, the book is game engine gems 1, they have a gem on voxel engines there.
About rivers, can't you just set a level for water and let rivers autogenerate in mountain-side-mountain ladders? To avoid placing water inside mountain caveats, you could perform a raycast up to check if it's free N blocks up.
I'm working on a game in Unity where you can walk around in a city that also exists in real life.
In the game you should be able to enter real-world coordinates, or use your phone's GPS, and you'll be transported to the in-game position of those coordinates.
For this, i'd need to somehow convert the game coordinates to latitude and longitude coordinates. I have some coordinates from specific buildings, and i figured i might be able to write a script to determine the game coordinates from those reference points.
I've been searching for a bit on Google, and though i have probably come across the right solutions occasionally, i've been unable to understand them enough to use it in my code.
If someone has experience with this, or knows how i could do this, i'd appreciate it if you could help me understand it :)
Edit: Forgot to mention that other previous programmers have already placed the world at some position and rotation they felt like using, which unfortunately i can't simply change without breaking things.
Tim Falken
This is simple linear math. The main issues you'll come across is the fact that your game coordinate system will be probably be reversed along one or more axis. You'll probably need to reverse the direction along the latitude (Y) axis of your app. Aside from that it is just a simple conversion of the scales. Since you say that this is the map of a real place you should be able to easily figure out the min\max lon\lat which your map covers. Take the absolute value of the difference between these two values and divide that by the width\height of your map in each direction. This will be the change in latitude per map unit value. Store this value and it should be easy to convert both ways between the two units. Make functions that abstract the details and you should have no problems calculating this either way.
I assume that you have been able to retrieve the GPS coordinates OK.
EDIT:
By simple linear math I mean something like this (this is C++ style psuedo code and completely untested; in a real world example the constants would all be member variables instead):
define('MAP_WIDTH', 1000);
define('MAP_HEIGHT', 1000);
define('MIN_LON', 25.333);
define('MIN_LAT', 20.333);
define('MAX_LON', 27.25);
define('MAX_LAT', 20.50);
class CoordConversion {
float XScale=abs(MAX_LON-MIN_LON)/MAP_WIDTH;
float YScale=abs(MAX_LAT-MIN_LAT)/MAP_HEIGHT;
int LonDir = MIN_LON<MAX_LON?1:-1;
int LatDir = MIN_LAT<MAX_LAT?1:-1;
public static float GetXFromLon(float lon) {
return (this.LonDir>0?(lon-MIN_LON):(lon-MAX_LON))*this.XScale;
}
public static float GetYFromLat(float lat) {
return (this.LatDir >0?(lat-MIN_LAT):(lat-MAX_LAT))*this.YScale;
}
public static float GetLonFromX(float x) {
return (this.LonDir>0?MIN_LON:MAX_LON)+(x/this.XScale);
}
public static float GetLatFromY(float y) {
return (this.LonDir>0?MIN_LAT:MAX_LAT)+(y/this.YScale);
}
}
EDIT2: In the case that the map is rotated you'll want to use the minimum and maximum lon\lat actually shown on the map. You'll also need to rotate each point after the conversion. I'm not even going to attempt to get this right off the top of my head but I can give your the code you'll need:
POINT rotate_point(float cx,float cy,float angle,POINT p)
{
float s = sin(angle);
float c = cos(angle);
// translate point back to origin:
p.x -= cx;
p.y -= cy;
// rotate point
float xnew = p.x * c - p.y * s;
float ynew = p.x * s + p.y * c;
// translate point back:
p.x = xnew + cx;
p.y = ynew + cy;
}
This will need to be done in when returning a game point and also it needs to be done in reverse before using a game point to convert to a lat\lon point.
EDIT3: More help on getting the coordinates of your maps. First find the city or whatever it is on Google maps. Then you can right click the highest point (furthest north) on your maps and find the highest longitude. Repeat this for all four cardinal directions and you should be set.
I'm not sure how the CGPoint variable that I have created knows how to handle the specific if statement.
For example, I have CGPoint myVelocity; then I have an arbitrary number float maximumVelocity = 100;
Then I execute the following code
if (myVelocity.x > maximumVelocity) {
myVelocity.x = maximumVelocity;
}
else if (myVelocity.x < -maximumVelocity)
{
myVelocity.x = -maximumVelocity;
}
From what I understand, if the first condition is met, which is myVelocity.x > maximumVelocity then the CGPoint variable is set to the maximum, which is the number 100. This is so that my variable never exceeds the arbitrary number. And the other condition is set up so that it doesn't go into the negative..
At least that's what I think.
Now here is the important part of this post.. I'm confused with how the myVelocity variable knows what the that arbitrary number is. For example is it 10? is it 25 the next second or when does it reach 100.
I should also point out that before the if statement is run, I have the following code stored in myVelocity
The following is the code that is stored into 'myVelocity' prior to the if statement executing.
float deceleration = 0.4f;
float sensitivity = 6.0f;
float maximumVelocity = 100;
myVelocity.x = myVelocity.x *deceleration + acceleration.x *sensitivity;
I have recently inquired about code smilar to the latter part of my question, but now I'm curious about the former.
A CGPoint is just a struct with "x" and "y" components. You can think of it as an easier way to pass around a pair of floats.
So your code above would be equivalent to:
float x;
// other stuff
if (x > maximumVelocity) {
x = maximumVelocity;
}
else if (x < -maximumVelocity)
{
x = -maximumVelocity;
}
Now pair that with another variable by using a struct:
struct CGPoint {
float x;
float y;
};
and to access that "x" variable, to either set or read from it, use ".x", like you did in your code sample.
(P.S. CGPoints actually are a pair of CGFloats for reasons that are irrelevant to this post)
GCPoint represent a bidimensional space, ideally storing a velocity in a CGPoint means that you need a velocity vector represented by 2 dimensions, x and y.
In your case i see that you only use 1 dimension, i didnt quite get what your trying to achieve but in your case you can just use a float to store velocity value if it has not a direction.
If you need a 2 dimension velocity you have to check for maximumVelocity by checking the lenght of the vector. In you example your checking only the x dimension, but if the velocity is x=50,y=20000 this is moving pretty fast on the y axis.
ccpLength(<#const CGPoint v#> let you check the lenght of a CGPoint, so you can compare with a float to see if the actual velocity is faster than your maximum, in that case you need to normalize your vector to actually match your maxiumVelocity, you can do this with
ccpMult(v, maximumVelocity/ccpLength(v))