I'm making a script which should rotate a GameObject like a joystick, which means that only X and Z axes must change. So i'm using sin and cos functions to calculate rotation angles. But for some reason Y axis changes as well.
public float alpha;
void Update () {
alpha += Time.deltaTime;
var x = R * Mathf.Cos(alpha);
var z = R * Mathf.Sin(alpha);
transform.Rotate(new Vector3(x, 0, z) * Time.deltaTime);
}
So the question is how do I stop Y axis from changing or maybe there is another way to rotate the object like a joystick.
P.S. I am using Unity 2017.4.13f1
In your update function you may write :
public float alpha;
public Vector3 rotation;
void Start(){
rotation = transform.rotation.eulerAngles;
}
void Update () {
alpha += Time.deltaTime;
var x = Mathf.Cos(alpha);
var z = Mathf.Sin(alpha);
rotation.x = x;
rotation.z = z;
transform.rotation = Quaternion.Euler(rotation*time.deltaTime);
}
I couldn't understand the R variable that you multiplied with Sin and Cos. where is that R defined???
I decided to set Y axis to 0 every frame. Maybe not the most elegant solution but it works just as I needed.
Vector3 rotationVector;
void Start()
{
rotationVector = new Vector3();
}
private float alpha;
public float multiplier;
void Update ()
{
alpha += Time.deltaTime;
rotationVector.x = Mathf.Cos(alpha);
rotationVector.z = Mathf.Sin(alpha);
transform.Rotate(multiplier * rotationVector * Time.deltaTime);
transform.eulerAngles = new Vector3(transform.eulerAngles.x, 0, transform.eulerAngles.z);
}
Related
I have created a C# script to define spiral motion of an object in a plane in 3D.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class spiralanti : MonoBehaviour
{
float angles;
float radiuss;
float angleSpeed;
float rSpeed;
// Start is called before the first frame update
void Start()
{
angles = 0;
radiuss = 10;
angleSpeed = 150;
rSpeed = 0.7f;
angles = Mathf.Max(0, Mathf.PI);
radiuss = Mathf.Max(0, radiuss);
//float x = 0;
// float y = 0;
// float z = 0;
}
// Update is called once per frame
void Update()
{
angles += Time.deltaTime * angleSpeed;
radiuss -= Time.deltaTime * rSpeed;
if (radiuss == 0)
{
float x = 0;
float y = 0;
float z = 0;
transform.position = new Vector3(x, y, z);
}
else
{
float x = radiuss * Mathf.Cos(Mathf.Deg2Rad * angles);
float z = radiuss * Mathf.Sin(Mathf.Deg2Rad * angles);
float y = 0;
transform.position = new Vector3(x, y, z);
}
}
}
The object spirals very well, but I want to make it stop when it reaches origin and stay there. I have tried the if-else statement as given in the code, but it does not stop. Instead it becomes an outward spiral from an inward spiral.
Please help me with the code.
First of all: Never use == for comparing two float values.
Due to floating point imprecision the value might not exactly match the other one even if logically you would think so.
Example Unity uses if
10f / 10f != 1f
since sometimes this could be something like 1.00000001 or 0.999999999.
IF you want to check exact values rather use Mathf.Approximately
if(Mathf.Approximately(a,b))
which basically equals
if(Mathf.Abs(a-b) <= Mathf.Epsilon)
and then secondly your
radiuss -= Time.deltaTime * rSpeed;
allows overshooting so if before running this the radiuss is already < Time.deltaTime * rSpeed you end up with a negative value which is not exactly == 0 but maybe -0.00000001 or less so you never get into the if block.
So you could either simply use
if(radius <= 0)
{
transform.position = Vector3.zero;
}
...
or you could definitely make sure it is not below 0 and do
radius = Mathf.Max(0, radius);
if(Mathf.Approximately(radius, 0))
{
transform.position = Vector3.zero;
}
...
I am trying to build a trajectory arc that would predict the trajectory path of the object, the drag and shoot seem fine but the arc is not working. initially I used an arrow for showing the direction of the movement of the object but later I tried to do the same using an array which would store 2 points and would keep updating after every iteration and it would result in an arc since I used the equations of motion to predict the positions after each frame.
***
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class movement: MonoBehaviour
{
public float velocity;
float time;
float x;
float y;
float tt;
float g;
Vector2 force;
public float power = 2.0f;
Vector3 startpoint;
Vector3 endpoint;
Camera cam;
public Vector2 maxpower;
public Vector2 minpower;
public Rigidbody2D rb;
Vector3 currentposition;
Vector3 sp;
LineRenderer lr;
int resolution = 10;
Vector3 newpoint;
// Start is called before the first frame update
void Start()
{
time = 0f;
g = Mathf.Abs(Physics2D.gravity.y);
cam = Camera.main;
lr = GetComponent<LineRenderer>();
}
// Update is called once per frame
void Update()
{
time += Time.deltaTime;
x = gameObject.transform.position.x + velocity * time;
tt = time * time;
y = gameObject.transform.position.y + (g * tt) / 2f;
if(Input.GetMouseButtonDown(0))
{
startpoint = cam.ScreenToWorldPoint(Input.mousePosition);
startpoint.z = 5;
}
if(Input.GetMouseButton(0))
{
sp = new Vector3(gameObject.transform.position.x, gameObject.transform.position.y, 5);
currentposition = cam.ScreenToWorldPoint(Input.mousePosition);
currentposition.z = 5;
LineRenderer(sp);
}
if (Input.GetMouseButtonUp(0))
{
endpoint = cam.ScreenToWorldPoint(Input.mousePosition);
endpoint.z = 5;
force = new Vector2(Mathf.Clamp(startpoint.x - endpoint.x, minpower.x, maxpower.x), Mathf.Clamp(startpoint.y - endpoint.y, minpower.y, maxpower.y));
rb.AddForce(force * power, ForceMode2D.Impulse);
x = x + velocity * time;
y = y + (g * tt) / 2f;
EndLine();
}
}
public void LineRenderer(Vector3 p)
{
lr.positionCount = resolution;
Vector3 arc = p;
for(int i=0;i<resolution;i++)
{
newpoint = calculate(arc, i / (float)resolution);
lr.SetPosition(i, newpoint);
arc = newpoint;
}
}
public Vector3 calculate(Vector3 point, float t)
{
point.x += velocity * t;
point.y += 0.5f * g * t * t;
return point;
}
public void EndLine()
{
lr.positionCount = 0;
}
}
***
This the code, any help is appreciated.
A bug that I see is your delta-time:
You call Calculate(arc, i/resolution), with i and resolution both being integers.
The parameter might be float time, but C# will first calculate i/resolution as an integer division, then convert the result to float. The result will be zero as long as i is less than resolution.
Change it to: i/(float)resolution to force a floating-point division.
I wrote this code in Unity3D that should rotate an object in a circle, that's the case except that the starting position is not taken into account.
I do not understand why the function written in start is not taken into account for the position
public class RotationCircuit : MonoBehaviour
{
float timeCounter = 0;
float speed;
float width;
float height;
private float startPosY;
private float startPosX;
private float startPosZ;
void Start()
{
speed = 1;
width = 4; //largueur
//height = 1; //hauteur
startPosX = transform.position.x;
startPosY = transform.position.y;
startPosZ = transform.position.z;
float y = GetComponent<Transform>().position.y;
float x = GetComponent<Transform>().position.x;
float z2 = GetComponent<Transform>().position.z;
transform.position = new Vector3(x, y, z2);
}
void Update()
{
timeCounter += Time.deltaTime * speed;
float x2 = Mathf.Cos(timeCounter) * width;
//float y2 = Mathf.Sin(timeCounter) * height; //utile pour faire des haut et bas
float y2 = GetComponent<Transform>().position.y;
float z2 = GetComponent<Transform>().position.z;
transform.position = new Vector3(x2, y2, z2);
}
}
in general you should use transform.position instead of GetComponent<Transform>().position
Then your code block
float y = transform.position.y;
float x = transform.position.x;
float z2 = transform.position.z;
transform.position = new Vector3(x, y, z2);
does change absolutely nothing ... you get the current position, store it in local variables and write back exactly the same position ...
Btw they also have the same values you already stored in
startPosX = transform.position.x;
startPosY = transform.position.y;
startPosZ = transform.position.z;
later you never use those values at any point.
The same thing in Update
float x2 = Mathf.Cos(timeCounter) * width;
float y2 = transform.position.y;
float z2 = transform.position.z;
transform.position = new Vector3(x2, y2, z2);
only changes the x component of the position which is calculated by
Mathf.Cos(timeCounter) * width;
which doesn't take the initial transform.position.x or startPosX into account at any point.
I don't exactly know how you want to take the start position into account but it looks like it would be something like this:
// Little hint: By making those fields serialized
// you can adjust those values directly in the Inspector
// especially while running the Game without having to recompile everytime
[SerializedField] private float speed = 1;
[SerializedField] private float width = 4;
[SerializedField] private float height = 1;
private float timeCounter = 0;
private Vector3 startPosition;
private void Start()
{
// you can simply store the Vector3 position
// no need to store each component individually
startPosition = transform.position;
}
private void Update()
{
timeCounter += Time.deltaTime * speed;
var x = Mathf.Cos(timeCounter) * width;
var y = Mathf.Sin(timeCounter) * height;
// from the startPosition move x right and y up
transform.position = startPosition + Vector3.right * x + Vector3.up * y;
}
That the object in the beginning jumps once namely width to the right is obviously related to the Mathf.Cos which is 1 for the start time 0.
So I have this function attached to a sphere and in inverse one attached to another. They are rigged to emit a trail and the game object they are orbiting around is a sphere which is locked at 0,0,0. This is my code so far :
float t = 0;
float speed;
float width;
float height;
int cat = 0;
public GameObject orbit; //the object to orbit
// Use this for initialization
void Start()
{
speed = 2;
width = 5;
height = 2;
InvokeRepeating("test", .001f, .009f);
}
void test()
{
t += Time.deltaTime * speed;
Vector3 orbitv = orbit.transform.position;
float inc = .0000000001f;
inc += inc + t;
float angmom = .00001f;
angmom = angmom + t;
float x = orbitv.x + Mathf.Cos(t);
float z = orbitv.z + inc; //+ (Mathf.Cos(t)*Mathf.Sin(t));
float y = orbitv.y + Mathf.Sin(t);
transform.position = new Vector3(x, y, z);
}}
Which does this:
Instead of moving in the z direction exclusively, I'd like them to continue their current rotation, but in a circle around the sphere at 0,0,0 while staying at the same y level. Anyone have any ideas how I can do this?
Edit: This is what I'm trying to do:
Here's some code I cooked up for you.
All the movement is achieved with basic trigonometric functions and some easy vector math.
To tackle problems like these, try to break things down like I did with dividing the movement into circular/up-down & sideways. This lets you create the ring effect.
Adding more intertwined waves should be trivial by changing the phase of the oscillations and adding more trails.
public class Orbit : MonoBehaviour {
float t = 0;
public float speed;
public float width;
public float height;
public float radius;
int cat = 0;
public GameObject center; //the object to orbit
public Vector3 offset;
void Update()
{
t = Time.time * speed;
OrbitAround();
AddSideways();
}
void OrbitAround()
{
float x = radius * Mathf.Cos(t);
float y = Mathf.Sin(offset.y * t);
float z = radius * Mathf.Sin(t);
transform.position = new Vector3(x, y, z);
}
void AddSideways()
{
float x = Mathf.Cos(offset.x * t);
Vector3 dir = transform.position - center.transform.position;
transform.position += dir.normalized * x;
}
}
It should give you a trail like this:
You can play around with the Vec3 offset which changes the frequency of the oscillations and essentially lets you choose the number of rings.
Good Sunday Football afternoon everyone,
My issue is that I have a player controller in Unity that I am creating and the player is supposed to move left or right in a circular motion. Well I have created that but I'm having difficulties locating how to make the player move around a fixed circumference that will eventually be changed.
Here's what I got so far, and the code works. C#, unity, using a sphere.
//editable property
float timeCounter = 0;
public float speed;
void Start()
{
//Called at the start of the game
speed = 1;
}
void Update()
{
timeCounter += Input.GetAxis("Horizontal") * Time.deltaTime * speed; // multiply all this with some speed variable (* speed);
float x = Mathf.Cos(timeCounter) ;
float y = Mathf.Sin(timeCounter) + 6;
float z = 0;
transform.position = new Vector3(x, y, z);
}
void FixedUpdate()
{
//Called before preforming physics calculations
}
}
Assuming you want the player moving at constant linear speed (and that I understood what you want), I would do something like that:
float playerAngle = 0; // the angular position of the player
float playerSpeed = 0.5; // the linear speed of the player
float radius = 1; // the radius of the circle
void Update()
{
playerAngle += Input.GetAxis("Horizontal") * Time.deltaTime * speed / radius;
float x = radius * Mathf.Cos( playerAngle ) ;
float y = radius * Mathf.Sin( playerAngle ) + 6;
float z = 0;
transform.position = new Vector3(x, y, z);
}