Hello, I started unity recently. I need to find idea to change my 3d object depending on time. We can give an example like building houses in 3d rts game. Their appearance changing with building time.
In 2d from codemonkey example. Its too complicated for me. Can you guys show me the way , give an idea to achieve this?
float buildTickNormalized = buildTick * 1f / buildTickMax;
if (buildTickNormalized >= .3f) spriteRenderer.sprite = GameAssets.i.tower_2;
if (buildTickNormalized >= .6f) spriteRenderer.sprite = GameAssets.i.tower_3;
if (buildTickNormalized >= 1f) spriteRenderer.sprite = GameAssets.i.tower_Built;
You have many ways to do this. You could for example just use the animator. In there you just put keyframes for the change in image, and move the keyframes along a timeline. If you need your object to keep changing, you set the animation to loop.
public class ExampleScript : MonoBehaviour
{
public float timeToChange = 20f;
bool hasChanged = false;
//You need to run it in update so that it'll check every frame
void Update()
{
//If we haven't already changed the image, and the system time is more than my timeToChange...
if (!hasChanged && Time.time > timeToChange)
{
//Do the change here
//The change has happened
hasChanged = true;
}
}
While that solution is perfectly fine for someone starting, is not the best one, as it’ll keep checking forever for every frame if it needs to change the object. Usually what you’ll use instead is a coroutine. Coroutines are more advanced concept, that work like functions but run every frame till they end. Here is an example of how you’ll do it with a coroutine:
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour
{
public float timeBeforeDoingSomething = 10.2f;
//At start you run your coroutine, notice that you need to use StartCoroutine() for that.
void Start()
{
StartCoroutine(WaitAndDoSomething(timeBeforeDoingSomething));
}
//this is the coroutine, the difference with a normal method is that it has a IEnumerator as a return type
private IEnumerator WaitAndDoSomething(float waitTime)
{
//over here it says that the function will wait till the time has completed.
yield return new WaitForSeconds(waitTime);
//Here you do whatever you want.
print("Coroutine ended: " + Time.time + " seconds");
}
}
Actually this code for 2d. I consider to do stuff like this for 3d. Here codemonkey , done the stuff with using ThickTimer etc. but this is really hard to understand for me
@calpolican is coroutine works fine at mobile ? Btw thanks for reply i will try.
Yes, coroutines are computationally inexpensive (well kind of…). The syntax may look scary at first, but they’re really handy for everything that is time related.
The thick timer thing shouldn’t sound scary either. Basically Unity has a public property of the Time class called “time”, hence if you call from any script “Time.time” it’ll give you a float (a decimal number). That float is fed by a built in clock where unity counts the time that has been happening since the beggining of the game. So, it’s very handy to know how much time has run since the start of the game. In the code you provied we don’t see how he defines the variable “buildTick”. But most probably he just defines it as Time.time.
So, basically what’s his code is saying is:
if (timePlayed > certainAmount) { ChangeMyObject’sPicture(); }
The word “normalized” that he uses and that weird division, just means that he’s turning the time to a value between 0 and 1. For example if I can live up to 100 years, and I want to normalize my age (30), I do 30/100, and I get 0.3 as the normalize value. He doesn’t really need to normalize the time, he could have said if (Time.time > 30), were 30 = 30 seconds {Change the picture()}. He just over complicated things.
“spriteRenderer.sprite” is just the image of the object. Basically spriteRenderer is a component that you can check in the inspector and that unity uses to render sprites. And that component/script has a public variable “sprite” where you can hook the image. He’s just telling unity what’s the variable that he want’s to change.
Then he’s just assigning a new picture to it just like you would do in the inspector. The picture he assigns is inside a a script called “GameAssets”. Inside GameAssets, apparently there’s a variable called “i” (probably an object with all the images of the towers). And inside “i”, there’s the variable he wants, called “tower_2”, that holds the reference to the sprite.
Thus spriteRender.sprite = GameAssets.i.tower_2; is just assigning the sprite and specifying what will be that new sprite. That’s really all there is to it. Sometimes programmers make it look more difficult than it really is, but it’s pretty much the same you’d do when you assign something in the inspector. Search the component, then the variable you want to assign it, and then look for the place where the new image is.
Hope that makes it more clear.