How to solve a starting position problem? - c#

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.

Related

Variable not assigning on void Start() (noob question)

I have a code to make a cube move back and forth within a certain range of it's original placed position.
The script is directly on the cube and it does move, but around 0,0,0 coordinates, not it's original position.
Here is my code:
using UnityEngine;
public class ObstacleResonator : MonoBehaviour
{
public float xspeed = 0f;
public float yspeed = 0f;
public float zspeed = 0f;
public float xrange = 0f;
public float yrange = 0f;
public float zrange = 0f;
float StartX;
float StartY;
float StartZ;
Vector3 desiredPosition;
void Start()
{
// this is what i think is the problem, the variables are not getting assigned
float StartX = transform.position.x;
float StartY = transform.position.y;
float StartZ = transform.position.z;
}
// Update is called once per frame
void Update()
{
// the following is to make it reverse once it is out of range in any of the axes
if (transform.position.x > xrange + StartX)
{
xspeed = -xspeed;
}
if (transform.position.x < -xrange + StartX)
{
xspeed = -xspeed;
}
if (transform.position.y > yrange + StartY)
{
yspeed = -yspeed;
}
if (transform.position.y < -yrange + StartY)
{
yspeed = -yspeed;
}
if (transform.position.z > zrange + StartZ)
{
zspeed = -zspeed;
}
if (transform.position.z < -zrange + StartZ)
{
zspeed = -zspeed;
}
// the following actually moves the cube
desiredPosition.x = transform.position.x + xspeed * Time.deltaTime;
desiredPosition.y = transform.position.y + yspeed * Time.deltaTime;
desiredPosition.z = transform.position.z + zspeed * Time.deltaTime;
transform.position = desiredPosition;
}
}
There probably is a more compact way to write it.
The cube is moving around 0,0,0 instead of it's original transform position. I tried assigning the StartX, StartY, StartZ values manually, and it worked perfectly, but they just dont seem to get assigned by on the start.
The problem is that you declare NEW variables within the Start() function, they go out of scope as soon as the function is executed. You don't update the class variables.
Use this instead:
void Start()
{
StartX = transform.position.x;
StartY = transform.position.y;
StartZ = transform.position.z;
}

how to make a predictive trajectory arc while aiming?

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.

Unity3D How to constrain rotation without rigidbody?

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);
}

How to make two objects inversely orbiting a point do so in a curve? Unity, C#

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.

How to adjust player movement around a circumference

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);
}

Categories

Resources