This shows you the differences between two versions of the page.
pjv:laboratoare:2023:03 [2023/10/10 11:40] alexandru.gradinaru created |
pjv:laboratoare:2023:03 [2024/10/07 10:48] (current) alexandru.gradinaru |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ===== Transformari de baza ===== | + | ===== 3. Transformari de baza ===== |
==== Cerinte ===== | ==== Cerinte ===== | ||
- | TBU | + | Creati o scena care sa contina mai multe zone de spawn (minim 3). Fiecare zona va contine un grid 5x5 de obiecte scriptate, alese aleator din urmatoarele grupuri: |
+ | * obiecte care se rotesc incontinuu | ||
+ | * obiecte care sar incontinuu | ||
+ | * obiecte care se maresc o data la 3 secunde, pana la un maxim de dimensiune, apoi revin la forma initiala | ||
+ | |||
+ | <hidden> | ||
+ | |||
+ | * o tinta care se roteste in permanenta | ||
+ | * un obiect de tip tun care | ||
+ | * poate lansa proiectile | ||
+ | * poate roti teava sus-jos pe taste | ||
+ | * proiectilul | ||
+ | * este lansat la fiecare apasare a tastei SPACE | ||
+ | * este lansat din varful tevii tunului, pe directia inainte, si are comportament fizic (gravitatie, forta etc.) | ||
+ | * | ||
+ | </hidden> | ||
==== Documentatie video ===== | ==== Documentatie video ===== | ||
- | TBU | + | Inregistrare pe MS Teams |
==== Documentatie extinsa text ===== | ==== Documentatie extinsa text ===== | ||
- | TBU | + | |
+ | > **time.deltatime** | ||
+ | |||
+ | In unity, Time.deltaTime will provide you **time in seconds it took to complete the last frame (Read Only)**. This can be used to make your game frame independent. | ||
+ | |||
+ | When you multiply any value with Time.deltaTime you essentially express: I want to move this object 10 meters per second instead of 10 meters per frame. | ||
+ | |||
+ | For more details please visit "Edit -> Project Settings -> Time" **OR** From scripting, check out the [Time](http://docs.unity3d.com/ScriptReference/Time.html) class. | ||
+ | |||
+ | <code c#> | ||
+ | |||
+ | public class ExampleClass : MonoBehaviour { | ||
+ | void Update() { | ||
+ | float translation = Time.deltaTime * 10; | ||
+ | transform.Translate(0, 0, translation); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | > **Difference between Update, Fixed Update and Late Update.** | ||
+ | |||
+ | **Update:** (Most things) | ||
+ | |||
+ | * Update is called once per frame from every script in which it is defined. Calling of Update function is dependent on the frame rate. | ||
+ | * The time interval to call update is not fixed; it depends on how much time required to complete the individual frame. | ||
+ | |||
+ | **FixedUpdate:**(Physics things) | ||
+ | |||
+ | * FixedUpdate is independent of the frame rate. The time interval is to call FixedUpdate is constant; as it is called on a reliable timer. | ||
+ | * FixedUpdate can be called multiple times per frame if frame rate is low or it may not be called per frame if the frame rate will be high. | ||
+ | * All the physics related calculations and updates are called immediately after **FixedUpdate**. So, its good to handle all physics related calculation inside FixedUpdate. | ||
+ | |||
+ | **LateUpdate:**(After update) | ||
+ | |||
+ | * LateUpdate is also called per frame. It is called after all other Update functions. | ||
+ | * This is useful to ensure all other Update related calculation is complete and other dependent calculation can be called. | ||
+ | * For example, if you need to integrate a third-person camera to follow any object; then it should be implemented inside the LateUpdate. It is make sure that camera will track the object after its movement and rotation update. | ||
+ | |||
+ | > **GameObject Manipulation** | ||
+ | |||
+ | <code c#> | ||
+ | /* Create a GameObject */ | ||
+ | Instantiate(GameObject prefab); | ||
+ | Instantiate(GameObject prefab, Transform parent); | ||
+ | Instantiate(GameObject prefab, Vector3 position, Quaternion rotation); | ||
+ | /* In Practice */ | ||
+ | Instantiate(bullet); | ||
+ | Instantiate(bullet, bulletSpawn.transform); | ||
+ | Instantiate(bullet, Vector3.zero, Quaternion.identity); | ||
+ | Instantiate(bullet, new Vector3(0, 0, 10), bullet.transform.rotation); | ||
+ | |||
+ | newobj = Instantiate(objTemplate) as ObjType; | ||
+ | |||
+ | //from prefab - prefab must be in Resources folder | ||
+ | newobj1 = Instantiate(Resources.Load("enemy")); | ||
+ | |||
+ | // Instantiate the projectile at the position and rotation of this transform | ||
+ | Rigidbody projectile; | ||
+ | Rigidbody clone; | ||
+ | clone = Instantiate(projectile, transform.position, transform.rotation); | ||
+ | |||
+ | enemyOrc = Instantiate(Orc) as Enemy; | ||
+ | |||
+ | /* Destroy a GameObject */ | ||
+ | Destroy(gameObject); | ||
+ | |||
+ | /* Finding GameObjects */ | ||
+ | GameObject myObj = GameObject.Find("NAME IN HIERARCHY"); | ||
+ | GameObject myObj = GameObject.FindWithTag("TAG"); | ||
+ | childObject=parentObject.GetChild("child_name"); | ||
+ | parentObject.GetChild("child_name").GetComponent<SpriteRenderer>().sprite = image; | ||
+ | |||
+ | /* Accessing Components */ | ||
+ | Example myComponent = GetComponent<Example>(); | ||
+ | AudioSource audioSource = GetComponent<AudioSource>(); | ||
+ | Rigidbody rgbd = GetComponent<Rigidbody>(); | ||
+ | GetComponent<SpriteRenderer>().sprite = image; //set image in child component | ||
+ | GetComponent<Text>().text = '123' //set text | ||
+ | |||
+ | /* Transforms - can be accessed using the `transform` attribute */ | ||
+ | Vector3 objectPosition = gameObject.transform.position; | ||
+ | gameObject.transform.position = new Vector3(posX, posY, posZ); | ||
+ | transform.Translate(Vector3.up * Time.deltaTime, Space.World); | ||
+ | transform.Rotate(Vector3.up * Time.deltaTime, Space.World); | ||
+ | |||
+ | /* Activate - can hide or how an element from the scene*/ | ||
+ | myObject.SetActive(false); // hide | ||
+ | myObject.SetActive(true); // show | ||
+ | |||
+ | GetComponent<BoxCollider>().enabled = false; // hide component | ||
+ | |||
+ | </code> | ||
+ | |||
+ | > **Vector Quick Reference** | ||
+ | |||
+ | X = Left/Right Y = Up/Down Z = Forward/Back | ||
+ | |||
+ | <code c#> | ||
+ | Vector3.right /* (1, 0, 0) */ Vector2.right /* (1, 0) */ | ||
+ | Vector3.left /* (-1, 0, 0) */ Vector2.left /* (-1, 0) */ | ||
+ | Vector3.up /* (0, 1, 0) */ Vector2.up /* (0, 1) */ | ||
+ | Vector3.down /* (0, -1, 0) */ Vector2.down /* (0, -1) */ | ||
+ | Vector3.forward /* (0, 0, 1) */ | ||
+ | Vector3.back /* (0, 0, -1) */ | ||
+ | Vector3.zero /* (0, 0, 0) */ Vector2.zero /* (0, 0) */ | ||
+ | Vector3.one /* (1, 1, 1) */ Vector2.one /* (1, 1) */ | ||
+ | float length = myVector.magnitude /* Length of this Vector */ | ||
+ | myVector.normalized /* Keeps direction, but reduces length to 1 */ | ||
+ | |||
+ | </code> | ||
+ | |||
+ | > **Time Variables** | ||
+ | |||
+ | <code c#> | ||
+ | /* The time in seconds since the start of the game */ | ||
+ | float timeSinceStartOfGame = Time.time; | ||
+ | |||
+ | /* The scale at which the time is passing */ | ||
+ | float currentTimeScale = Time.timeScale; | ||
+ | /* Pause time */ | ||
+ | Time.timeScale = 0; | ||
+ | |||
+ | /* The time in seconds it took to complete the last frame */ | ||
+ | /* Use with Update() and LateUpdate() */ | ||
+ | float timePassedSinceLastFrame = Time.deltaTime; | ||
+ | |||
+ | /* The interval in seconds at which physics and fixed frame rate updates are performed */ | ||
+ | /* Use with FixedUpdate() */ | ||
+ | float physicsInterval = Time.fixedDeltaTime; | ||
+ | |||
+ | </code> | ||
+ | |||
+ | > **Random values** | ||
+ | |||
+ | <code c#> | ||
+ | Random.Range(-10.0f, 10.0f) | ||
+ | Random.Range(0, 8); | ||
+ | </code> | ||
+ | |||
+ | > **Coroutines** | ||
+ | |||
+ | While Coroutines seem to work like threads at first glance, they actually aren't using any multithreading. They are executed sequentially until they `yield`. Coroutine might seem like it is a thread, but coroutines execute within the main thread. | ||
+ | |||
+ | The difference between a coroutine and a thread is very much like the difference between [cooperative multitasking](https://en.wikipedia.org/wiki/Cooperative_multitasking) and [preemptive multitasking](https://en.wikipedia.org/wiki/Preemption_(computing)). Note that a coroutine runs on the main thread and must voluntarily yield control back to it, if control is not yielded (this is where the coroutine must be _cooperative_) then your coroutine will hang your main thread, thus hanging your game. | ||
+ | |||
+ | The disadvantage of not doing "real" multithreading is that you can not use coroutines to parallelize CPU-intense calculations over multiple CPU cores. With the release of Unity 2017, it is now possible to use a new C# feature called [**async-await**](https://blogs.msdn.microsoft.com/appconsult/2017/09/01/unity-coroutine-tap-en-us/) for our asynchronous methods instead. This comes with a lot of nice features compared to coroutines. | ||
+ | |||
+ | **Let's look at a simple example. Given the following coroutine:** | ||
+ | |||
+ | <code c#> | ||
+ | public class AsyncExample : MonoBehaviour | ||
+ | { | ||
+ | IEnumerator Start() | ||
+ | { | ||
+ | Debug.Log("Waiting 1 second..."); | ||
+ | yield return new WaitForSeconds(1.0f); | ||
+ | Debug.Log("Done!"); | ||
+ | } | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | **The equivalent way to do this using async-await would be the following:** | ||
+ | |||
+ | <code c#> | ||
+ | public class AsyncExample : MonoBehaviour | ||
+ | { | ||
+ | async void Start() | ||
+ | { | ||
+ | Debug.Log("Waiting 1 second..."); | ||
+ | await Task.Delay(TimeSpan.FromSeconds(1)); | ||
+ | Debug.Log("Done!"); | ||
+ | } | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | <note tip> | ||
+ | Conclusion: | ||
+ | |||
+ | * If you want to use asynchronous execution to express game logic, use coroutines. | ||
+ | * If you want to use asynchronous execution to utilize multiple CPU cores, use threads. | ||
+ | </note> | ||
+ | |||
+ | > **Coroutines** | ||
+ | |||
+ | <code c#> | ||
+ | /* Create a Coroutine */ | ||
+ | private IEnumerator CountSeconds(int count = 10) | ||
+ | { | ||
+ | for (int i = 0; i <= count; i++) { | ||
+ | Debug.Log(i + " second(s) have passed"); | ||
+ | yield return new WaitForSeconds(1.0f); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /* Call a Coroutine */ | ||
+ | StartCoroutine(CountSeconds()); | ||
+ | StartCoroutine(CountSeconds(10)); | ||
+ | |||
+ | /* Call a Coroutine that may need to be stopped */ | ||
+ | StartCoroutine("CountSeconds"); | ||
+ | StartCoroutine("CountSeconds", 10); | ||
+ | |||
+ | /* Stop a Coroutine */ | ||
+ | StopCoroutine("CountSeconds"); | ||
+ | StopAllCoroutines(); | ||
+ | |||
+ | /* Store and call a Coroutine from a variable */ | ||
+ | private IEnumerator countSecondsCoroutine; | ||
+ | |||
+ | countSecondsCoroutine = CountSeconds(); | ||
+ | StartCoroutine(countSecondsCoroutine); | ||
+ | |||
+ | /* Stop a stored Coroutine */ | ||
+ | StopCoroutine(countSecondsCoroutine); | ||
+ | |||
+ | /* Coroutine Return Types */ | ||
+ | yield return null; // Waits until the next Update() call | ||
+ | yield return new WaitForFixedUpdate(); // Waits until the next FixedUpdate() call | ||
+ | yield return new WaitForEndOfFrame(); // Waits until everything this frame has executed | ||
+ | yield return new WaitForSeconds(float seconds); // Waits for game time in seconds | ||
+ | yield return new WaitUntil(() => MY_CONDITION); // Waits until a custom condition is met | ||
+ | yield return new WWW("MY/WEB/REQUEST"); // Waits for a web request | ||
+ | yield return StartCoroutine("MY_COROUTINE"); // Waits until another Coroutine is completed | ||
+ | |||
+ | </code> | ||