How can I lerp a vector3 by time not by position? - c#

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.

Related

How can I make the animation match when the NPC walks left or right?

I have some NPCs that randomly walk within a range, however when I can't determine when they are walking left or right so the animation looks wrong.
I have a function called "Decrease" that warns inside the terminal when the object walks decreases or increases its position, but this function does not work as it should
So...
How can I make the animation match when the NPC walks left or right?
Here is my NPC configuration:
Here is my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NPCController : MonoBehaviour
{
private float waitTime;
private Animator _animator;
private SpriteRenderer _renderer;
public Transform moveSpot;
private bool _facingRight = true;
public float lastXVal;
public float speed;
public float startWaitTime;
public float minX;
public float maxX;
public float minY;
public float maxY;
void Awake()
{
_animator = GetComponent<Animator>();
_renderer = GetComponent<SpriteRenderer>();
}
void Start()
{
waitTime = startWaitTime;
moveSpot.position = new Vector2(Random.Range(minX, maxX), Random.Range(minY, maxY));
}
void Update()
{
transform.position = Vector2.MoveTowards(transform.position, moveSpot.position, speed * Time.deltaTime);
if (Vector2.Distance(transform.position, moveSpot.position) < 0.2f)
{
//Change animation state
if (waitTime <= 0)
{
_animator.SetBool("Walk", true);
moveSpot.position = new Vector2(Random.Range(minX, maxX), Random.Range(minY, maxY));
waitTime = startWaitTime;
}
else
{
_animator.SetBool("Walk", false);
_animator.SetBool("Idle", true);
waitTime -= Time.deltaTime;
}
}
}
public void Decrease()
{
if (transform.hasChanged)
{
if (transform.position.x < lastXVal)
{
//Update lastXVal
lastXVal = transform.position.x;
Debug.Log("Decreased!");
}
else if (transform.position.x > lastXVal)
{
//Update lastXVal
lastXVal = transform.position.x;
Debug.Log("Increased");
}
transform.hasChanged = false;
}
}
}
You can use dot product to calculate the direction of travel.
Vector2 moveDirection = (moveSpot.position - transform.position).normalized;
float dotValue = Vector2.Dot(Vector2.right, moveDirection)
// if dotValue is 1 then you are moving right and if dotValue is -1 you are moving left

Unity grappling more like Tarzan

I am trying to make a grappling hook more fluent but as of right now it is very choppy and does not have the right feel. It currently makes a line and pulls the player there. I have not tried anything yet because I am not even sure we're to start on fixing this. Here is all the grappling code below. `using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(SFPSC_PlayerMovement))] // PlayerMovement also requires Rigidbody
public class SFPSC_GrapplingHook : MonoBehaviour
{
public bool IsGrappling
{
get { return isGrappling; }
}
private SFPSC_PlayerMovement pm;
private Rigidbody rb;
private int segments;
private void Start()
{
segments = rope.segments;
pm = this.GetComponent<SFPSC_PlayerMovement>();
rb = this.GetComponent<Rigidbody>();
}
private bool isGrappling = false;
private void Update()
{
if (crossHairSpinningPart != null)
{
// we need 2 raycasts bc w/ 1 you can grapple through colliders which isn't good
if (Physics.Raycast(SFPSC_FPSCamera.cam.transform.position, SFPSC_FPSCamera.cam.transform.forward, out hitInfo, maxGrappleDistance, layerMask))
{
hitName = hitInfo.collider.name;
if (Physics.Raycast(SFPSC_FPSCamera.cam.transform.position, SFPSC_FPSCamera.cam.transform.forward, out hitInfo, maxGrappleDistance))
{
if (hitName != hitInfo.collider.name)
goto _else;
crossHairSpinningPart.gameObject.SetActive(true);
crossHairSpinningPart.Rotate(Vector3.forward * crossHairSpinSpeed * Time.deltaTime);
goto _out;
}
}
_else:
crossHairSpinningPart.gameObject.SetActive(false);
}
_out:
if (!isGrappling)
{
if (Input.GetKeyDown(SFPSC_KeyManager.Grapple))
Grapple();
return;
}
else
{
if (!Input.GetKey(SFPSC_KeyManager.Grapple))
UnGrapple();
GrappleUpdate();
return;
}
}
[Header("Properties")]
public float maxGrappleDistance = 100.0f;
public SFPSC_Rope rope;
public float maximumSpeed = 100.0f;
public float deceleration = 2500.0f; // This is how much the player is going to decelerate after stopped grappling
public float deceleratingTime = 1.4f; // This is the time the decelerating is going to act on the player after stopped grappling
public RectTransform crossHairSpinningPart;
public float crossHairSpinSpeed = 200.0f;
public float distanceToStop = 2.0f;
public LayerMask layerMask;
public float grappleCooldown = 1.0f;
private bool isBlocked = false;
private Transform location; // the grappled location
private RaycastHit hitInfo;
private string hitName;
public void Grapple()
{
if (isBlocked)
return;
// we need 2 raycasts bc w/ 1 you can grapple through colliders which isn't good
if (Physics.Raycast(SFPSC_FPSCamera.cam.transform.position, SFPSC_FPSCamera.cam.transform.forward, out hitInfo, maxGrappleDistance, layerMask))
{
hitName = hitInfo.collider.name;
if (Physics.Raycast(SFPSC_FPSCamera.cam.transform.position, SFPSC_FPSCamera.cam.transform.forward, out hitInfo, maxGrappleDistance))
{
if (hitName != hitInfo.collider.name)
return;
// We create a GameObject and we parent it to the grappled object.
// If we don't parent it to the object and the object moves the player is stuck only on one location instead of the moving object.
location = new GameObject().transform;//Instantiate(new GameObject(), hitInfo.point, Quaternion.identity).transform;
location.position = hitInfo.point;
location.parent = hitInfo.collider.transform;
if (decelerateTimer != 0.0f)
StopCoroutine(Decelerate());
pm.DisableMovement();
// Rope attaching
rope.segments = (int)((hitInfo.distance / maxGrappleDistance) * segments);
rope.Grapple(transform.position, hitInfo.point);
rb.useGravity = false;
isGrappling = true;
}
}
}
private Vector3 grappleForce;
public void UnGrapple()
{
if (!isGrappling)
return;
if (location != null)
Destroy(location.gameObject);
if (decelerateTimer == 0.0f)
StartCoroutine(Decelerate());
else
decelerateTimer = 0.0f;
pm.EnableMovement();
// Rope detaching
rope.UnGrapple();
Invoke("UnblockGrapple", grappleCooldown);
rb.useGravity = true;
isGrappling = false;
}
private void UnblockGrapple()
{
isBlocked = false;
}
private float decelerateTimer = 0.0f, max;
private IEnumerator Decelerate()
{
WaitForEndOfFrame wfeof = new WaitForEndOfFrame();
max = deceleratingTime * Mathf.Clamp01(targetDistance / 10.0f) * Mathf.Clamp01(rb.velocity.magnitude / 30.0f);
for (; decelerateTimer < max; decelerateTimer += Time.deltaTime)
{
rb.AddForce(-rb.velocity.normalized * deceleration * (1.0f - decelerateTimer / max) * Mathf.Clamp01(rb.velocity.sqrMagnitude / 400.0f) * Time.deltaTime, ForceMode.Acceleration);
yield return wfeof;
}
decelerateTimer = 0.0f;
}
private Vector3 dir;
private float speed = 0.0f, targetDistance;
private void GrappleUpdate()
{
if (location == null)
return;
targetDistance = Vector3.Distance(transform.position, location.position);
rope.segments = (int)((targetDistance / maxGrappleDistance) * segments);
dir = (location.position - transform.position).normalized;
rb.velocity = Vector3.Lerp(rb.velocity, dir * maximumSpeed * Mathf.Clamp01(targetDistance / (4.0f * distanceToStop)), Time.deltaTime);
// Rope updating
rope.UpdateStart(transform.position);
rope.UpdateGrapple();
}
private Vector3 ClampMag(Vector3 vec, float maxMag)
{
if (vec.sqrMagnitude > maxMag * maxMag)
vec = vec.normalized * maxMag;
return vec;
}
}
`
Try using FixedUpdate instead of Update for physics based work (basically all of your code in Update right now). Update is dependent on your computer's clock speed and refresh rate (more or less), and gets called at fairly irregular intervals, because the next update is called in the next frame, after the present frame has finished processing. FixedUpdate makes it frame-rate independent.
Also, you can cap your framerate using Application.targetFrameRate and cap it to a decent FPS.
You could also multiply your movement with Time.deltaTime for smoother movement, although this is a standard practice and yet debatable for use as a smoothing value.

How can I add a slowdown effect when object is getting close to a target?

using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
using UnityEngine.AI;
public class Waypoints : UnityEngine.MonoBehaviour
{
public List<Transform> waypoints = new List<Transform>();
public float movementSpeed = 5.0f;
public float slowdownSpeed = 1f;
public float rotationSpeed = 2.0f;
public float waypointDistance = 0.1f;
public float slowdownDistance = 7f;
public bool moveBackward = false;
public bool moveLoop = false;
public bool includeTransformPosition = false;
private Transform targetWaypoint;
private int targetWaypointIndex = 0;
private int lastWaypointIndex;
private bool includeTransform = true;
private GameObject go;
// Use this for initialization
void Start()
{
go = new GameObject();
go.transform.position = transform.position;
if (moveBackward && waypoints.Count > 2)
{
lastWaypointIndex = 0;
targetWaypoint = waypoints[waypoints.Count - 1];
}
else
{
lastWaypointIndex = waypoints.Count - 1;
targetWaypoint = waypoints[targetWaypointIndex]; //Set the first target waypoint at the start so the enemy starts moving towards a waypoint
}
}
// Update is called once per frame
void Update()
{
if (includeTransformPosition && includeTransform)
{
waypoints.Insert(0,go.transform);
includeTransform = false;
}
else
{
if (includeTransformPosition == false)
{
waypoints.Remove(go.transform);
includeTransform = true;
}
}
float movementStep = movementSpeed * Time.deltaTime;
float rotationStep = rotationSpeed * Time.deltaTime;
Vector3 directionToTarget = targetWaypoint.position - transform.position;
Quaternion rotationToTarget = Quaternion.LookRotation(directionToTarget);
transform.rotation = Quaternion.Slerp(transform.rotation, rotationToTarget, rotationStep);
float distance = Vector3.Distance(transform.position, targetWaypoint.position);
CheckDistanceToWaypoint(distance);
if(slowdownDistance < 7f)
{
movementSpeed -= movementSpeed * Time.deltaTime;
}
transform.position = Vector3.MoveTowards(transform.position, targetWaypoint.position, movementStep);
}
void CheckDistanceToWaypoint(float currentDistance)
{
if (currentDistance <= waypointDistance)
{
targetWaypointIndex++;
UpdateTargetWaypoint();
}
}
void UpdateTargetWaypoint()
{
if (targetWaypointIndex > lastWaypointIndex)
{
targetWaypointIndex = 0;
}
targetWaypoint = waypoints[targetWaypointIndex];
}
}
At this part I'm trying to slowdown the movement speed but it's not changing the speed at all :
if(slowdownDistance < 7f)
{
movementSpeed -= movementSpeed * Time.deltaTime;
}
What I'm trying to do when the transform start to move increase the speed slowly to some constant speed and then when the transform is getting closer to the waypoint then if the distance is less then 7 decrease the speed down to 0 so the object will stop at the waypoint then after X seconds move back the transform to the transform original position(go.transform) with the same increasing decreasing speed movement.
but I can't even make the first simple slowdown.
you set slowdownDistance to 7, i dont see you ever reducing it below 7 but you have if statement that executes only it it is under 7 do you reduce it elsewhere?
You probably planned to compare slowdownDistance to some distance rather than comparing it to its own value.
If you want to slow down the whole scene you could use a:
while(distance < range)
{
Time.timeScale = 1 - (distance / value);
}
with this you can change the value and so when the player come close time will be slown down mostly.
With the same idea you can do:
while(distance < range)
{
speed = speedInitial - (distance / value);
}
If you want to change just the speed of the player

How can I iterate through the array and start rotating the cubes from the array at random intervals?

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.

How can i dim a light component?

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.

Categories

Resources