How to I make this script stay in day and night longer? - c#

I don't quite understand this code so I am having difficulty modifying it.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SunScript : MonoBehaviour {
public float duration = 1.0F;
public Light lt;
void Start() {
lt = GetComponent<Light>();
}
void Update() {
float phi = Time.time / duration * 0.1f * Mathf.PI;
float amplitude = Mathf.Cos(phi) * 0.5F + 0.5F;
lt.intensity = amplitude;
}
}
This moves the light's intensity up and down in a cycle. However, I would like to have it stay at its brightest and its dimmest for a while before it starts to move back the other direction. How should I do this?

What about replacing Mathf.Cos(phi) one of these functions instead of just a cosine?
Using the equation at the bottom of that page:
float amplitude = Mathf.Sin(Mathf.PI / 2f * Mathf.Cos(phi)) * 0.5f + 0.5f;
For the formula with the b term, you could do this (using extra temp variables to make it a little more readable).
float b = // whatever your b parameter is or have this declared as a class field that you can set in the Unity editor
float cosine = Mathf.Cos(phi);
float numerator = 1f + (b * b);
float denominator = 1f + (b * b * cosine * cosine);
float amplitude = (Mathf.Sqrt(numerator / denominator) * cosine) * 0.5f + 0.5f;

You can also use the Unity AnimationCurve to achieve this:
public class SunScript : MonoBehaviour
{
public float duration = 1.0F;
public AnimationCurve curve;
private Light lt;
void Start()
{
lt = GetComponent<Light>();
}
void Update()
{
lt.intensity = curve.Evaluate((Time.time % duration) / duration);
}
}
Simply make sure your curve is from 0 to 1 following X axis and make it the values you want on the Y axis.
Hope this helps,

Related

FixedUpdate not adding a force to player's Rigidbody

I am working on a movement script for my 2D platformer, and this code stopped working as soon as I moved the AddForce command to FixedUpdate rather than Update. It will still print the Debug.Log, and it will print the correct value of the Movment Variable, but the Rigidbody does not move at all when I use the arrow keys in-game.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class playerMovment : MonoBehaviour
{
float hInput;
float moveSpeed = 3;
float accel = 1f;
float decel;
float Movment;
[SerializeField] Rigidbody2D rb;
// Start is called before the first frame update
void Start()
{
decel = accel * -1f;
}
// Update is called once per frame
void Update()
{
calcMovment();
}
void calcMovment()
{
if (Input.GetKey(KeyCode.LeftShift))
{
hInput = Input.GetAxis("Horizontal") * moveSpeed * 1.5f;
}
else
{
hInput = Input.GetAxis("Horizontal") * moveSpeed;
}
float targetSpeed = hInput * moveSpeed;
//Debug.Log(targetSpeed);
float speedDiff = targetSpeed - rb.velocity.x;
//Debug.Log(speedDiff);
float accelRate = (Mathf.Abs(targetSpeed) > 0.01f) ? accel : decel;
//Debug.Log(accelRate);
Movment = Mathf.Pow(Mathf.Abs(speedDiff) * accelRate, 0.5f) * Mathf.Sign(speedDiff);
//Debug.Log(Movment);
}
void FixedUpdate()
{
Debug.Log(Movment);
rb.AddForce(Movment * Vector2.right);
//Debug.Log(rb.velocity.x);
}
}
The problem begins in these 2 lines of code:
float accelRate = (Mathf.Abs(targetSpeed) > 0.01f) ? accel : decel;
Movment = Mathf.Pow(Mathf.Abs(speedDiff) * accelRate, 0.5f) * Mathf.Sign(speedDiff);
accelRate becomes negative in one moment which leads to the negative base in in the Mathf.Pow() the second line, and according to the official MSDN documentation (here), if x < 0 but not NegativeInfinity; y is not an integer, NegativeInfinity, or PositiveInfinity -> NaN, and in your case x is Mathf.Abs(speedDiff) * accelRate and it's negative

How to rotate around an object without using unity's built-in functions?

i want to rotate a cube around a 1x1 pipe with arrow keys. (left and right).
The problem is i cannot use built-in functions which sets transform's position and location directly. (Such as transform.lookAt, transform.Rotate or transform.RotateAround). Because I need the vector values of rotation's euler and position for multiple stuff before i modify the value of the transform i want to rotate.
I tried different techniques but no luck so far.
I tried using sin-cos for rotating but could not figure out how to make it work for both rotation and position.
_timer += Time.deltaTime * _larvaSpeed;
float x = -Mathf.Cos(_timer) * distanceBetweenCenter;
float y = Mathf.Sin(_timer) * distanceBetweenCenter;
Here is what i want to achieve. By pressing right or left, move and rotate the object around the pipe.
The result i want. (If i pressed right arrow key a litte bit).
I would appreciate any help. Thank you!
here is the solution using circle mathematics and I strongly recommended not use it, it's just to understand the circular move using circle equation as #FaTaLL ask in the comments
Circle equation...
(x1 - x2)^2 + (y1 - y2)^2 = r^2
x1, y1 is the cube position
x2, y2 is the pipe position
r is the distance between cube and pipe;
using UnityEngine;
public class Rotating : MonoBehaviour
{
public GameObject pipe;
public float Delta;
Vector3 nextpos;
bool compareY;
bool next;
int switchx;
float storeVarAxis;
float x, y, r;
private void Start()
{
next = true;
switchx = 1;
compareY = true;
x = transform.position.x - pipe.transform.position.x;
y = transform.position.y - pipe.transform.position.y;
storeVarAxis = y;
r = Mathf.Sqrt(x * x + y * y);
}
private void Update()
{
if (next)
{
if (compareY == true)
{
y -= Delta * Time.deltaTime;
if (y <= -storeVarAxis)
{
y = -storeVarAxis;
compareY = false;
switchx = -1;
}
}
else
{
y += Delta * Time.deltaTime;
if (y >= storeVarAxis)
{
y = storeVarAxis;
compareY = true;
switchx = 1;
}
}
float v = r * r - y * y;
x = Mathf.Sqrt(Mathf.Abs(v));
nextpos = new Vector3(pipe.transform.position.x + x * switchx, pipe.transform.position.y + y, transform.position.z);
next = false;
}
transform.position = Vector3.MoveTowards(transform.position, nextpos, 1f * Time.deltaTime);
if(Vector3.Distance(transform.position, nextpos) < .05) transform.position = nextpos;
if (transform.position.x.Equals(nextpos.x) && transform.position.y.Equals(nextpos.y)) next = true;
}
}
well, the recommended way is using this simple script
using UnityEngine;
public class Rotating : MonoBehaviour
{
public float speed;
public GameObject pipe;
float r, angle;
Vector3 startpos;
private void Start()
{
r = Mathf.Abs(transform.position.y - pipe.transform.position.y);
angle = 0;
transform.position = pipe.transform.position;
startpos = transform.position;
}
void Update()
{
angle = angle + speed * Time.deltaTime;
transform.rotation = Quaternion.EulerAngles(0,0, angle);
transform.position = startpos + (transform.rotation * new Vector3(r, 0, 0));
}
}
I think Quaternion * Vector3 is what you are looking for. Luckily the box's rotation in its own local coordinates is the same rotation you need to apply to the box's position.
public float speed; //how fast to rotate
public float radius; //radius of the cylinder
public float angle; //angle around it
void Update()
{
if (Input.GetKey(KeyCode.LeftArrow))
{
angle = angle + speed * Time.deltaTime;
}
if (Input.GetKey(KeyCode.RightArrow))
{
angle = angle - speed * Time.deltaTime;
}
//figure out the rotation (from euler angles i guess??)
var quat = Quaternion.EulerAngles(new Vector3(0, angle, 0));
//ok uh what is the box position?? lets just multiply
var unrotated_position = new Vector3(radius, 0, 0);
var rotated_position = quat * unrotated_position;
this.transform.position = rotated_position;
//oh yea and also rotate the box in its own local coordinates
this.transform.rotation = quat;
}

Multiple GameObjects Instantiated Between Two Angles

I am trying to spawn n GameObjects between angles equally spaced out.
Ideally, I'd like to be able to adjust the "cone" to so that the enemy can shoot in any direction, in any density.
Can someone see what I have done wrong?
These are enemy projectiles. That I am trying "scatter shot". Think of the dragon from Level 1 in NES Zelda:
Though, I am not entirely sure what is happening with my implementation.
Projectile.cs
public Vector2 moveDirection = Vector2.zero;
public float moveSpeed = 4.0f;
private void FixedUpdate()
{
_body.MovePosition(transform.position + (new Vector3(moveDirection.x, moveDirection.y, 0).normalized) * (moveSpeed * Time.deltaTime));
}
MultiShooter.cs
public GameObject projectileObject;
public Transform projectileEmitter;
[Range(2, 10)] public int numToShoot = 3;
[Space]
[Range(0, 360)] public int angle = 30;
[Range(1, 50)] public float rayRange = 10.0f;
[Range(0, 360)] public float coneDirection = 180;
public void OnStartShooting()
{
for (int i = 1; i <= numToShoot; i++)
{
var projectile = Instantiate(projectileObject);
projectile.transform.position = projectileEmitter.position;
var projectileScript = projectile.GetComponent<Projectile>();
projectileScript.moveDirection = DirFromAngle(((angle / i) + coneDirection)* pointDistance, rayRange);
projectile.SetActive(true);
}
}
public Vector3 DirFromAngle(float angleInDegrees, float range)
{
return Quaternion.AngleAxis(angleInDegrees, Vector3.forward) * transform.up * range;
}
Editor script to show the lines.
private void OnSceneGUI()
{
MultiShooter fow = (MultiShooter)target;
Handles.color = Color.magenta;
Vector3 upDirection = fow.DirFromAngle((-fow.angle / 2.0f) + fow.coneDirection, fow.rayRange);
Vector3 dwDirection = fow.DirFromAngle((fow.angle / 2.0f) + fow.coneDirection, fow.rayRange);
Handles.DrawLine(fow.projectileEmitter.position, upDirection);
Handles.DrawLine(fow.projectileEmitter.position, dwDirection);
}
For the ith object, the fraction of angular distance from one side of the range to the other can be expressed with the formula i/(numToShoot-1) for values ofnumToShoot > 1. If numToShoot == 1, you can just have the percentage be 50% to shoot right in the middle of the range.
Your drawing method seems to work with coneDirection ± angle/2, so we can subtract .5 from this angular percentage to express it in terms of angular distance from the center of the range.
Then we can use the same math as the drawing method with coneDirection + angle percentage * angle range:
public void OnStartShooting()
{
for (int i = 0; i < numToShoot; i++)
{
var projectile = Instantiate(projectileObject);
projectile.transform.position = projectileEmitter.position;
var projectileScript = projectile.GetComponent<Projectile>();
float anglePercentage;
if (numToShoot == 1)
anglePercentage = 0f;
else
anglePercentage = (float)i/(numToShoot-1f) - .5f;
projectileScript.moveDirection = DirFromAngle(
coneDirection
+ anglePercentage * angle, rayRange);
projectile.SetActive(true);
}
}

How to calculate the trajectory of bullet in Unity2D?

I'm doing the 2D game with bullets moving in parabola, but before I shoot the projectile I want to be able to calculate its trajectory.
float velocity = Mathf.Min(Mathf.Max(distance, 1), 2.5f);
float cos = Mathf.Cos( (gameObject.transform.localEulerAngles.z + 90) * Mathf.Deg2Rad);
float sin = Mathf.Sin( (gameObject.transform.localEulerAngles.z + 90) * Mathf.Deg2Rad);
newGO.GetComponent<Rigidbody2D>().AddForce(velocity * new Vector3(cos, sin))
This code adds the rigidbody2d to my bullet (newGO). I try to count a point after 1 sec of flying using it:
Debug.Log(new Vector3(source.transform.position.x + velocity * 1 * cos, source.transform.position.y + velocity * sin * 1 + Physics2D.gravity.y * 0.5f * 1));
Unfortunately it doesn't return the correct result. What should I do?
Thanks for help and sorry for my English.
I think being a projectile you should use Rigidbody2D.velocity to set the initial velocity of the projectile rather than Rigidbody2D.AddForce. (Although the documentation does not recommend)
This simple script predicts where the attached object will be in a time determined by the variable "timeLimit" and moves a "target" gameobject to that point.
public class Velocity : MonoBehaviour {
public GameObject target;
private float HoriInitialSpeed = 5;
private float VertInitialSpeed = 5;
private float timeLimit = 2;
private float timeElapsed=0;
void Start ()
{
float HoriPredict = HoriInitialSpeed * timeLimit;
float VertiPredict = VertInitialSpeed* timeLimit + (0.5f * Physics2D.gravity.y * timeLimit * timeLimit);
target.transform.Translate(HoriPredict, VertiPredict,0);
GetComponent<Rigidbody2D>().velocity = new Vector2(HoriInitialSpeed, VertInitialSpeed);
}
void Update () {
timeElapsed += Time.deltaTime;
if(timeElapsed >= timeLimit)
{
//stop the bullet
GetComponent<Rigidbody2D>().velocity = new Vector2(0, 0);
GetComponent<Rigidbody2D>().gravityScale = 0;
}
}
}
Note: the bullet and the target must be in the same point inicially

Rotate object around parent object in Unity

I am new to unity and am trying to understand how the code works but am having a problem with my simple project.
I have a Star and a Planet. The planet is a child of the Star like so:
Star¬
Planet
I added a component C# script to Planet that is meant to make it rotate around the Star. But when i press play the planet is not moving.
This is my script:
using UnityEngine;
using System.Collections;
public class Orbit : MonoBehaviour {
public float rotateSpeed = 5.0f;
public float orbitSpeed = 1.0f;
private Vector3 pos;
void Start(){
//get parent object position
pos = transform.root.gameOject;
}
void Update() {
// planet to spin on it's own axis
transform.Rotate (transform.up * rotateSpeed * Time.deltaTime);
// planet to travel along a path that rotates around the sun
transform.RotateAround (pos, Vector3.up, orbitSpeed * Time.deltaTime);
}
}
I am not sure what my mistake is. And am hoping some one can help.
Side question, given i want to eventually have more than one planet, is it efficient to have a component script for every individual planet to rotate or is there a more automative way to do it such as iterate through all the planets in one go?
Unit Version 5.3.2f1
You should consider oscillation. Whether you use sin or cos does not really matter somehow. You will get the same shape but one will start at 0 as sin(0) = 0 and the other starts at 1 as cos(0) = 1.
One nice feature of sin and cos is that the result is lerping and clamped between -1 and 1. We can get a variable that will constantly go from 1 to -1 and back to 1 and so on.
The following is entirely based on basic trigonometry and unit circle
void Update ()
{
transform.localPosition= new Vector3(Mathf.Cos (Time.time ),0,Mathf.Sin (Time.time));
}
this is based on the trig equation:
x = cos(2 * pi * k + t)
y = sin(2 * pi * k + t)
The 2 * PI * k part is shorten to Time.time, result is the same, you would only need those for extra precision if you were to reproduce a real situation.
Other case you want to use the full equation is if you need to control the time it takes for a revolution:
private float twoPi = Mathf.PI * 2f;
void Update ()
{
transform.localPosition= new Vector3(Mathf.Cos (twoPi * Time.time ),0,Mathf.Sin (twoPi * Time.time));
}
This will take 1sec to do the full revolution.
When you use Cos for one, you have to use Sin for the other or your object will not spin around the parent.
You can add distance to spread the planet apart from the star:
private float twoPi = Mathf.PI * 2f;
[SerializeField]private float amplitude = 2.0f;
void Update()
{
float x = amplitude * Mathf.Cos (twoPi * Time.time );
float z = amplitude * Mathf.Sin (twoPi * Time.time );
transform.localPosition= new Vector3(x,0,z);
}
All spinning items will rotate at the same frequency of 1 so you should be able to provide different frequencies to each planet:
private float twoPi = Mathf.PI * 2f;
[SerializeField]private float amplitude = 2.0f;
[SerializeField]private float frequency = 2.0f;
void Update()
{
float x = amplitude * Mathf.Cos (twoPi * Time.time * frequency);
float z = amplitude * Mathf.Sin (twoPi * Time.time * frequency);
transform.localPosition= new Vector3(x,0,z);
}
if you give different frequencies to x and z within the same object, the child will not spin entirely around but will have a horseshoe shape. Frequency could be assimilated to speed as it will define how fast one full revolution is performed.
You can then fully control the period (this is the math term for speed), a period is the time between two peaks on the sinusoidal (the movement can be flattened to a sinusoidal, two actually, x and z). The relation between frequency and period is
frequency = 1 / period;
So the greater the frequency, the shorter the period. If you want your revolution to take 2sec => frequency = 1 / 2 => 0.5. If you need 2 minutes, frequency is always in seconds so 120sec => frequency = 1 / 120 = 0.0083f;
All your planet will rotate at the same position around the star, that is they will all start from left or right so you can apply a phase. This is the k from the initial equation and it is not multiplied but added:
private float twoPi = Mathf.PI * 2f;
[SerializeField] private float amplitude = 2.0f;
[SerializeField] private float periodInSec = 120;
private float frequency = 2.0f;
[SerializeField] private float phase = 0.5f;
void Start()
{
frequency = 1 / periodInSec;
}
void Update()
{
float x = amplitude * Mathf.Cos (twoPi * Time.time * frequency + phase);
float z = amplitude * Mathf.Sin (twoPi * Time.time * frequency + phase);
transform.localPosition= new Vector3(x,0,z);
}
And if you need to provide an elliptic shape (which is the case of most astres), you simply give a different amplitude to x and z:
[SerializeField]private float amplitudeX = 2.0f;
[SerializeField]private float amplitudeZ = 3.0f;
[SerializeField] private float periodInSec = 120;
private float frequency = 2.0f;
[SerializeField] private float phase = 0.5f;
void Start()
{
frequency = 1 / periodInSec;
}
void Update()
{
float x = amplitudeX * Mathf.Cos (twoPi * Time.time * frequency + phase);
float z = amplitudeZ * Mathf.Sin (twoPi * Time.time * frequency + phase);
transform.localPosition= new Vector3(x,0,z);
}
If you need to have many planets around one star and you want the planet to move on all three axis. That is, one spin "flat" while another one spin with a rotation, the easiest is to make the planet a child of a star child.
-Star
-Container
-Earth
-Container
-March
The containers are at (0,0,0) and you can give each container a different rotation and the child planet will rotate on its own ellipse around the star. Just make sure they don't collide, billions of lives at stake.
public Vector3 pos and then Drag the Star in the Inspector.
much easier.

Categories