This shows you the differences between two versions of the page.
|
pjv:laboratoare:2023:03 [2023/10/23 09:10] alexandru.gradinaru |
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 ===== | ||
| - | Creati o scena care sa contina: | + | 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: |
| - | * o tinta care se roteste in permanenta | + | * 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 | * un obiect de tip tun care | ||
| * poate lansa proiectile | * poate lansa proiectile | ||
| Line 11: | Line 17: | ||
| * este lansat la fiecare apasare a tastei SPACE | * este lansat la fiecare apasare a tastei SPACE | ||
| * este lansat din varful tevii tunului, pe directia inainte, si are comportament fizic (gravitatie, forta etc.) | * 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> | ||