Search Unity

C#, my code snippets (and other things I want to remember)

Discussion in 'Community Learning & Teaching' started by Deleted User, Aug 12, 2016.

  1. Deleted User

    Deleted User

    Guest

    This thread is not intended to be a tutorial per se but it could function like one; which is why I created it here, in the "Community Learning and Teaching" section of the forums. What I'd like to do here is posting what I've learnt so far while working on my personal projects, mainly how to do stuff with C#.

    Looking for answers to questions about how to do stuff with C# can be awfully frustrating: answers - all kinds of them, working, not working, up to date, deprecated - are scattered everywhere. Even the Documentation and the Scripting API can be very frustrating; and what to say about Answers? Although very useful these do not provide everything. Finding answers you need can take hours on end and most of the time end up (for me at least) in more frustration. So, I'm publishing here the bits I've learnt, first, for me as a sort of remainder, second for everyone who could need the knowledge.

    Disabling, enabling or destroying child objects

    Add the script below to the parent object:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class DisableEnable : MonoBehaviour
    5. {
    6.     void Start ()                            
    7.     {
    8.         foreach (Transform child in transform)   //This code works "as is"; no need to declare anything.
    9.         {
    10.             child.gameObject.SetActive (false);   //disabling the objects
    11.             child.gameObject.SetActive (true);    //enabling the objects
    12.             Destroy(child.gameObject);            //destroying the objects
    13.         }
    14.     }
    15. }
    The moderation team is free to move this thread if they think it's not in a suitable place. :)
     
    Last edited by a moderator: Mar 3, 2019
  2. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,997
    Your experience trying to find this stuff seems pretty typical -- there are lots and lots of code examples just floating like magic spells. They give the idea that the only way to do something is to Search, then cut and paste. No one explains that scripting is computer programming, which is a skill you can learn. Then you can understand the manual and write whatever you want. In my humble opinion, that's the biggest problem with the Unity scripting community (by this I mean You-Tube, Unity Answers and various blogs.) I don't think they're trying to hide that anyone can learn to program. It's just not mentioned where people notice it.

    For example, in the manual, SetActive looks like "void SetActive(bool)". That's really all you need to know. A little programming knowledge (not even Unity or C#) says that bool means either the word true or the word false. Likewise, Destroy(gameObject) is the standard command to kill yourself. That's also all you need to know. The basics of programming say you can put that Destroy in a loop "aimed at" whatever other gameObject you like (in what you wrote, each child.)

    Even if you look at what self-taught scripters say (as opposed to a programming class, or a good book,) they started with examples, but then realized they had to learn the underlying programming concepts. They didn't just make an enormous set of book-marks to all the examples they needed.
     
    Deleted User likes this.
  3. Deleted User

    Deleted User

    Guest

    Update, FixedUpdate and LateUpdate

    I'm still experiencing and learning about C#; I'm an old woman so things don't go fast. :p

    I'm trying to understand the subtleties behind the different Update functions. Awake and Start are pretty easy to understand:

    Code (CSharp):
    1.  
    2.     void Awake ()
    3.     {
    4.         print ("Awake: is called when the script instance is being loaded." +
    5.             " The script must be attached to an enabled object." +
    6.             " The script doesn't need to be enabled for the function to be called.");
    7.     }
    8.  
    9.     void Start ()
    10.     {
    11.         print ("Start: is called on the frame when a script is enabled" +
    12.             " just before any of the Update methods is called the first time.");
    13.     }
    FixedUpdate, LateUpdate and Update are less obvious. I've experienced with them and, each time they appear in the following order in the console:
    1. FixedUpdate,
    2. Update,
    3. LateUpdate (maybe that's why it's called "late"?).
    Now, what I cannot grasp is the difference between Update and LateUpdate since they are called at the same rate, here 642 times in about 10 seconds, when FixedUpdate is called a bit less often, as can be seen on this capture:

    Capture.JPG

    So, Update and LateUpdate, same thing? Also, what about the difference in performance between these two and FixedUpdate?

    When I've understood this, I've made a big progress! :D
     
    Last edited by a moderator: Mar 3, 2019
  4. panoskal

    panoskal

    Joined:
    Mar 31, 2017
    Posts:
    28
    Here is the documentation link for LateUpdate :

    https://docs.unity3d.com/ScriptReference/MonoBehaviour.LateUpdate.html

    From what I understand Update and LateUpdate are called every frame, their difference is that LateUpdate is called after all Update functions have been called. This is useful when you want a piece of code to be called always last, because it is affected by changes that happen inside other Update functions.

    For example, if you want your camera to follow the player, you would want it to happen every frame. By putting the code for the camera control inside LateUpdate you ensure that it is called "Late" every frame, after the player has moved and not before.

    As for FixedUpdate, I am still trying to understand that myself.
     
    Deleted User likes this.
  5. Deleted User

    Deleted User

    Guest

    Thanks. I had read the documentation and "late" makes sense since it really happens last! FixedUpdate seems to reflect our computers real graphics performance. At least, that's what I understand.
     
  6. Deleted User

    Deleted User

    Guest

    Last edited by a moderator: Jan 1, 2020
  7. Deleted User

    Deleted User

    Guest

    First Person Character controller: clamping the horizontal rotation of the camera

    The first person character controller that Unity Technologies gives us in their Standard Assets rotates by default by 360°. In a project, I wanted it to just rotate by 120°. I managed to do that.

    Preparation:
    1. download the latest Standard Assets and open them in Unity,
    2. to get the FPS controller only, and get it right without any error, import the following assets and leave the rest:
    Capture.JPG

    Clamping the horizontal rotation of the camera:

    The script to modify is MouseLook.cs. I proceeded by imitation, trial and errors but it works! Below are the original script:

    Code (CSharp):
    1. using System;
    2. using UnityEngine;
    3. using UnityStandardAssets.CrossPlatformInput;
    4.  
    5. namespace UnityStandardAssets.Characters.FirstPerson
    6. {
    7.     [Serializable]
    8.     public class MouseLook
    9.     {
    10.         public float XSensitivity = 2f;
    11.         public float YSensitivity = 2f;
    12.         public bool clampVerticalRotation = true;
    13.         public float MinimumX = -90F;
    14.         public float MaximumX = 90F;
    15.         public bool smooth;
    16.         public float smoothTime = 5f;
    17.         public bool lockCursor = true;
    18.  
    19.  
    20.         private Quaternion m_CharacterTargetRot;
    21.         private Quaternion m_CameraTargetRot;
    22.         private bool m_cursorIsLocked = true;
    23.  
    24.         public void Init(Transform character, Transform camera)
    25.         {
    26.             m_CharacterTargetRot = character.localRotation;
    27.             m_CameraTargetRot = camera.localRotation;
    28.         }
    29.  
    30.  
    31.         public void LookRotation(Transform character, Transform camera)
    32.         {
    33.             float yRot = CrossPlatformInputManager.GetAxis("Mouse X") * XSensitivity;
    34.             float xRot = CrossPlatformInputManager.GetAxis("Mouse Y") * YSensitivity;
    35.  
    36.             m_CharacterTargetRot *= Quaternion.Euler (0f, yRot, 0f);
    37.             m_CameraTargetRot *= Quaternion.Euler (-xRot, 0f, 0f);
    38.  
    39.             if(clampVerticalRotation)
    40.                 m_CameraTargetRot = ClampRotationAroundXAxis (m_CameraTargetRot);
    41.  
    42.             if(smooth)
    43.             {
    44.                 character.localRotation = Quaternion.Slerp (character.localRotation, m_CharacterTargetRot,
    45.                     smoothTime * Time.deltaTime);
    46.                 camera.localRotation = Quaternion.Slerp (camera.localRotation, m_CameraTargetRot,
    47.                     smoothTime * Time.deltaTime);
    48.             }
    49.             else
    50.             {
    51.                 character.localRotation = m_CharacterTargetRot;
    52.                 camera.localRotation = m_CameraTargetRot;
    53.             }
    54.  
    55.             UpdateCursorLock();
    56.         }
    57.  
    58.         public void SetCursorLock(bool value)
    59.         {
    60.             lockCursor = value;
    61.             if(!lockCursor)
    62.             {//we force unlock the cursor if the user disable the cursor locking helper
    63.                 Cursor.lockState = CursorLockMode.None;
    64.                 Cursor.visible = true;
    65.             }
    66.         }
    67.  
    68.         public void UpdateCursorLock()
    69.         {
    70.             //if the user set "lockCursor" we check & properly lock the cursos
    71.             if (lockCursor)
    72.                 InternalLockUpdate();
    73.         }
    74.  
    75.         private void InternalLockUpdate()
    76.         {
    77.             if(Input.GetKeyUp(KeyCode.Escape))
    78.             {
    79.                 m_cursorIsLocked = false;
    80.             }
    81.             else if(Input.GetMouseButtonUp(0))
    82.             {
    83.                 m_cursorIsLocked = true;
    84.             }
    85.  
    86.             if (m_cursorIsLocked)
    87.             {
    88.                 Cursor.lockState = CursorLockMode.Locked;
    89.                 Cursor.visible = false;
    90.             }
    91.             else if (!m_cursorIsLocked)
    92.             {
    93.                 Cursor.lockState = CursorLockMode.None;
    94.                 Cursor.visible = true;
    95.             }
    96.         }
    97.  
    98.         Quaternion ClampRotationAroundXAxis(Quaternion q)
    99.         {
    100.             q.x /= q.w;
    101.             q.y /= q.w;
    102.             q.z /= q.w;
    103.             q.w = 1.0f;
    104.  
    105.             float angleX = 2.0f * Mathf.Rad2Deg * Mathf.Atan (q.x);
    106.  
    107.             angleX = Mathf.Clamp (angleX, MinimumX, MaximumX);
    108.  
    109.             q.x = Mathf.Tan (0.5f * Mathf.Deg2Rad * angleX);
    110.  
    111.             return q;
    112.         }
    113.  
    114.     }
    115. }

    and the lines I added:
    Code (CSharp):
    1. using System;
    2. using UnityEngine;
    3. using UnityStandardAssets.CrossPlatformInput;
    4.  
    5. namespace UnityStandardAssets.Characters.FirstPerson
    6. {
    7.     [Serializable]
    8.     public class MouseLook
    9.     {
    10.         public bool clampHorizontalRotation = true;
    11.         public float minimumY = -90f;
    12.         public float maximumY = 90f;
    13.  
    14.         public void LookRotation(Transform character, Transform camera)
    15.         {
    16.             if (clampHorizontalRotation)
    17.             {
    18.                 m_CharacterTargetRot = ClampRotationAroundYAxis (m_CharacterTargetRot);
    19.             }
    20.         }
    21.  
    22.         Quaternion ClampRotationAroundYAxis (Quaternion q)
    23.         {
    24.             q.x /= q.w;
    25.             q.y /= q.w;
    26.             q.z /= q.w;
    27.             q.w = 1.0f;
    28.  
    29.             float angleY = 2.0f * Mathf.Rad2Deg * Mathf.Atan (q.y);
    30.             angleY = Mathf.Clamp (angleY, minimumY, maximumY);
    31.             q.y = Mathf.Tan (0.5f * Mathf.Deg2Rad * angleY);
    32.  
    33.             return q;
    34.         }
    35.     }
    36. }
     
    Last edited by a moderator: Mar 3, 2019
  8. Deleted User

    Deleted User

    Guest

    FixedUpdate

    I was watching the Update and FixedUpdate tutorial and I noticed that something is not said in the video:

    - FixedUpdate depend on how the "time" is set in your project.

    The "time" setting can be found in Edit/Project Settings/Time; it's set by default to 0.02, so, when I call FixedUpdate in a script, the time between two FixedUpdate will always be 0.02:

    fixedupdate1.JPG
    It's interesting to note that the first Update also have the value of 0.02.

    If I modify the "time" setting to 1, the time between two FixedUpdate will also be 1:

    fixedupdate2.JPG
    It's interesting to note that the first Update will still have the value of 0.02. I don't know why but maybe someone can answer this?
     
    Last edited by a moderator: Mar 3, 2019
  9. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    If you are interested in the callback methods and execution order:
    https://docs.unity3d.com/Manual/ExecutionOrder.html

    Or event functions:
    https://docs.unity3d.com/Manual/EventFunctions.html

    Time and Framerate management:
    https://docs.unity3d.com/Manual/TimeFrameManagement.html
    (This discusses Update vs FixedUpdate)

    All of these come from Unity's scripting overview:
    https://docs.unity3d.com/Manual/ScriptingConcepts.html

    ... and @panoskal is correct "Scripting", "Coding" and "Programming" can be learned as a skill independent of Unity.

    Many people learn coding as a means to an end to guide Unity. Coding concepts can be learned independently of Unity and applied to Unity. C# is a standalone language that can be used to create independent applications or programs. Now, this link is somewhat stale, but could give you a place to start:
    https://forum.unity3d.com/threads/getting-started-with-coding-for-unity.113937/
     
    Deleted User likes this.
  10. Deleted User

    Deleted User

    Guest

    Thank you very much @Adam-Buckner!
     
  11. Deleted User

    Deleted User

    Guest

    Fading a material colour in and out in time

    I'm proud, it's the first time I manage to figure out something by myself: https://stackoverflow.com/questions/43944926/lerp-the-alpha-value-of-a-color/43947418#43947418

    The question was about making the alpha layer of a material colour fade in and out in time. I knew that using Color.Lerp wouldn't work and I remembered something I had read in a scripting tutorial here; after multiple trials, I eventually came up with this, and it works!

    Set the material "rendering mode" to "transparent" first; then apply the script to the object.
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class NewColour : MonoBehaviour
    6. {
    7.     //Set the material "rendering mode" to "transparent" in the inspector
    8.     public Renderer rend;
    9.  
    10.     void Start ()
    11.     {
    12.         rend = GetComponent<Renderer> ();
    13.     }
    14.  
    15.     void FixedUpdate ()
    16.     {
    17.         rend.material.color = new Color (0f, 0.5f, 1f, Mathf.PingPong(Time.time, 1));
    18.     }
    19. }
    The colour is blue RGB (0, 128, 255) and Mathf.PingPong(Time.time, 1) makes the alpha layer fade in and out. :)
     
    Last edited by a moderator: Mar 3, 2019
  12. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    FWIW: for this there may be some advantage to setting the material's render mode to "fade". I can't remember the exact reason, but my memory tells me that "transparent" is for making things like glass and "fade" is for fading out solid objects.

    Let me see what I can find.

    [edit]

    I found this:
    https://docs.unity3d.com/Manual/StandardShaderMaterialParameterRenderingMode.html

    ... By googling material and getting to this page:
    https://docs.unity3d.com/Manual/Materials.html

    ... and then choosing standard shader from the built in shaders section:
    https://docs.unity3d.com/Manual/shader-StandardShader.html

    ... and the paging down until I got to the material parameters.

    Might be worth a look, as all of this section looks interesting.

    Long story short, that first page on the parameters talks about the difference between "transparent" and "fade".
     
    Last edited: May 15, 2017
    Deleted User likes this.
  13. Deleted User

    Deleted User

    Guest

    Thank you for the precisions!

    My object with the "fade" rendering mode, alpha layer set to 0:

    Capture.JPG

    and with the "transparent" rendering mode, alpha layer set to 0:

    Capture2.JPG
     
    Last edited by a moderator: Mar 3, 2019
  14. Deleted User

    Deleted User

    Guest

    For memory:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class BehaviourScript : MonoBehaviour
    6. {
    7.     /*Here variables are defined.*/
    8.  
    9.     /*Use Awake () and/or Start () for initialization
    10.     of the above mentioned variables.
    11.     Custom methods can also be called in Awake () and Start ().*/
    12.  
    13.     /*Awake is called - one time only - if the script is attached
    14.     to an active game object, even if the script is not enabled.*/
    15.     void Awake ()
    16.     {
    17.         DisableObject ();
    18.     }
    19.  
    20.     /*Start is called - one time only -  if the script is enabled
    21.     and attached to an active game object.*/
    22.     void Start ()
    23.     {
    24.        
    25.     }
    26.  
    27.     /*Use the different Update methods to act on the
    28.     variables and call custom methods.*/
    29.  
    30.     /*Update is called once per frame.*/
    31.     void Update ()
    32.     {
    33.        
    34.     }
    35.  
    36.     /*FixedUpdate is called accordingly to the "time" settings
    37.     in your project (see post #8 in this thread.*/
    38.     void FixedUpdate ()
    39.     {
    40.        
    41.     }
    42.  
    43.     /*LateUpdate is called once all the other Update methods
    44.     have been successfully called.*/
    45.     void LateUpdate ()
    46.     {
    47.        
    48.     }
    49.  
    50.     /*Write custom methods below and call them in
    51.     Awake (), Start (), or one of the Update () functions.*/
    52.     void DisableObject ()
    53.     {
    54.         /*Define local (temporary) variables*/
    55.         float delay = 3f;
    56.  
    57.         print(delay);
    58.         GameObject.Destroy(gameObject, delay);
    59.     }
    60. }
     
  15. Deleted User

    Deleted User

    Guest

    I just dug up this thread of mine and updated some of its content, for clarity. :)
     
  16. Deleted User

    Deleted User

    Guest

    I made this simple clock tutorial; it's an ordinary clock with arms that rotate; it shows the local time of the computer. it's good and I like it but I wanted to make a digital clock. I found several tutorials out there on the web but I wanted to find a solution for myself. After experimenting with the script provided by the tutorial I eventually found out that making a digital clock was a very simple task:
    1. create a UI Text and place it wherever you want;
    2. create a C# script and reference this UI text as a private text component;
    3. attach the script to the UI text.
    Here is the script:
    Code (CSharp):
    1. using System;
    2. using UnityEngine;
    3. using UnityEngine.UI;
    4.  
    5. public class DigitalClock : MonoBehaviour
    6. {
    7.     private Text clock;
    8.  
    9.     private void Start()
    10.     {
    11.         clock = GetComponent<Text>();
    12.     }
    13.  
    14.     private void Update()
    15.     {
    16.         DateTime time = DateTime.Now;
    17.  
    18.         clock.text = DateTime.Now.ToString();
    19.     }
    20. }
    Here you go! A digital clock!

    Capture.JPG
     
  17. Deleted User

    Deleted User

    Guest

    A tutorial about how to make a mirror in Unity. I made it with 2018.2 without any problem.

     
  18. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,997
    RE: fade vs. transparent. I think it's about the specular lighting.

    Fade means you want the object to become completely invisible in a magical way. To fade out. Even a 1/2-faded object should look magically 1/2 there. Whereas transparent means you want it to look like a real-world transparent object. Anyone would agree that 2nd glowing sphere represents a real fully transparent object. If we put it underwater, or in different lighting, we'd never see it. There's currently a white glare on parts of it since that's how transparent things work under strong light. A windshield is 100% transparent, but a decent game engine puts little glares on it as it turns.

    In mechanical terms, that glare is the Specular Highlight. Fade affects it, transparent doesn't. Either might be what you want, depending.
     
  19. Deleted User

    Deleted User

    Guest

    Yeah, that's exactly what they do. :)
     
  20. Deleted User

    Deleted User

    Guest

    Just used var in a script. Okay, what about it? :) I remember reading threads here about using var, how good it was or bad. At the time it just seemed to me that people who used var just knew what they were doing; I haven't changed my mind; back then though I didn't really care thinking that things would come to me if needed, when needed.

    And here I am, using var. I have this function:
    Code (CSharp):
    1.     private void StartAudio()
    2.     {
    3.         audioManager.ambientAudio.clip = audioManager.ambientClip;
    4.         audioManager.ambientAudio.loop = true;
    5.         audioManager.ambientAudio.pitch = 0.5f;
    6.         audioManager.ambientAudio.spatialBlend = 1f;
    7.     }
    I was reading it and was thinking: "four times audioManager.ambientAudio?", wow, there must be something better to do. So I wanted to create a local variable but what kind of variable? If I'm not wrong, nothing fits here (if someone knows better, please tell me! :))

    Except var!
    Code (CSharp):
    1.     private void StartAudio()
    2.     {
    3.         var ambientAudioSettings = audioManager.ambientAudio;
    4.  
    5.         ambientAudioSettings.clip = audioManager.ambientClip;
    6.         ambientAudioSettings.loop = true;
    7.         ambientAudioSettings.pitch = 0.5f;
    8.         ambientAudioSettings.spatialBlend = 1f;
    9.     }
    This script is going to be full of functions that will be on the same model. Another one:
    Code (CSharp):
    1.     public static void FootstepAudio()
    2.     {
    3.         var playerAudioSettings = audioManager.playerAudio;
    4.  
    5.         if(audioManager == null || playerAudioSettings.isPlaying)
    6.             return;
    7.  
    8.         int index = Random.Range(0, audioManager.walkingClips.Length);
    9.  
    10.         playerAudioSettings.clip = audioManager.walkingClips[index];
    11.         playerAudioSettings.playOnAwake = false;
    12.         playerAudioSettings.volume = 0.5f;
    13.         playerAudioSettings.Play();
    14.     }

    Still learning! ;)

    Edit: read further below.
     
    Last edited by a moderator: Jul 14, 2019
  21. I'm not good at Audio or audio programming, so I have no idea what is "audioManager".
    But
    Code (CSharp):
    1. var something = value;
    is equal to
    Code (CSharp):
    1. <type> something = value;
    where <type> is value's type.

    So if you check what audioManager.ambientAudio's type you will know what you can var be replaced. In fact, in order to know what kind of members you can have in those four lines, you have to know the type of ambientAudio.
    It's somewhat matter of taste (if you don't care about ease of change later and quick overview of your code), I like my types explicitly stated because I know what to expect from them when I change/add to code.

    So the "nothing fits here" is a false assumption. ambientAudio's type fits there. Whatever it is.
     
    Deleted User likes this.
  22. Deleted User

    Deleted User

    Guest

    Thanks for the reply !

    audioManager is an instance of a script named AudioManager and ambientAudio is an AudioSource. What should replace var? :)
     
  23. You just said it is an AudioSource. :)
     
  24. Deleted User

    Deleted User

    Guest

    It does work. Thanks! :)

    Is there really no reason at all to use var?
     
  25. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,997
    The normal internet does a decent job with Searches like "var C#", but there's one game thing about var:

    Game programmers often used a simplified language where you didn't even declare variables, n=5 and name="cat" were good enough. Learning about int or float or string seemed overly complicated, so wasn't in the language. To catch when you spelled a variable wrong, some game languages made you declare, but only using "var n" (short for "variable"). So before Unity was a thing, game programmers were using var aas = myAudio.source. When Unity was created, it had you write scripts in UnityScript. not C#. It copied that "var" thing.

    So sometimes when you see var, it's someone showing off how they learned a new C# feature. But other times it's just a regular game programmer doing things the old-fashioned way.
     
    Deleted User likes this.
  26. In professional C# development there are two sects:
    - those who love "var" because it make them not to think about variable types, so they can concentrate on what they are writing (allegedly)
    - and those (including me), who like to see what the variable is without hovering mouse and opening an IDE, at least in languages like C# (you don't want to know what I have done in Javascript for example ;) )

    It is ultimately up to you to decide if the type means unbearable burden which you don't need or you want to see at a glance what the type is and what this variable is all about. Neither is strictly wrong, as I mentioned earlier, it is a matter of taste. We really don't have to flog the var users before we burn them at stake. No biggie.
     
    Last edited by a moderator: Jul 14, 2019
    Deleted User likes this.
  27. Deleted User

    Deleted User

    Guest

    Something I never remember: how to use an array to assign a random value to some property:
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class MaxParticlesSettings : MonoBehaviour
    4. {
    5.     private ParticleSystem particles;
    6.     private int[] maxParticlesToEmit = new int[] { 500, 1000, 1500 };
    7.     int index;
    8.  
    9.     private void Start()
    10.     {
    11.         particles = GetComponent<ParticleSystem>();
    12.         index = Random.Range(0, maxParticlesToEmit.Length);
    13. }
    14.  
    15.     private void Update()
    16.     {
    17.         ParticleSystem.MainModule main = particles.main;
    18.         main.maxParticles = maxParticlesToEmit[index];
    19.     }
    20. }
     
  28. Deleted User

    Deleted User

    Guest

    I used the particles system as an example for this, not the best example in my opinion. I like settings random values to the number of particles emitted by fires and sparks in order to give some life to the scene. For this, I have a better script.
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class MaxParticlesSettings : MonoBehaviour
    4. {
    5.     private ParticleSystem particles;
    6.     private const int minLevelParticles = 250;
    7.     private const int maxLevelParticles = 1000;
    8.     private int levelParticles;
    9.  
    10.     private void Start()
    11.     {
    12.         particles = GetComponent<ParticleSystem>();
    13.         levelParticles = Random.Range(minLevelParticles, maxLevelParticles);
    14.  
    15.         ParticleSystem.MainModule main = particles.main;
    16.         main.maxParticles = levelParticles;
    17.     }
    18. }
     
  29. Deleted User

    Deleted User

    Guest

    FPS counter and IEnumerator. I use an FPS counter in my projects; I tried several different scripts, all of them gave the same results so I picked one that I liked better and it is the FPSCounter script Annop "Nargus" Prapasapong shared on the Unity Wiki in 2012. Not much recent but it works, so...

    The script contains a coroutine and an infinite for loop, both of them I am not much familiar with.
    Code (CSharp):
    1. /********************
    2. * FPS COUNTER
    3. * Written by: Annop "Nargus" Prapasapong
    4. * Created: 7 June 2012
    5. **************************/
    6. using System.Collections;
    7. using UnityEngine;
    8. using UnityEngine.UI;
    9.  
    10. public class FPSCounter : MonoBehaviour
    11. {
    12.     public float frequency = 0.5f;
    13.  
    14.     public int FramesPerSec { get; protected set; }
    15.  
    16.     private Text counter;
    17.  
    18.     private void Start()
    19.     {
    20.         counter = GetComponent<Text>();
    21.         counter.text = "";
    22.         StartCoroutine(FPS());
    23.     }
    24.  
    25.     private IEnumerator FPS()
    26.     {
    27.         for(; ; )
    28.         {
    29.             int lastFrameCount = Time.frameCount;
    30.             float lastTime = Time.realtimeSinceStartup;
    31.             yield return new WaitForSeconds(frequency);
    32.  
    33.             float timeSpan = Time.realtimeSinceStartup - lastTime;
    34.             int frameCount = Time.frameCount - lastFrameCount;
    35.  
    36.             FramesPerSec = Mathf.RoundToInt(frameCount / timeSpan);
    37.             counter.text = FramesPerSec.ToString() + " FPS";
    38.         }
    39.     }
    40. }
     
  30. Deleted User

    Deleted User

    Guest

    Something else I keep forgetting and need to search for when I need it...

    How to make a raycast visible in the scene view

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class DrawRaycast : MonoBehaviour
    6. {
    7.     public bool drawDebugRaycast;
    8.     public float distance = 1.5f;
    9.  
    10.     private new Rigidbody2D rigidbody2D;
    11.     private Vector2 lookDirection = new Vector2(1, 0);
    12.     private Vector2 offset = Vector2.up * 0.5f;
    13.     private LayerMask layerMask;
    14.  
    15.     private void Start()
    16.     {
    17.         rigidbody2D = GetComponent<Rigidbody2D>();
    18.         layerMask = LayerMask.GetMask("NPC");
    19.     }
    20.  
    21.     private void Update()
    22.     {
    23.         Vector2 position = rigidbody2D.position;
    24.         RaycastHit2D raycastHit2D = Physics2D.Raycast(position + offset, lookDirection, distance, layerMask);
    25.  
    26.         if(drawDebugRaycast)
    27.         {
    28.             Color colour = raycastHit2D ? Color.magenta : Color.green;
    29.             Debug.DrawRay(position + offset, lookDirection * distance, colour);
    30.         }
    31.     }
    32. }
    The line
    Code (CSharp):
    1.             Color colour = raycastHit2D ? Color.magenta : Color.green;
    uses a ?: operator. It means that if the raycast has hit its intended target, the drawn line will be magenta, otherwise, it will be green.

    The images below illustrate the ?: operator.

    Sans-titre-2.jpg
    Sans-titre-1.jpg
     
    Last edited by a moderator: Nov 8, 2019
  31. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,997
    The last line should maybe be: lookDirection.normalized * distance (add normalized)

    The issue is that recasts don't care about the length, but DrawRay does. They don't work the same. Suppose lookDirection is (15,7) -- almost 45 degrees, but not quite. And the distance is 5. Raycasts will go along (15,7) only out to 5. Going about 1/4th of that line. But DrawRay would go (15,7)*5, which is much further. Normalizing crunches it down to a standard short line, so the *5 gives a real distance of 5.
     
    Deleted User likes this.
  32. Deleted User

    Deleted User

    Guest

    My post was not about raycasts by themselves, it was about how to cast a line to make them visible. :)
    Not sure I understand that.

    I made a test, with Unity 2020.1.0a11, where I put two sprites:
    • one at 0, 0, 0,
    • one at 35.3, -28.24, 0.
    I modified the script and added a debug.log to track when the raycast hits its target or not. I noticed that the raycast (and the line) must be quite longer than the real distance between the two objects so that the hit happens.

    On the images below you can see that the message in the console confirms that the hit happened. On the other hand, if I reduce the ray distance, from 45.17 to 45.16 (image 1), the hit doesn't happen. I haven't calculated the real distance between the two objects.

    Sans-titre-1.jpg
    Sans-titre-2.jpg
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class DrawRaycast : MonoBehaviour
    6. {
    7.     public bool drawDebugRaycast;
    8.     public float distance = 22f;
    9.     public Vector2 offset = Vector2.up * 0.5f;
    10.     public Vector2 lookDirection = new Vector2(1, 1);
    11.  
    12.     private new Rigidbody2D rigidbody2D;
    13.     private LayerMask layerMask;
    14.  
    15.     private void Start()
    16.     {
    17.         rigidbody2D = GetComponent<Rigidbody2D>();
    18.         layerMask = LayerMask.GetMask("NPC");
    19.     }
    20.  
    21.     private void Update()
    22.     {
    23.         Vector2 position = rigidbody2D.position;
    24.         RaycastHit2D raycastHit2D = Physics2D.Raycast(position + offset, lookDirection, distance, layerMask);
    25.  
    26.         if(drawDebugRaycast)
    27.         {
    28.             Color colour = raycastHit2D ? Color.magenta : Color.green;
    29.             Debug.DrawRay(position + offset, lookDirection * distance, colour);
    30.         }
    31.  
    32.         if(Input.GetKeyDown(KeyCode.X))
    33.         {
    34.             RaycastHit2D hit = Physics2D.Raycast(origin: position + offset, direction: lookDirection, distance: distance, layerMask: layerMask);
    35.             if(hit.collider != null)
    36.             {
    37.                 Debug.Log("Raycast has hit the object " + hit.collider.gameObject);
    38.             }
    39.         }
    40.     }
    41. }
     
    Last edited by a moderator: Nov 8, 2019
  33. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,997
    Let me rephrase that. Depending on lookDirection, the drawRay in that code will be too long or short. Sometimes much, much too long.

    With the lookDirection variable set as Vector2(1,0), the raycast and drawRay are the same. But if you changed it to (2,0), the raycast won't change, but drawRay will go twice as far, making it wrong. Raycasts and drawRay use slightly different rules for length.
     
  34. Deleted User

    Deleted User

    Guest

    Okay. I didn't keep my test so I won't be able to test that right now but I'll remember. :)
     
  35. Deleted User

    Deleted User

    Guest

    Well well, I don't think I ever read that in tutorials, and I've done a lot of them. I knew about the camelCase naming convention, not about the PascalCase. I had seen variables names beginning the m_ prefix in scripts but it wasn't clear that it was actually a naming convention to be used in Unity.

    Fount in the John Lemon's Haunted Jaunt tutorial at https://learn.unity.com/tutorial/pl...65ddedbc2a08d53c7acb#5caf6e8cedbc2a08d53c846a.
     
  36. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,997
    Way back, people wrote multi-word variables using an underscore, since it looked like a space: num_of_cats. In Pascal, a 30-year-old programming language, it was more common to use numOfCats. Pascal wasn't all that popular, but was adopted by some Universities for teaching, so was pretty well known. Much later, Java adopted the same style, and Java was extremely popular (this was before C# even existed. Microsoft used Visual Basic, where var names tended to be n1 or g).

    By the time someone decided to make a word for it, which isn't really needed, Camel-case seemed like a fun thing to say. PacalCase would sound weird, since no one now has heard of it, but it also sounds more official and like you're paying tribute to history. But, as an analogy, the standard knot for tying shoes has a name. Shoes are getting tied just fine by people who don't know that name or care.
     
    Deleted User likes this.
  37. Deleted User

    Deleted User

    Guest

  38. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,769
    The first link regarding saving, is from 2014 or so. Unity moved ahead since then. You have many options now to save things.
    I think you may be falling into trap, that you tried battle in you very first post. Things getting outdated, or potentially better alternatives are not presented.

    I prefer native Unity API Utility Json, is to serialize, save and retrieve whole class back and forward. Then just save/load file with data.

    Also you could use new player preferences option.

    There are also other options. But I think these are quite simple to grasp.
     
  39. Deleted User

    Deleted User

    Guest

    True; I had noticed the date. But this one I just found dates back to 2018 and is virtually identical to the 2014 tutorial (you just need to survive the advertising at the beginning, I guess I'm on the right track. :)

    I'll need to learn how to store the scene state and everything in it in the save file, beside the player's data.

     
  40. Deleted User

    Deleted User

    Guest

    So, I made it, I made a start choice menu for my game. It was not obvious since I had no idea how to do that and I took me some time to figure it out.

    Choosing at start consists in choosing between two players. Steps:
    1. create an independent scene and add it to the build settings first in the list so that the game starts on that scene,
    2. add buttons on that scene for each player and configure them,
    3. create an empty game object and add a DontDestrolOnLoad script to this game object.
    The button:

    Sans-titre-1.jpg

    The script will refer the different players and start functions that will be added to OnClick() on the buttons. The OnClick() functions will contains the booleans that will store the information regarding what player was chosen (which explains why the script must be DontDestroyOnLoad), and load the actual game scene.
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.SceneManagement;
    3.  
    4. public class StartChoice : MonoBehaviour
    5. {
    6.     public static bool playerAshChoice;
    7.     public static bool playerAnnaleeChoice;
    8.  
    9.     private static StartChoice startChoice;
    10.  
    11.     private void Awake()
    12.     {
    13.         if(startChoice != null && startChoice != this)
    14.         {
    15.             Destroy(gameObject);
    16.             return;
    17.         }
    18.  
    19.         startChoice = this;
    20.  
    21.         DontDestroyOnLoad(gameObject);
    22.     }
    23.  
    24.     public static void PlayerChoiceAsh()
    25.     {
    26.         playerAshChoice = true;
    27.         Debug.Log("playerAshChoice == " + playerAshChoice);
    28.         SceneManager.LoadSceneAsync(1, LoadSceneMode.Single);
    29.     }
    30.  
    31.     public static void PlayerChoiceAnnalee()
    32.     {
    33.         playerAnnaleeChoice = true;
    34.         Debug.Log("playerAnnaleeChoice == " + playerAnnaleeChoice);
    35.         SceneManager.LoadSceneAsync(1, LoadSceneMode.Single);
    36.     }
    37.  
    38.     public static void QuitGame()
    39.     {
    40.         Application.Quit();
    41.     }  
    42. }
    Unfortunately, StartChoice being "DontDestroyOnLoad", the buttons will lose their On Click event when you get back to the selection scene during a game session.

    The solution is adding a script that will customise the On Click event. Here is one of the two that I have on the selection scene:
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3.  
    4. public class ButtonAnnaleeOnClickEvent : MonoBehaviour
    5. {
    6.     private Button button;
    7.  
    8.     private void Awake()
    9.     {
    10.         button = GetComponent<Button>();
    11.  
    12.         button.onClick.AddListener(OnClickEvent);
    13.     }
    14.  
    15.     private void OnClickEvent()
    16.     {
    17.         StartChoice.PlayerChoiceAnnalee();
    18.     }
    19. }
    In my game, I first chose to put the players on the scene and destroy the one that is not used at start; I'd do that in another script.
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class StartChoiceManager : MonoBehaviour
    4. {
    5.     [HideInInspector] public GameObject player;
    6.  
    7.     private static StartChoice startChoice;
    8.  
    9.     private void Start()
    10.     {
    11.         startChoice = GameObject.FindGameObjectWithTag("StartChoice").GetComponent<StartChoice>();
    12.         GameObject playerAnnalee = GameObject.Find("Annalee");
    13.         //Debug.Log("playerAnnalee = " + playerAnnalee);
    14.         GameObject playerAsh = GameObject.Find("Ash");
    15.         //Debug.Log("playerAsh = " + playerAsh);
    16.  
    17.         if(startChoice.playerAnnaleeChoice)
    18.         {
    19.             player = playerAnnalee;
    20.             Destroy(playerAsh);
    21.         }
    22.         else if(startChoice.playerAshChoice)
    23.         {
    24.             player = playerAsh;
    25.             Destroy(playerAnnalee);
    26.         }
    27.     }
    28. }
    but i switched to instantiating the chosen player on the scene. The StartChoiceManager script would now look like this:
    Code (CSharp):
    1.  
    2. using UnityEngine;
    3.  
    4. public class StartChoiceManager : MonoBehaviour
    5. {
    6.     public GameObject playerAnnaleePrefab;
    7.     public GameObject playerAshPrefab;
    8.     public GameObject player;
    9.  
    10.     private static StartChoice startChoice;
    11.  
    12.     private void Start()
    13.     {
    14.         startChoice = GameObject.Find("StartChoice").GetComponent<StartChoice>();
    15.  
    16.         if(startChoice.playerAnnaleeChoice)
    17.         {
    18.             Instantiate(playerAnnaleePrefab, new Vector3(-15f, -20f, 0f), Quaternion.identity);
    19.         }
    20.         else if(startChoice.playerAshChoice)
    21.         {
    22.             Instantiate(playerAshPrefab, new Vector3(-15f, -20f, 0f), Quaternion.identity);
    23.         }
    24.  
    25.         player = GameObject.FindGameObjectWithTag("Player");
    26.         Debug.Log("player = " + player);
    27.     }
    28. }
     
    Last edited by a moderator: Jan 1, 2020
  41. Deleted User

    Deleted User

    Guest

    How to make something happen at a certain time of the day:

    The following script make some changes on a scene according to the time of day. The bool "day" is there to make it so that the function that makes the changes runs only one time in Update(), since we'll have to work in Update(). It must be true by default because the scene is designed to be the night scene by default and SetNightTime sets the day bool to true to prepare the day scene environment installation. The boss condition here is
    Code (CSharp):
    1. if((minDayTime < now) && (now < maxDayTime))
    Code (CSharp):
    1. using System;
    2. using System.Globalization;
    3. using UnityEngine;
    4.  
    5. public class SceneTimeManager : MonoBehaviour
    6. {
    7.     private bool day = true;
    8.  
    9.     private void Update()
    10.     {
    11.         DateTime minDayTime = DateTime.ParseExact("08:00", "HH:mm", CultureInfo.InvariantCulture);
    12.         DateTime maxDayTime = DateTime.ParseExact("20:00", "HH:mm", CultureInfo.InvariantCulture);
    13.         DateTime now = DateTime.Now;
    14.  
    15.         if((minDayTime < now) && (now < maxDayTime))
    16.         {
    17.             if(day)
    18.                 SetDayTime();
    19.         }
    20.         else
    21.         {
    22.             if(!day)
    23.                 SetNightTime();
    24.         }
    25.     }
    26.  
    27.     private void SetDayTime()
    28.     {
    29.         do stuff();
    30.  
    31.         day = false;
    32.     }
    33.  
    34.     private void SetNightTime()
    35.     {
    36.         do stuff();
    37.  
    38.         day = true;
    39.     }
    40. }
     
    Last edited by a moderator: Jan 1, 2020
  42. Deleted User

    Deleted User

    Guest

    Since the only tutorial about that in Unity is behind a pay wall, I kept searching and found this playlist dating back to 2016:

     
  43. Deleted User

    Deleted User

    Guest

    And this one from 2018:



    I have no idea which is the best; I'll have to try everything I think. :)
     
  44. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,769
    Even there are options to learn playprefs, there were some post on forum too. However hard way such tutorials are conveyed to potential users, or behind paywall, personally I wouldn't trust it, that tomorrow play prefs won't get depreciated. Sorry for my pessimism :)
     
  45. Deleted User

    Deleted User

    Guest

    You're right but I need a save system, whatever that is. So, I'll have to go with what I find. :D