i have mathematical formula and i have spawn points. but, i have so differenet object sizes and radiuses. how i can instantiate a objects in the edge of circle and rotate them onto center circle like picture;
i am bad with this stuf and my code is wrong or not i dont know
```
public void GetObstacle(int count, CircleRotator rotator)
{
float TAU = 6.283185307179586f;
for (int i = 0; i < count; i++)
{
Transform cameraTR = mainCamera.transform;
Transform tr = rotator.transform;
var obj = new GameObject();
float t = (float)i / count;
float angle = t * TAU * 0.25f; //
Vector3 itemCenter = new Vector3(Mathf.Cos(angle) * rotator.GetRadius + tr.position.x,
tr.position.y + Mathf.Sin(angle) * rotator.GetRadius);
obj.transform.position = itemCenter;
Vector3 current = tr.position - cameraTR.position;
Vector3 target = obj.transform.position - cameraTR.position;
obj.transform.Rotate(Vector3.forward, Vector3.Dot(current, target));
obj.transform.SetParent(tr);
}
}
```
where 0.25 in here i dont understand. But without 0.25 all will broke. angle = t * TAU * 0.25f;
help pls or give some adwice. https://ibb.co/qNhZCh3 what i would like but what i have https://ibb.co/NFSRmSn
so many formulas and watched videos. but i can't understand how
Thanks #Ruzihm with help rotations.
spawn outside edge I got this way, where I'm not sure if this is the right way, where Size is the size of y collider. If someone show another good way i will be gratitude!
Vector3 direction = (tr.position - obj.transform.position);
obj.transform.rotation = Quaternion.LookRotation(Vector3.forward, direction);
obj.transform.position -= direction.normalized * obj.Size()/2f;
Related
I have an array of faces, each face has an array of points in 3d space. I want to fill an array of unfolded faces that contains the faces with their normals all pointing along the z axis. DirectionA is the z axis, DirectionB is the normal of the face. I work out the angle and axis then apply it. As I have points, myPoint is a point not a vector could that be a problem? My logic is not right somewhere....
Here is my current code:
public void UnfoldAll()
{
Vector3d directionA = new Vector3d(0, 0, 1);//z axis
int iii = 0;
foreach (Face f in faces)
{
Vector3d directionB = normals[f.normal - 1]; //normal from face
float rotationAngle = (float)Math.Acos(directionA.DotProduct(directionB));
Vector3d rotationAxis = directionA.CrossProduct(directionB);
//rotate all points around axis by angle
for (int i = 0; i < f.Corners3D.Length; i++)
{
Vector3d myPoint;
myPoint.X = f.Corners3D[i].X;
myPoint.Y = f.Corners3D[i].Y;
myPoint.Z = f.Corners3D[i].Z;
myPoint = Vector3d.Normalize(myPoint);
Vector3d vxp = Vector3d.CrossProduct(rotationAxis, myPoint);
Vector3d vxvxp = Vector3d.CrossProduct(rotationAxis, vxp);
Vector3d final = directionB;
var angle = Math.Sin(rotationAngle);
var angle2 = 1 - Math.Cos(rotationAngle);
final.X += (angle * vxp.X) + (angle2 * vxvxp.X);
final.Y += (angle * vxp.Y) + (angle2 * vxvxp.Y);
final.Z += (angle * vxp.Z) + (angle2 * vxvxp.Z);
unfoldedFaces[iii].Corners3D[i].X = final.X;
unfoldedFaces[iii].Corners3D[i].Y = final.Y;
unfoldedFaces[iii].Corners3D[i].Z = final.Z;
}
}
iii++;
}
Any suggestions would be great. Thank you.
When doing any kind of 3D transformation, it is usually a good idea to stay away from angles if you can. Things tend to be easier if you stick to matrices, quaternions and vectors as much as possible.
If you want to rotate a face you should find a transform that describes the rotation, and then simply apply this transform to each of the vertices to get the rotated triangle. You could use either a matrix or a quaternion to describe a rotational transform.
The exact method will depend a bit on what library you are using for transforms. For Unity3D you have the Quaternion.FromToRotation that should do what you want, just input the current normal as the from vector, and the desired normal as the toDirection.
If you are using System.Numerics you can use Quaternion.FromAxisAngle. Just take the cross product your two normals to get the axis, and take the arc cos of the dot-product to get the angle. Don't forget to ensure the normals are normalized.
Thank you that was helpful, here is my code if anyone else needs help:
public void UnfoldAll()
{
Vector3d directionA = new Vector3d(0, 0, 1);//z axis
unfoldedFaces = new UnfoldedFace[faces.Length];
int iii = 0;
foreach (Face f in faces)
{
unfoldedFaces[iii].Corners3D = f.Corners3D;
Vector3d directionB = normals[f.normal - 1]; //normal from face
directionB = Vector3d.Normalize(directionB);
Vector3d vxp = Vector3d.CrossProduct(directionA, directionB);
float rotationAngle = (float)Math.Acos(directionA.DotProduct(directionB));
Quaternion q = Quaternion.FromAxisAngleQ(vxp, rotationAngle);
q.Rotate(unfoldedFaces[iii].Corners3D);
iii++;
}
}
Help to understand the management of objects. At the moment, there is a rotation of the object. I want the arrow to rotate, and the angle of rotation depends on the current X and Y coordinates. Unity2D.
Now it is left (does not rotate), but it needs to be right (it always rotates and looks in one direction), but I don’t know how to calculate the degrees for rotation.
`
public float angle = 0; // угол
public float radius = 0.5f; // радиус
public bool isCircle = false; // условие движения по кругу
public float speed = 5f;
// Update is called once per frame
void Update()
{
angle += Time.deltaTime; // меняется значение угла
var x = Mathf.Cos(angle * speed) * radius + parent.position.x;
var y = Mathf.Sin(angle * speed) * radius + parent.position.y;
transform.position = new Vector3(x, y,0);
//transform.Rotate(0, 0, a);
}
`
Help me, how to calculate angle?
You need Mathf.Atan2, it will return a radian, then you need to multiply a Mathf.Rad2Deg to get the Euler angle.
A little bit confused - math is really not my strong point, so I'm not sure how to achieve.
Currently the objects instantiate, but I have no control over the distance from center or the rotation of each spawned object
public void instantiateInCircle()
{
for (int i = 0; i < amount; i++)
{
float radius = spawnDistance;
float angle = i * Mathf.PI * 2f / radius;
Vector3 newPos = transform.position + (new Vector3(Mathf.Cos(angle) * radius, spawnHeight, Mathf.Sin(angle) * radius ));
//Rotate objects to look at the center
GameObject instantiatedObject = Instantiate(itemToSpawn, newPos, Quaternion.Euler(0, 0, 0));
instantiatedObject.transform.LookAt(spawnAroundThis.transform);
//How to adjust the width of the radius, how far away from the center?
//Parent instantiated objects to disk
instantiatedObject.transform.parent = spawnAroundThis.transform;
instantiatedObject.transform.localScale = new Vector3(scale, scale, scale);
}
}
How to make the distance adjustable, move cubes in closer to center...?
Currently, you do not access the instantiated object, but the prefab instead. Cache the object and call the LookAt on them.
Since I do not know what type itemToSpawn is, I assumed it is a GameObject. You may want to use your type instead.
GameObject instantiatedObject = Instantiate(itemToSpawn, newPos, Quaternion.Euler(0, 0, 0));
instantiatedObject.transform.LookAt(spawnAroundThis.transform);
If you want to control the distance from center of the rotation:
for (int i = 0; i < amount; i++)
{
float radius = spawnDistance;
float angle = i * Mathf.PI * 2f / (float)amount; // divide by amount, NOT radius
// manipulate radius here as you want
Vector3 newPos = transform.position + (new Vector3(Mathf.Cos(angle) * radius, spawnHeight, Mathf.Sin(angle) * radius ));
...
}
I have a dilemma on an algorithm. I'm trying to generate 6 random positions that have a distance between them. My algorithm works, only to check the distance between the current point and the previous point. What I need is for the algorithm to verify the distance between all points and if the distance is less than the indicated value, it will generate a new position.
private void Generate()
{
for (int i = 0; i <= 5; i++)
{
Vector3 pos = PointsGenerator();
Instantiate(point, pos, Quaternion.identity); // just to highlight the points on the screen
}
}
private List<Vector3> Dist = new List<Vector3>();
private bool isOver = false;
private Vector3 PointsGenerator()
{
Vector3 currentPosition = Vector3.zero;
Vector3 oldPosition = Vector3.zero;
float distance = 0f;
do
{
currentPosition = new Vector3(UnityEngine.Random.Range(minX, maxX), UnityEngine.Random.Range(minY, maxY), 0f);
for (int i = 0; i < Dist.Count; i++)
{
distance = Vector2.Distance(currentPosition, Dist[i]);
if (distance <= 4f)
{
isOver = true;
break;
}
else
isOver = false;
}
} while (isOver == true);
Dist.Add(currentPosition);
return currentPosition;
}
Thanks to all who will give advice.
what is the question?
"I need these 6 points and not only have a distance between them, but also the distance from center + radius to be of value"
To achieve that, you will HAVE TO generate points that are on a sphere. For that, generate a (random if needed) center point of your sphere and define the radius.
Then, you need to use random spherical coordinates (radius, randomAngle1, randomAngle2). To convert those into cartesian coordinates, use
x = radius * cos(randomAngle1) * sin(randomAngle2)
y = radius * sin(randomAngle1) * sin(randomAngle2)
z = radius * cos(randomAngle1)
after that you can make the same algorithm as you already have to regenerate new points until they are far away from each other as well
I have just done the Curves and Splines Tutorials from the catlikecoding.com website (http://catlikecoding.com/unity/tutorials/curves-and-splines/) and after finishing it I came up with an idea. I would like to spawn the items from the SplineDecorator at the same distance from the spline at both sides of the spline. I have tried duplicating the for loop and instantiating the newItem twice but at different position but it doenst work as I want to. Here's the Spline Decorator script that takes a spline and then Instantiate some items along the its path
using UnityEngine;
public class SplineDecorator : MonoBehaviour
{
public BezierSpline spline;
public int frequency;
public float distanceBetweenItems;
public bool lookForward;
public Transform[] items;
private void Awake()
{
if (frequency <= 0 || items == null || items.Length == 0)
{
return;
}
float stepSize = 1f / (frequency * items.Length);
for (int p = 0, f = 0; f < frequency; f++)
{
for (int i = 0; i < items.Length; i++, p++)
{
Transform item = Instantiate(items[i]) as Transform;
Vector3 position = spline.GetPoint(p * stepSize);
item.transform.localPosition = new Vector3(position.x + distanceBetweenItems, position.y, position.z);
if (lookForward)
{
item.transform.LookAt(position + spline.GetDirection(p * stepSize));
}
item.transform.parent = transform;
}
}
}
}
You don't define exactly what "at both sides" means to you, so I'm not sure if this is what you're looking for, but maybe this will get you on the right track.
I replaced the inner loop with the following and got a sort of "race track" feel with distanceBetweenItems = 2:
Transform item = Instantiate(items[i]) as Transform;
Transform item2 = Instantiate(items[i]) as Transform;
Vector3 position = spline.GetPoint(p * stepSize);
Vector3 direction = spline.GetDirection(p * stepSize);
Vector3 cross = Vector3.Cross(direction, Vector3.up);
Vector3 delta = cross.normalized * (distanceBetweenItems/2);
item.transform.localPosition = new Vector3(position.x + delta.x, position.y + delta.y, position.z + delta.z);
item2.transform.localPosition = new Vector3(position.x - delta.x, position.y - delta.y, position.z - delta.z);
if (lookForward)
{
item.transform.LookAt( position + spline.GetDirection(p * stepSize));
item2.transform.LookAt(position + spline.GetDirection(p * stepSize));
}
item.transform.parent = transform;
item2.transform.parent = transform;
What I've done here is use Vector3.Cross() (Unity Documentation) to find the line perpendicular to both the spline and Vector3.up. Then I calculate how far along that line to go by normalizing it and multiplying it by half of distanceBetweenItems. (So that, combined, they're distanceBetweenItems apart.)
If you instead wanted something like tracing the wingtips of a plane flying that spline, you'll need to replace the Vector.up above. The simplest way is to replace it with the 'binormal vector', though there are issues with that. This pdf I just found talks a little about it, and might get you on the right path.
(Goofing around, I was able to get a reasonable approximation by replacing the Vector3 cross = ... line with Vector3 cross = Vector3.Cross(direction, direction - spline.GetDirection(p * stepSize + 0.01f));, though it's screwy on sharp bends, non-mirrored vertices, and at the start/end loop.)