I want to rotate my player in the way I showed in the picture. I don't understand what Vector3. I would use here in transform.rotate
As we talked in comments I guess that you know what Vectors are from your background.
And with transform.rotate() there are more then one options to use that method which we call Method Overloading. And one of the way to use is that is transform.Rotate(Vector3 direction, float rotation).
And the reason it takes Vector3 as a direction in this method is because the way Unity handles direction.
In Unity as when it comes to direction with Vector3 it is considered/calculated as follows
Vector3.right = x = 1, y = 0, z = 0
Vector3.left = x = -1, y = 0, z = 0
Vector3.up = x = 0, y = 1, z = 0
Vector3.down = x = 0, y = -1, z = 0
Vector3.forward = x = 0, y = 0, z = 1
Vector3.back = x = 0, y = 0, z = -1
So to answering your question you can achieve the functionality by using Vector3.forword as direction. Because the direction/Axis you want your object to be rotated is the one from back to front if you consider Vector3 that would be z axis ans as I've listed above you can use Vector3.forward as a direction/axis of your rotation in transform.Rotate()
Reference:
Tranform.Rotate
Hope this helps, welcome to unity Happy Coding
Related
I am working on a 3D project, in Unity.
I have an object moving in a confined space. The object have a fixed velocity, and it bounces back once they reach the space limit.
I want it to change direction once every n seconds.
The problem I am facing is: How to rotate a 3D vector by a given angle.
In 2D is pretty easy, while in 3D I am not sure how to handle it.
Can someone help me with that?
In 2D this is simple...
In three 3 as well.
You can e.g. simply rotate a Vector3 about any given Euler angles via
var newVector = Quaternion.Euler(x, y, z) * oldVector;
question remains where you get those angles from and whether those are random or you are rather looking for Reflect the vector once the objects reach your defined area constraints.
You can as well simply invert the individual components like e.g.
// Note for simplicity reasons this is not an actual "distance"
// but rather the maximum of each individual axis
public float maxDistance;
private Rigidbody _rigidbody;
private void Start ()
{
_rigidbody = GetComponent<Rigidbody>();
_rigidbody.velocity = Random.insideUnitSphere.normalized;
}
private void FixedUpdate()
{
var vel = _rigidbody.velocity;
var pos = _rigidbody.position;
if(Mathf.Abs(pos.x) >= maxDistance)
{
vel.x *= -1;
}
if(Mathf.Abs(pos.y) >= maxDistance)
{
vel.y *= -1;
}
if(Mathf.Abs(pos.z) >= maxDistance)
{
vel.z *= -1;
}
_rigidbody.velocity = vel;
}
You can change directions by a certain angle on a certain axis, making it similar to 2D.
If you are moving the object with its transform you can easily rotate an object with the Rotate method on the game object transform.
//in a script attached to the game object you want to rotate
transform.Rotate(Vector3.up, Random.Range(90,270), Space.self);
You can now use transform.forward to move the object.
If you want to go deeper into 3D rotation have a look at Quaternions
You can use the Quaternion.operator * to rotate one rotation by another, or to rotate a vector by a rotation.
Consider also looking at the Vector3 class methods such as Reflect and RotateTowards.
Tip: To keep a consistent speed across all directions, consider normalizing the direction vector, (0,1,1) will travel faster than (0,0,1).
You can normalize any vector as follows:
Vector3 direction = Vector3.up + Vector3.forward; //(0,1,1)
direction = direction.normalized; //(0,0.71,0.71)
I managed to do the thing I wanted. Firstly, I computed a Vector3 that was orthogonal to the current transform.forward; then I rotate that angle around itself of a random angle between 0 and 360 degrees, and finally I used that generated vector as axis for the rotation to apply to the velocity of my object.
Here is the code:
public static void ChangeObjectDirection(Rigidbody rb, int angle, float velocity)
{
// get the transform of rb
var t = rb.gameObject.transform;
// get the current velocity direction
var direction = t.forward;
// generate a normalized orthogonal vector wrt the current velocity direction
var orth = OrthogonalVector(direction);
// rotate the orthogonal vector around himself of a random angle between 0 and 360
orth = Quaternion.AngleAxis(Random.Range(0, 360), direction) * orth;
// generate random rotational angle in degrees
var randomAngle = Random.Range(-angle, angle);
// rotate the current velocity direction of randomAngle around the orth vector
direction = Quaternion.AngleAxis(randomAngle, orth) * direction;
// update the velocity direction
t.forward = direction;
rb.velocity = direction * velocity;
}
private static Vector3 OrthogonalVector(Vector3 u)
{
var a = u.x;
var b = u.y;
var c = u.z;
Vector3 v;
if (b == 0 && c == 0)
{
v = new Vector3(0f, 1f, 1f);
}
else if (a == 0 && c == 0)
{
v = new Vector3(1f, 0f, 1f);
}
else if (a == 0 && b == 0)
{
v = new Vector3(1f, 1f, 0f);
}
else
{
if (c != 0)
{
// ax + bx + cz == 0 with x == 1 and y == 1 => z = (-a - b) / c
v = new Vector3(1f, 1f, (-a - b) / c);
}
else
{
// ax + bx + cz == 0 with y == 1 and z == 1 => c = (-b - c) / a
v = new Vector3((-b - c) / a, 1f, 1f);
}
}
v = v.normalized;
return v;
}
I am trying to learn how to animate dots and update their x and y positions from frame to frame. I have found a tutorial online, and I am really struggling with the formulas that are used in dx and dy:
dots.speed = 3; %degrees/second
dots.duration = 5; %seconds
dots.direction_deg = 30; %degrees (clockwise from straight up)
dots.direction_rad = dots.direction_deg * pi /180 %direction converted to radians
% Calculate the distance travelled by a dot (in degrees), which is the speed (degrees/second) divided by the frame rate (frames/second).
dx = dots.speed*sin(dots.direction_rad)/display.frameRate;
dy = -dots.speed*cos(dots.direction_rad)/display.frameRate;
With my knowledge in trigonometry, I end up with these formulas for dx and dy:
Cos(angle) = Adjacent/Hypotenuse --> cos(dots.direction_rad) = 1/dx (1 is the distance from the origin to a point on the circle,which is equal to 1 radian). --> dx = 1/cos(dots.direction_rad) --> the distance is then equal to :
dots.speed*1/cos(dots.direction_rad)*display.frameRate
Sin(angle) = Opposite/Hypotenuse --> sin(dots.direction_rad) = dy/1 --> the distance is then equal to :
dots.speed * sin(dots.direction_rad) / display.frameRate.
My formulas are not giving the expected result. So what I am doing wrong. I don't seem to understand how the dx and dy were computed in the tutorial. Please help! thanks
i'm trying to get the tangent vector for each point on the circle , i tried to use the derivative for the circle equation, but the result looks off in the viewport, so i'm wondering if i can find some help here
the code
public void OnDrawGizmos(){
step = (360.0f * Mathf.Deg2Rad) / numberOfPoints ;
CreateVertices();
}
void CreateVertices()
{
Points.Clear();
Normals.Clear();
Tangents.Clear();
float dynamicAngle = 0.0f;
for (int i = 0; i <= numberOfPoints; i++)
{
Vector3 point;
point.x = transform.position.x + Radius * Mathf.Cos(dynamicAngle);
point.y = transform.position.y + Radius * Mathf.Sin(dynamicAngle);
point.z = transform.position.z;
dynamicAngle = dynamicAngle + step;
if (i >= 1)
{
Gizmos.color = Color.red;
Gizmos.DrawLine(Points[i - 1], point);
Gizmos.color = Color.white;
}
Points.Add(point);
CalculateNormals(dynamicAngle ,point);
CalculateTangents(dynamicAngle,i , point);
}
}
void CalculateNormals(float dynamicAngle , Vector3 point)
{
Vector3 Normal = (point - transform.position).normalized;
Gizmos.color = Color.magenta;
Gizmos.DrawLine(Normal, point);
Gizmos.color = Color.white;
Normals.Add(Normal);
}
void CalculateTangents(float dynamicAngle,int i ,Vector3 point)
{
Vector3 tangent;
tangent = new Vector3(-Normals[i].y, Normals[i].x, 0);
tangent.Normalize();
Gizmos.color = Color.blue;
Gizmos.DrawLine( point, tangent);
Gizmos.color = Color.white;
Tangents.Add(tangent);
}
Blue is the tangents purple is the normals, as you can see they are not perpendicular:
To understand my issue better here is a gif from unity viewport:
Since you already calculated the normals you can use the cross product to get the corresponding tangents
Vector3 up = new Vector3(0, 0, 1); // up side of your circle
Vector3 tangent = Vector3.Cross(normal, up);
If you only need to use circles on a specific plane you can also use this simplification
Vector3 tangent = new Vector3(-normal.y, normal.x, 0);
Edit:
The normals and tangents are direction vectors. They point from point in the direction the normal / tangent whould point. To draw the tangent, you have to pass the correct start and end points of the line by using
Gizmos.DrawLine(point, point + tangent);
If you move the GameObject away from the origin you will notice that the normals also get deformed, this has the same reason.
You are using 2D parametric equations:
x = x0 + r*cos(a)
y = y0 + r*sin(a)
z = z0
a = <0,2*Pi>
Tangent is unit circle coordinate with center (0,0,0) but shifted by 90 degrees:
tx = cos(a (+/-) pi/4)
ty = sin(a (+/-) pi/4)
tz = 0
Similarly bi-tangent is:
bx = (+/-) cos(a)
by = (+/-) sin(a)
bz = 0
and finally normal is
nx = 0
ny = 0
nz = (+/-) 1
The signs depends on your coordinate system conventions and movement direction.
I'd like to draw the trajectory of an object that is moving circularly, but I do not know how to do it.
Could you tell me a good way?
I've not done a orbiting around something, but I am using Cos and Sin to generate static items around the object.
If you use TrailRenderer with the use of MathF cos and sin to rotate around an object.
var y = amplitude * MathF.cos(Time.timeSinceLevelLoaded * speed) + currentPosY
var x = amplitude * MathF.sin(Time.timeSinceLevelLoaded * speed) + currentPosX
I've not watched it, but "Board to bits" on youtube has a tutorial on the matter. of space orbiting for a planet playlist.
Hope this is the right direction for you.
Thank you for a lot of response.
I found it works with below...
void drawLine()
{
Vector3[] points = new Vector3[segments+1];
for (int i = 0; i< segments; i++)
{
float angle = ((float)i / (float)segments) * 360 * Mathf.Deg2Rad;
float x = Mathf.Sin(angle) * radius;
float z = Mathf.Cos(angle) * radius;
points[i] = new Vector3(x, 0f, z);
}
points[segments] = points[0];
lr.positionCount = segments + 1;
lr.SetPositions(points);
}
I am doing some work with opengl es on the iPhone and I am stuck at a particular point. All the code samples on the internet show you how a matrix can be rotated about the x axis, y axis or the z axis but no one talks about how a matrix can be rotated about an arbitrary point?
I am using open gl es 2.0. Any help would be appreciated.
Regards,
It sounds like you're asking how to construct a matrix that rotates around one of those axes, but at a different point. The way you do that is to first translate to that point, and then apply the rotation for the axis you want. The order of multiplication of matrixes depends on whether you think of it as the axes moving or the geometry.
If you also want to be able to do a rotation of arbitrary x, y, z angle at the same time, you can use the matrix discussed in this article:
static inline void Matrix3DSetRotationByRadians(Matrix3D matrix, GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
{
GLfloat mag = sqrtf((x*x) + (y*y) + (z*z));
if (mag == 0.0)
{
x = 1.0;
y = 0.0;
z = 0.0;
}
else if (mag != 1.0)
{
x /= mag;
y /= mag;
z /= mag;
}
GLfloat c = cosf(angle);
GLfloat s = fastSinf(angle);
matrix[3] = matrix[7] = matrix[11] = matrix[12] = matrix[13] = matrix[14] = 0.0;
matrix[15] = 1.0;
matrix[0] = (x*x)*(1-c) + c;
matrix[1] = (y*x)*(1-c) + (z*s);
matrix[2] = (x*z)*(1-c) - (y*s);
matrix[4] = (x*y)*(1-c)-(z*s);
matrix[5] = (y*y)*(1-c)+c;
matrix[6] = (y*z)*(1-c)+(x*s);
matrix[8] = (x*z)*(1-c)+(y*s);
matrix[9] = (y*z)*(1-c)-(x*s);
matrix[10] = (z*z)*(1-c)+c;
}