Is there some way to have dynamic skybox? I want to make day night cycle but I need to change skyboxes - ideally with fading out and in animation
Skyboxes are really just materials. You can see its properties in the inspector by going to Window > Lighting > Settings and clicking the Material.
You can modify these properties with the SetFloat function. For example, if I can use the following script to pulse the exposure:
using UnityEngine;
public class SkyboxPulse : MonoBehaviour
{
public float pulseRate = 0.2f;
void Update()
{
float exposure = RenderSettings.skybox.GetFloat("_Exposure");
if (exposure < 0.1 || exposure > 1.9)
pulseRate = -pulseRate;
RenderSettings.skybox.SetFloat("_Exposure", exposure + pulseRate * Time.deltaTime);
print(RenderSettings.skybox.GetFloat("_Exposure"));
}
}
This script accesses and modifies the variables set in the shader "Skybox/Procedural". Warning: Whenever you terminate the skybox, it will remain the same exposure--it won't reset like other objects do after play mode.
Related
I don't know how to get a certainly value from the opacity of my gameobject. I wanna do a laser, so I did an animation of my laser going from 0 to 230, and then back to 0. I want it to make damage only if it's in 230 of opacity but I don't know how ;(. Can somebody help me? this is a part of my animation
Color internally is stored as float values 0 to 1.
So assuming you have access to your object it would probably be something like e.g.
public class DamageController : MonoBehaviour
{
// Here you drag in the according object
[SerializeField] private Renderer renderer;
// Due to imprecision I would go one lower just to be sure
private float targetAlpha = 229f/255f;
private void Update ()
{
if(renderer.material.color.a >= targetAlpha)
{
// However you deal damage
DealDamage (amountPerSecond * Time.deltaTime);
}
}
}
However, checking the alpha isn't actually necessary!
You have an animation anyway so you can also simply have the component reduced like
public class DamageController : MonoBehaviour
{
private void Update ()
{
// However you deal damage
DealDamage (amountPerSecond * Time.deltaTime);
}
}
And now simply additionally animate the enabled state of this component!
Make it disabled by default and only enable it within the animation during the desired period.
Trying to create simple endless moving platform with 3 cubes of scale 70 on z(Player will not move forward, will just move left/right). The RepositionPlatform script is attached to each platform/cube which is responsible for movement and checks the z position of each platform and if it is <= -100.0f, then position is changed to (0,0,200.0f).
Problem is sometimes there is a little gap between the platforms(cubes) or there is a little overlap which I don't want.
Platforms should be placed one after each other without any gap or overlap!!!
Can anyone help find the issue looking at the script or suggest any other better way ?
The script below is attached to 3 platform game objects!!!
public class RepositionPlatform : MonoBehaviour
{
private GameObject platformGO;
[SerializeField]
private float speed;
// Start is called before the first frame update
void Start()
{
platformGO = this.gameObject;
Debug.Log("In RepositionPlatform Start method - "+ platformGO.name);
}
// Update is called once per frame
void Update()
{
Debug.Log("In RepositionPlatform Update Method- " + platformGO.name);
platformGO.transform.Translate(Vector3.back * Time.deltaTime * speed);
Transform platformTransform = platformGO.transform;
if(platformTransform.position.z <= -100.0f)
{
platformTransform.position = new Vector3(0,0,200.0f);
}
}
}
Probably because speed is a floating point value. You should read up on them if you haven't already.
Long story short, you aren't accounting for how far below -100 the value might have gone, you're just resetting it.
If you translate it instead, you will preserve any extra distance beyond -100 that the transform might have gone.
Try this instead:
If (transform.position.z < -100){
transform.Translate(new Vector3(0,0,200));
}
Edit
Should be Z value, not X
What breaks is the scrubbing slider, it recognises a click, but it does not move. I have interactable enable.
I'm having to reimport all assets to get it to work again but even now this isn't a sure bet it'll fix it.
This code was working perfectly fine about a week ago, I've made little changes to it since.
A lot of it is commented so I can learn that different parts of the code. Feel free to delete it if it bothers you.
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class NewAnimController : MonoBehaviour {
public Slider scrubSlider; //This is the slider that controls the current position of the animation. Values have to be 0 to 1 for normalized time of the animation, called later in the script
public Slider speedSlider; //This is the slider that controls the playback speed of the animation
public Animator animator; //Animator that is attached to the model that we are looking to control the animation of
public float playbackSpeedAdjustment = 0.5f; //This is a variable that can be easily adjusted to change the total playback speed of the animation. If it's too fast make smaller and vice versa
public Text currentDateText;
public int monthsInProject;
private float rememberTheSpeedBecauseWeMightNeedIt; //Float needed to keep the speed of the animation between pausing and playing
public void Update()
{
float animationTime = animator.GetCurrentAnimatorStateInfo(0).normalizedTime; //float a new value animationTime that is equal to the animators animation state then converted to normalized time
//Debug.Log("animationTime (normalized) is " + animationTime); //logging the normalized time to be able to store it for the scrubbing slider. Doesn't need to be logged for this to work, good to log it to make sure that it's working
scrubSlider.value = animationTime; //making the slider value equal to the now logged normalized time of the animation state
}
public void ScrubSliderChanged(float ScrubSliderchangedValue) // this value has to be floated so that the scrubbing slider can be attached to in the inspector to be able to change the current frame of the animation
{
animator.Play("Take 001", -1, scrubSlider.normalizedValue);
}
public void SpeedSliderChanged(float SpeedSliderchangedValue) //value is floated to be able to change the speed of the animation playback
{
animator.speed = speedSlider.normalizedValue * playbackSpeedAdjustment; // here the speed is multiplied by the adjustment value set in the editor just in case the playback speed needs to be changed outside of normalized values
}
public void UserClickedPauseButton()
{
if (animator.speed > 0f)
{
// we need to pause animator.speed
rememberTheSpeedBecauseWeMightNeedIt = animator.speed;
animator.speed = 0f;
}
else
{
// we need to "unpause"
animator.speed = rememberTheSpeedBecauseWeMightNeedIt;
}
}
public void UserClickedBackButton()
{
scrubSlider.value = scrubSlider.value - (1f / monthsInProject);
}
public void UserClickedForwardButton()
{
scrubSlider.value = scrubSlider.value + (1f / monthsInProject);
}
public void UserClickedStartButton()
{
scrubSlider.value = 0;
}
public void UserClickedEndButton()
{
scrubSlider.value = 1;
}
}
Many thanks for all your help.
I'm pretty sure the problem is this. In Update you are doing something like this:
scrubSlider.value = animationTime
that means that every frame, "NO MATTER WHAT", YOU ARE SETTING THE SLIDER POSITION, to, where the animation is. If the user is trying to move the slider - you are moving it right back, that same frame!
It's not so easy to solve this problem. Unity did not include a trivial built-in function for this. You need a separate script which sits on the slider which determines whether or not the handle is being held down. You have to use the OnPointerDown and OnPointerUp handlers.
How to use pointer handlers in modern Unity:
Step one, make this small script called Teste.cs
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Collections;
public class Teste:MonoBehaviour, IPointerDownHandler, IPointerUpHandler
{
public Slider theSlider;
public bool sliderIsBeingHeldDown;
public void OnPointerDown(PointerEventData data)
{
sliderIsBeingHeldDown = true;
Debug.Log("holding down!");
}
public void OnPointerUp(PointerEventData data)
{
sliderIsBeingHeldDown = false;
Debug.Log("holding up!");
}
}
Don't forget the declaration...
Teste:MonoBehaviour, IPointerDownHandler, IPointerUpHandler
rather than the usual MonoBehavior.
Drag that script on to your UI.Slider.
Note that in general these only work when they are "on" the thing in question.
Run, and try clicking up and down on the slider button - check the console. It works right? Now you have to use that variable inside NewAnimController
(1) Add a public variable to NewAnimController,
public Teste teste;
(2) Be sure to drag to connect that variable in Inspector
(3) Now you can refer to teste.sliderIsBeingHeldDown to see if that slider is being held down. So instead of doing this every frame...
scrubSlider.value = animationTime;
you will have to do this every frame...
if (teste.sliderIsBeingHeldDown)
Debug.Log("don't try to work against the user!");
else
scrubSlider.value = animationTime;
I hope that works! I think that's the simplest way to know when the slider is being held-down.
You really chose a difficult project for your first project! Hell!
It's worth noting that you could also put the slider-adjusting code (I mean to say your actual code for the scrubber) "inside" the script that is actually on the slider -- but I wouldn't worry about that for now. Your solution as stands is good.
Note depending on how you implement it, you may need to make it pause more elegantly when you hold down the slider handle, but before moving the slider handle. To achieve this, one approach is arrange to call UserClickedPauseButton() or a similar concept, when, the Down/Up routines shown here in "Teste", are called. Conversely you could just not bother with ScrubSliderChanged, and instead do the whole job inside code that runs whenever the handle is "down".
(In general, you'd almost certainly use UnityEvent here to make a solid reusable solution for a slider such as this for use with something like a scrubber.)
I have just updated Unity to version 5.2.1 from 5.0.0 this morning and I experienced a few problems. After Unity translated the game to work for the new version, I tested the game. Everything worked fine, except that when I shot a bullet in my game, they would stick to the walls instead of bouncing off of them, but only at certain angles and distances. It was like the bullet was so fast that it skipped hitting the collider and got stuck inside of the collider. That would make a little bit of sense, but the weird part is that I have a C# script for slow motion in the game. Whenever I turn the slow motion on and then turn it off again, the problem with bullets sticking goes away. I cannot seem to figure out what is causing the problem and it definitely wasn't there before I updated the software. Can anyone help me out with this? Thanks. I'll post the bullet script and the slow motion script below. The bullet is instantiated inside the player script by the way.
Bullet Script:
using UnityEngine;
using System.Collections;
public class Bullet : MonoBehaviour {
public float bulletSpeed;
public float bulletOpacity;
public bool fadeOut;
Animator anim;
Rigidbody2D rigidbod;
SpriteRenderer spriterend;
public GameObject player;
public float aimRotation;
// Use this for initialization
void Start () {
anim = GetComponent<Animator> ();
rigidbod = GetComponent<Rigidbody2D> ();
spriterend = GetComponent<SpriteRenderer> ();
rigidbod.velocity = transform.right * bulletSpeed;
rigidbod.gravityScale = 0;
bulletOpacity = 1;
}
// Update is called once per frame
void Update () {
Destroy (gameObject, 3f);
spriterend.color = new Color (1f, 1f, 1f, bulletOpacity);
if (fadeOut == true)
bulletOpacity -= 0.03f;
if (bulletOpacity <= 0)
Destroy (gameObject);
aimRotation = player.GetComponent<Player> ().aimRotation;
}
void OnTriggerEnter2D (Collider2D bulletHit) {
/*if (bulletHit.gameObject.layer == LayerMask.NameToLayer ("vulnerableLayer")) {
}*/
rigidbod.gravityScale = 1;
rigidbod.drag = 1;
fadeOut = true;
}
}
Slow Motion Script:
using UnityEngine;
using System.Collections;
public class SlowMotion : MonoBehaviour {
public float currentLongevity = 0f;
public float slowAmount = 0.2f;
public float normalTime = 1f;
public float slowLongevity = 0.4f;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if (Input.GetMouseButtonDown (1)) {
Time.fixedDeltaTime = 0.0f * Time.timeScale;
if (Time.timeScale == normalTime)
Time.timeScale = slowAmount;
}
if (Time.timeScale == slowAmount) {
currentLongevity += Time.deltaTime;
}
if (currentLongevity > slowLongevity) {
currentLongevity = 0;
Time.timeScale = normalTime;
}
}
}
Since you indicated that the 'weird' bullet behavior ceases after the SlowMotion script is run, I would suggest that the issue has to do with setting Time.fixedDeltaTime as you are doing in the Update() method of the SlowMotion script. This is also supported by your later comment that the 'weird' behavior no longer appears when you set the rigidBody2D's collision detection to continuous (the bullet's RigidBody2D I assume).
Continuous RididBody2D collision detection enables determining if contact occurred between updates, where as Discrete collision detection registers a collision during a physics update. In your SlowMotion script, the following line (in the Update() method) sets fixedDeltaTime to zero:
Time.fixedDeltaTime = 0.0f * Time.timeScale;
Since Time.fixedDeltaTime is the interval in seconds at which physics and other fixed frame rate updates are performed, there must be some minimum value at which the frame rate is realistically run, (0.0 cannot be an actual frame-rate update interval). When Time.fixedDeltaTime == 0.0, Unity may use a default minimum value or use this to indicate that frame updates run as often as possible, (though I have not tested this). Since the Bullet script calls Update() rather than FixedUpdate(), there is no guarantee that the actual interval between the frame updates is uniform. I suspect that when you run the SlowMotion script, and set Time.fixedDeltaTime to 0.0, Unity runs with the smallest possible frame update interval and following this, it does render the expected bullet behavior.
One way to test this would be to set your initial Time.fixedDeltaTime to 0.0 in the editor (and your collision detection behavior back to discrete for the bullet's RididBody2D).
To set Time Manager fixedDeltaTime in the editor: main menu -> Edit -> Project Settings -> Time
If you find a fixedDeltaTime that works, you can set this in the editor and retrieve the initial value in your SlowMotion script in the Awake() method to initialize the base fixedDeltaTime. I would not recommend using fixedDeltaTime == 0.0 since there is no indication in the documentation of a consistent behavior for a time interval of 0.0 and it may be bound more to the underlying hardware and could result in more unexpected behavior.
Hope this helps, cheers!
I am trying to slow down and ultimately stop it, i have a script that slows down timeScale however with that my player using mecanim also slows down.
I have created a TimeController.cs
that will allow me to keep track of time by having a alternative deltaTime as the player can use for variable,
public class TimeController : MonoBehaviour {
private float oldTimeSinceStart;
public float deltaTime;
void LateUpdate () {
float timeSinceStart = Time.realtimeSinceStartup;
deltaTime = timeSinceStart - oldTimeSinceStart;
oldTimeSinceStart = timeSinceStart;
if (Input.GetButton("BulletTime"))
{
if (Time.timeScale > 0.01)
{
Time.timeScale -= 0.004f;
}
}
else
{
if (Time.timeScale < 1)
{
Time.timeScale += 0.01f;
}
}
}
}
From this point i thought about using Animator Update to set the mecanim logic driven speed for player speed and animation speed, however i dont seem to be able,
When using Animator.Update(MyTimeController.deltaTime);
It seems to run at variable speed, as if the Animator has a second input somewhere.
is there away around this? can you isolate the timeScale from the player/mecanim and have it look at another Time class for input variables?
So time slows down for the world but not the player, think clockstoppers!
As Felype mentioned, you can use Animator Component, I usually get the Animator component and then use <animator_object>[<animation_clip_object.name>].speed. For speed, value of 1 means normal speed.
Acording to Unity Documentation there's this animation speed property in the animator object:
https://docs.unity3d.com/Documentation/ScriptReference/Animator-speed.html
Try using
<yourgameobjecthere>.getComponent<Animator>().speed = Time.timescale; right after you set the time scale.
I'm not sure the animation speed is applied correctly during an animation tho.