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);
}
Related
I can't put a limit on the rotation on the Y axis and also I would have my player look in the direction he is moving , I have already tried to put Mathf.calmp for the Touchfiled.Touchdist.y (camera Y axis) but it doesn't work I don't know where the problem comes from but I would like to solve it so please help me.
here is my code :
public FloatingJoystick joystick;
public TouchField touchField;
public GameObject FocusPoint;
[HideInInspector] public CharacterController characterController;
[HideInInspector] public Vector3 motionVector , gravityVector, RelativeVector;
[Header("Player Settings")]
[Range(0,6)] public float PlayerSpeed = 2.5f;
[Range(0, 100)] public float Sensivility = 50;
[Range(0, 0.5f)] public float groundClearance;
private float gravityForce = -9.18f;
private float gravityPower = -9.8f;
private float JumpValue = 9.8f;
private float TurnDiraction;
private void Start()
{
characterController = GetComponent<CharacterController>();
}
private void Update()
{
Movment();
CameraController();
if (characterController.isGrounded)
{
print("Grounded");
}
}
public void CameraController()
{
RelativeVector = transform.InverseTransformPoint(FocusPoint.transform.position);
RelativeVector /= RelativeVector.magnitude;
TurnDiraction = (RelativeVector.x / RelativeVector.magnitude);
FocusPoint.transform.eulerAngles = new Vector3(FocusPoint.transform.eulerAngles.x + touchField.TouchDist.y, FocusPoint.transform.eulerAngles.y, 0) ;
FocusPoint.transform.parent.Rotate(transform.up * touchField.TouchDist.x * Sensivility * Time.deltaTime);
}
public void Movment()
{
if (characterController.isGrounded && gravityVector.y < 0)
{
gravityVector.y = -2;
}
gravityVector.y += gravityPower * Time.deltaTime;
characterController.Move(gravityVector * Time.deltaTime);
if (characterController.isGrounded)
{
motionVector = transform.right * joystick.Horizontal + transform.forward * joystick.Vertical;
characterController.Move(motionVector * PlayerSpeed * Time.deltaTime);
if(joystick.Vertical > 0)
{
transform.Rotate(transform.up * TurnDiraction * 800 * Time.deltaTime);
FocusPoint.transform.parent.Rotate(transform.up * -TurnDiraction * 800 * Time.deltaTime);
}
}
}
You rotate in 2 steps, and in the second and in the second one you do:
FocusPoint.transform.parent.Rotate(transform.up * touchField.TouchDist.x * Sensivility * Time.deltaTime);
If you rotate the parent respect the y axis all the children turn along with the rotation given to the parent in the hierarchy.
So it does not matter that you clamp the y rotation in the previous step
FocusPoint.transform.eulerAngles = new Vector3(FocusPoint.transform.eulerAngles.x + touchField.TouchDist.y, FocusPoint.transform.eulerAngles.y, 0);
if the gameobject is going to be rotated respect y axis after.
Try rotating at once according to your limits, or take into account those limits for all the rotation steps.
On the other hand, gravity is neither a power, nor a force, but an acceleration :)
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'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);
}
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.