How can I change the light intensity value from 3.08 back to 1.0 after 2 seconds. I have comment in my code for additional info
public class Point_LightG : MonoBehaviour {
public Light point_light;
float timer;
// Use this for initialization
void Start () {
point_light = GetComponent<Light>();
}
// Update is called once per frame
void Update () {
timer -= Time.deltaTime;
lights();
}
public void lights()
{
if (timer <= 0)
{
point_light.intensity = Mathf.Lerp(1.0f, 3.08f, Time.time);
timer = 2f;
}
// so after my light intensity reach 3.08 I need it to gradually change back to 1.0 after 2 seconds.
}
}
To lerp between two values, just use the Mathf.PingPong with the Mathf.Lerp and provide a speed the lerp should happen at.
public Light point_light;
public float speed = 0.36f;
float intensity1 = 3.08f;
float intensity2 = 1.0f;
void Start()
{
point_light = GetComponent<Light>();
}
void Update()
{
//PingPong between 0 and 1
float time = Mathf.PingPong(Time.time * speed, 1);
point_light.intensity = Mathf.Lerp(intensity1, intensity2, time);
}
If you prefer to use a duration instead of a speed variable to control the light intensity then you that is better done with a coroutine function and just the Mathf.Lerp function with a simple timer. The lerp can then be done within x seconds.
IEnumerator LerpLightRepeat()
{
while (true)
{
//Lerp to intensity1
yield return LerpLight(point_light, intensity1, 2f);
//Lerp to intensity2
yield return LerpLight(point_light, intensity2, 2f);
}
}
IEnumerator LerpLight(Light targetLight, float toIntensity, float duration)
{
float currentIntensity = targetLight.intensity;
float counter = 0;
while (counter < duration)
{
counter += Time.deltaTime;
targetLight.intensity = Mathf.Lerp(currentIntensity, toIntensity, counter / duration);
yield return null;
}
}
Usage
public Light point_light;
float intensity1 = 3.08f;
float intensity2 = 1.0f;
void Start()
{
point_light = GetComponent<Light>();
StartCoroutine(LerpLightRepeat());
}
Related
using UnityEngine;
using UnityEditor;
using System.Collections;
public class LerpExample : MonoBehaviour
{
[Header("Animation-Curve")]
public AnimationCurve slideCurve;
public Transform finalPosition;
private Vector3 initialPosition;
public float time;
private void Awake()
{
initialPosition = transform.position;
}
private void Start()
{
StartCoroutine(MoveObject());
}
private void Update()
{
}
private IEnumerator MoveObject()
{
float i = 0;
float rate = 1 / time;
while (i < 1)
{
i += rate * Time.deltaTime;
transform.position = Vector3.Lerp(initialPosition, finalPosition.position, slideCurve.Evaluate(i));
yield return 0;
}
}
}
I'm using animation curves to make the transform start decreasing speed and then when getting close to the target to decrease the speed.
but I ant now to lerp without finalPosition position but with finalPosition as time.
for example, if I will set the time to 7 so the transform will start lerp from its position, and after 7 seconds where ever the transform is reached decrease down the speed back.
The target instead position will be time.
Now it start to slow down near the target after 7 seconds or in 7 seconds for example 7 seconds but I want that it will start to slow down in 7 seconds without a vector3 target just after 7 seconds slow down and stop.
I have this situation :
An object that starts moving by force with a rigidbody on the terrain.
While the object is moving I want the player to start moving too beside the object with the rigidbody.
The player should start moving slowly to max speed than when the other moving object near stops moving the player should slowly slow down to stop.
IN general, I used the SpeedUp and SlowDown methods but they were working fine when I wanted to do it when moving the player forward. The problem is that the parameter "Forward" will move the player only in the forward direction.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Cinemachine;
using FIMSpace.FLook;
public class Rolling : MonoBehaviour
{
public GameObject mainCam;
public CinemachineFreeLook freeLookCamGameplay;
public CinemachineFreeLook freeLookCamPickUp;
public Transform player;
public Transform crate;
public Transform cube;
public Animation anim;
public UnlockCrate unlockCrate;
public float timeToStopRolling;
public float speed;
public float waitBeforeSlowdown;
public float startDrag;
public float endDrag = 50;
public float rotationSpeed;
public static bool hasStopped = false;
private bool crateOpenOnce = false;
private bool alreadyRolling;
private Rigidbody rb;
private Quaternion defaultRotation;
private Animator animator;
private bool startSpeedUp = true;
public float lerpTimeMultiplicator = 0.25f;
private float timeElapsed = 0;
private float lerpDuration = 3f;
private float startValue = 1;
private float endValue = 0;
private float valueToLerp = 0;
private bool triggerOnce = false;
private void Start()
{
rb = GetComponent<Rigidbody>();
defaultRotation = rb.rotation;
animator = player.GetComponent<Animator>();
}
private void Update()
{
var distance = Vector3.Distance(crate.position, player.position);
if (distance < 1.7f && crateOpenOnce == false && unlockCrate.HasOpened())
{
rb.isKinematic = false;
crateOpenOnce = true;
}
if(crateOpenOnce && startSpeedUp)
{
StartCoroutine(SpeedUp());
StartCoroutine(WaitBeforeSlowdown());
startSpeedUp = false;
}
if(animator.GetFloat("Forward") == 0f && startSpeedUp == false &&
triggerOnce == false)
{
triggerOnce = true;
}
}
private IEnumerator Slowdown()
{
while(timeElapsed < lerpDuration)
{
timeElapsed += Time.deltaTime;
valueToLerp = Mathf.Lerp(startValue, endValue, timeElapsed / lerpDuration);
animator.SetFloat("Forward", valueToLerp);
// Yield here
yield return null;
}
}
private IEnumerator SpeedUp()
{
while(timeElapsed < lerpDuration)
{
timeElapsed += Time.deltaTime;
valueToLerp = Mathf.Lerp(endValue, startValue, timeElapsed / lerpDuration);
animator.SetFloat("Forward", valueToLerp);
// Yield here
yield return null;
}
}
private IEnumerator WaitBeforeSlowdown()
{
yield return new WaitForSeconds(13f);
timeElapsed = 0;
StartCoroutine(Slowdown());
}
private void OnCollisionEnter(Collision collision)
{
//NOTE: In general you should go for Tags instead of the name
if (collision.gameObject.name == "Crate_0_0")
{
if (crateOpenOnce)
{
rb.drag = 0f;
// Directly start a routine here (if none is already running)
if (!alreadyRolling) StartCoroutine(RollingRoutine());
}
}
}
private void OnCollisionExit(Collision collision)
{
if (collision.gameObject.name == "Crate_0_0")
{
var brain = mainCam.GetComponent<CinemachineBrain>();
brain.m_DefaultBlend.m_Time = 1f;
freeLookCamGameplay.enabled = false;
freeLookCamPickUp.enabled = true;
}
}
private Vector3 GetRandomDirection()
{
var rnd = Random.insideUnitSphere;
rnd.y = 0;
return rnd.normalized;
}
private IEnumerator RollingRoutine()
{
// Just in case prevent concurrent routines
if (alreadyRolling) yield break;
// Block new routines from starting
alreadyRolling = true;
// Get the random direction for this routine
var rollDirection = GetRandomDirection();
// Roll for the given time within the FixedUpdate call
for (var timePassed = 0f; timePassed < timeToStopRolling; timePassed += Time.deltaTime)
{
// Wait until you are in FixedUpdate
// the code after this is now executed within FixedUpdate
yield return new WaitForFixedUpdate();
rb.AddForce(Vector3.right /*rollDirection*/ * speed * Time.deltaTime);
}
// Wait before slowing down
yield return new WaitForSeconds(waitBeforeSlowdown);
// Do slow down and rotate to default until both conditions are fulfilled
var dragLerpFactor = 0f;
// Store the original drag to reset it later
var defaultDrag = rb.drag;
while (!Mathf.Approximately(rb.velocity.sqrMagnitude, 0) || rb.rotation != defaultRotation)
{
// Again wait until you are in FixedUpdate
yield return new WaitForFixedUpdate();
dragLerpFactor += Time.deltaTime * lerpTimeMultiplicator;
rb.drag = Mathf.Lerp(startDrag, endDrag, dragLerpFactor);
rb.MoveRotation(Quaternion.RotateTowards(rb.rotation, defaultRotation, rotationSpeed * Time.deltaTime));
}
// Just to be sure to end with clean value assign once
rb.rotation = defaultRotation;
rb.drag = defaultDrag;
rb.velocity = Vector3.zero;
hasStopped = true;
Destroy(transform.GetComponent<Rigidbody>());
Destroy(transform.GetComponent<SphereCollider>());
}
}
That is why I'm trying to use the code in the LerpExample script.
The main goal is to move the player slowly to max speed and then slowly to stop beside the rolling t transform in the Rolling script.
fairly new here.
I'm working on a game where I want my fog density to increase. I've succesfully done it, but i want it to increase over time, something like a few seconds or so.
Here is my script:
using UnityEngine;
public class FogScript : MonoBehaviour
{
private void OnTriggerEnter(Collider other)
{
RenderSettings.fogDensity = 0.2f;
}
}
As you can see it's fairly simple. Just need to know how to increase the density over a few seconds instead of the moment it activates.
You can use a Coroutine. They are like temporary little Update methods and by default each frame the next iteration is executed.
// Adjust these via the Inspector in Unity
[SerializeField] private float targetDensity = 0.2f;
[Tooltip(2Fade duration in seconds")]
[SerializeField] private float fadeDuration = 1.0f;
private void OnTriggerEnter(Collider other)
{
// starts the FadeFog routine
StartCoroutine(FadeFog())
}
private IEnumerator FadeFog()
{
var timePassed = 0f;
while(timePassed <= fadeDuration)
{
// a factor from 0 to 1
var factor = timePassed / fadeDuration;
// linear interpolate between from and to with given factor
RenderSettings.fogDensity = Mathf.Lerp(0, targetDensity, factor);
// Let this frame be rendered and continue from here in the next frame
yield return null;
}
}
or since OnTriggerEnter itself may be an IEnumerator you can also directly use
private IEnumerator OnTriggerEnter(Collider other)
{
var timePassed = 0f;
while(timePassed <= fadeDuration)
{
var factor = timePassed / fadeDuration;
RenderSettings.fogDensity = Mathf.Lerp(0, targetDensity, factor);
yield return null;
}
}
void Update(){
fogD += Time.deltaTime * rateOfIncrease;
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Rotate : MonoBehaviour
{
public float xAngle, yAngle, zAngle;
public GameObject[] objectsToRotate;
private bool isRotating = false;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if(isRotating == true)
{
for(int i = 0; i < objectsToRotate.Length; i++)
{
objectsToRotate[i].transform.Rotate(xAngle, yAngle, zAngle);
}
}
}
private void OnMouseDown()
{
isRotating = true;
}
}
For example the first object should start rotating at once.
The second one after 0.3f seconds and the third one after 1 second.
Each object should start rotating at another random time.
All of them should finish after rotating 360 degrees.
Before that I used a Coroutine to rotate a single object.
private void OnMouseDown()
{
if (isRotating == false)
StartCoroutine(Rotate(5));
}
IEnumerator Rotate(float duration)
{
Quaternion startRot = transform.rotation;
float t = 0.0f;
while (t < duration)
{
isRotating = true;
t += Time.deltaTime;
transform.rotation = startRot * Quaternion.AngleAxis(t / duration * 360f, Vector3.up);
yield return null;
}
transform.rotation = startRot;
isRotating = false;
}
You also can use your coroutine. Your code might be something like that:
public Transform[] objectsToRotate;
private void OnMouseDown()
{
foreach (var objectTransform in objectsToRotate)
{
float delay = Random.Range(0.0f, 5.0f);
float duration = 2.0f;
StartCoroutine(Rotate(objectTransform, duration, delay));
}
}
IEnumerator Rotate(Transform objectTransform, float duration, float delay)
{
yield return new WaitForSeconds(delay);
Quaternion startRot = objectTransform.rotation;
float t = 0.0f;
while (t < duration)
{
t += Time.deltaTime;
objectTransform.rotation = startRot * Quaternion.AngleAxis(t / duration * 360f, Vector3.up);
yield return true;
}
objectTransform.rotation = startRot;
}
Delay is simple random but you can adjust it if you want.
I want to move the Camera with a smooth motion so I am writing this script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraScroll : MonoBehaviour {
public GameObject targetCamera;
private bool isScrolling = false;
private Vector3 initialPosition;
private Vector3 scrollTarget;
private float scrollDuration;
private float scrollTick;
private float timeStartedScrolling;
#region Easing
float EasingInOutSine(float time, float start, float change, float duration) {
return -change/2 * (Mathf.Cos(Mathf.PI*time/duration) - 1) + start;
}
float EasingOutSine(float time, float start, float change, float duration) {
dynamic td = time/duration;
return change * Mathf.Sin(td * (Mathf.PI/2)) + start;
}
float EasingInOutBack(float time, float start, float change, float duration) {
float td2 = time/(duration/2.0f);
float s = 1.70158f;
if ((td2) < 1.0f) {
return change/2.0f*(td2*td2*(((s*(1.525f))+1.0f)*td2 - (s*(1.525f)))) + start;
} else {
return change/2.0f*((td2-2.0f)*(td2-2.0f)*(((s*(1.525f))+1.0f)*(td2-2.0f) + (s*(1.525f))) + 2) + start;
}
}
#endregion
void Start() {
if (targetCamera == null) {
targetCamera = GameObject.Find("Main Camera");
}
// Tests
//Scroll(new Vector3(4.0f, 0.0f, -10f), 2f); // seems to be working?
//Scroll(new Vector3(4.0f, 0.0f, -10f), 0.3f); // easing gets cut off
Scroll(new Vector3(4.0f, 0.0f, -10f), 1f); // easing gets cut off
}
void Update() {
if (isScrolling) {
scrollTick += Time.deltaTime;
float s = scrollTick / scrollDuration;
float timeSinceStarted = Time.time - timeStartedScrolling;
float percentageComplete = timeSinceStarted / scrollDuration;
if (percentageComplete > 1.0f) {
isScrolling = false;
Debug.Log("Scrolling ended");
} else {
// time, start, change, duration
var easing = EasingInOutSine(Time.time, 0, Mathf.Clamp01(Time.time*scrollDuration), scrollDuration);
targetCamera.transform.position = Vector3.Lerp(initialPosition, scrollTarget, easing);
}
}
}
void Scroll(Vector3 targetPosition, float duration) {
scrollDuration = duration;
scrollTarget = targetPosition;
initialPosition = targetCamera.transform.position;
timeStartedScrolling = Time.time;
isScrolling = true;
}
}
The problem is that the motion of the camera is cutoff and the easing is not applied properly if the duration is set to be 1 second or lower
I'd like the script to be able to use different easing algorithms in the future and play with deltaTime properly, I am not sure if I am doing it the right way
I think you just need a constant change.
With an increasing change the slow down effect of the easing will be overpowered by the exponential movement caused by the increasing change. This effect is most apparent in low duration movements because it will never reach the value ceiling slower so it will keep speeding up until the end.
Since your using your easing algorithm to output a percentage to throw into a lerp, you probably want to use a change of 1 so that the easing interpolates between 0 and 1.
I have two lights components. First i'm finding both Lights and disable them.
Then I want to enable them when changing some object scale and using the object scaling duration time for the lights dim.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DimLights : MonoBehaviour
{
//Lights Change
public Light[] lightsToDim = null;
public float maxTime;
private GameObject[] myLights;
private float mEndTime = 0;
private float mStartTime = 0;
private void Start()
{
myLights = GameObject.FindGameObjectsWithTag("Light");
mStartTime = Time.time;
mEndTime = mStartTime + maxTime;
LightsState(false);
}
public void LightsState(bool state)
{
foreach (GameObject go in myLights)
{
go.GetComponent<Light>().enabled = state;
}
}
public void LightDim()
{
foreach (Light light in lightsToDim)
{
light.intensity = Mathf.InverseLerp(mStartTime, mEndTime, Time.time);
}
}
}
The second script is scaling some object:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ChangeScale : MonoBehaviour
{
//Scaling change
public GameObject objectToScale;
public float duration = 1f;
public Vector3 minSize;
public Vector3 maxSize;
private bool scaleUp = false;
private Coroutine scaleCoroutine;
//Colors change
public Color startColor;
public Color endColor;
public float colorDuration; // duration in seconds
private void Start()
{
startColor = GetComponent<Renderer>().material.color;
endColor = Color.green;
objectToScale.transform.localScale = minSize;
}
// Use this for initialization
void Update()
{
if (Input.GetKeyDown(KeyCode.F))
{
//Flip the scale direction when F key is pressed
scaleUp = !scaleUp;
//Stop old coroutine
if (scaleCoroutine != null)
StopCoroutine(scaleCoroutine);
//Scale up
if (scaleUp)
{
//Start new coroutine and scale up within 5 seconds and return the coroutine reference
scaleCoroutine = StartCoroutine(scaleOverTime(objectToScale, maxSize, duration));
}
//Scale Down
else
{
//Start new coroutine and scale up within 5 seconds and return the coroutine reference
scaleCoroutine = StartCoroutine(scaleOverTime(objectToScale, minSize, duration));
}
}
if (Input.GetKeyDown(KeyCode.C))
{
StartCoroutine(ChangeColor());
}
}
IEnumerator scaleOverTime(GameObject targetObj, Vector3 toScale, float duration)
{
float counter = 0;
//Get the current scale of the object to be scaled
Vector3 startScaleSize = targetObj.transform.localScale;
while (counter < duration)
{
counter += Time.deltaTime;
targetObj.transform.localScale = Vector3.Lerp(startScaleSize, toScale, counter / duration);
yield return null;
}
}
IEnumerator ChangeColor()
{
float t = 0;
while (t < colorDuration)
{
t += Time.deltaTime;
GetComponent<Renderer>().material.color = Color.Lerp(startColor, endColor, t / colorDuration);
yield return null;
}
}
}
In the second script the ChangeScale i want inside the scaleOverTime method to dim the light using the method LightDim in the DimLights script.
It's not that complicated. You change the scaleOverTime function to work on light by copying it making a new function from it. The only thing to change is the Vector3.Lerp function to Mathf.Lerp function and also targetObj.transform.localScale to targetObj.intensity.
A simple Light dim function:
IEnumerator dimLightOverTime(Light targetObj, float toIntensity, float duration)
{
float counter = 0;
//Get the current intensity of the Light
float startIntensity = targetObj.intensity;
while (counter < duration)
{
counter += Time.deltaTime;
targetObj.intensity = Mathf.Lerp(startIntensity, toIntensity, counter / duration);
yield return null;
}
}
Unfortunately, you are using an array so the function should be made to take an array:
IEnumerator dimLightOverTime(Light[] targetObj, float toIntensity, float duration)
{
float counter = 0;
//Get the current intensity of the Light
float[] startIntensity = new float[targetObj.Length];
for (int i = 0; i < targetObj.Length; i++)
{
startIntensity[i] = targetObj[i].intensity;
}
while (counter < duration)
{
counter += Time.deltaTime;
for (int i = 0; i < targetObj.Length; i++)
{
targetObj[i].intensity = Mathf.Lerp(startIntensity[i], toIntensity, counter / duration);
}
yield return null;
}
}
This prevents having to start new coroutine for each Light and saving some time.
The new Update function:
public Light[] lightsToDim = null;
private Coroutine lightCoroutine;
// Use this for initialization
void Update()
{
if (Input.GetKeyDown(KeyCode.F))
{
//Flip the scale direction when F key is pressed
scaleUp = !scaleUp;
//Stop old coroutine
if (scaleCoroutine != null)
StopCoroutine(scaleCoroutine);
if (lightCoroutine != null)
StopCoroutine(lightCoroutine);
//Scale up
if (scaleUp)
{
//Start new coroutine and scale up within 5 seconds and return the coroutine reference
scaleCoroutine = StartCoroutine(scaleOverTime(objectToScale, maxSize, duration));
lightCoroutine = StartCoroutine(dimLightOverTime(lightsToDim, 1, duration)); ;
}
//Scale Down
else
{
//Start new coroutine and scale up within 5 seconds and return the coroutine reference
scaleCoroutine = StartCoroutine(scaleOverTime(objectToScale, minSize, duration));
lightCoroutine = StartCoroutine(dimLightOverTime(lightsToDim, 0, duration)); ;
}
}
}
Notice the new variable "lightCoroutine". That's used to store the old coroutine just like we did for the scaleCoroutine.