#Return types and Void
1 messages · Page 1 of 1 (latest)
Alright, let's go :)
using UnityEngine;
public class VoidVsType : MonoBehaviour
{
private void Start()
{
// Minimum values
Debug.Log(int.MinValue);
Debug.Log(float.MinValue);
// Maximum values
Debug.Log(int.MaxValue);
Debug.Log(float.MaxValue);
}
}
This is the first example.
Let's make sure you understand it, and then I will modify it
alr
Do you know what an int is`?
int stands for integer - it is a whole number (no fractions)
oh so it is like math
You probably should, but I am here now. I'll lead.
it is math phrases in english
yes, and there are many number types
i should understand almost all of these
all have their uses
Not exactly
For beginning game dev, you'll be working mostly with int, float, double
int is a whole number (0,1,2,3,4,5,6,7,8,9,10,11...)
float is a fractional number, appended with an f (1.23f)
double is a fractional number also, appended with a d or nothing at all (the default) (1.23)
Do you know how to use Debug.Log() ?
That's both a yes and a no.
Some of this matters, but you should not try to comprehend them in that wide a perspective, as a beginner, unless you are also a math genius
(Advanced)
There is both int and uint
int is signed, and can thus be positive or negative
uint is unsigned, and uses the extra bit-space to be able to store an even bigger number
This is true for most numeric types.
For the record: I have never used uint or any of the unsigned numeric types.
Okay, but how would i be able to use this knowledge?
I am getting there
Do you know how to use Debug.Log() ?
No
Alright. Have you written any code so far?
python is super-simplistic, and doesn't deal with types like C#
or rather, simplistic might be the wrong word. It's just different.
yea that is why i was so confused
Have you created a Unity project, or have one open?
Any C# scripts in there?
yes
post one in a code segment or pastebin link
using UnityEngine;
public class Movement : MonoBehaviour
{
private float horizontal;
private float speed = 8f;
[SerializeField] private Rigidbody2D rb;
[SerializeField] private LayerMask groundLayer;
void Update()
{
horizontal = Input.GetAxisRaw("Horizontal");
}
private void FixedUpdate()
{
rb.velocity = new Vector2(horizontal * speed, rb.velocity.y);
}
}
I wanted movement but no turning
and no jumping
Alright.
So Update() runs every visual frame
FixedUpdate() runs every fixedTimestep, default 0.2 seconds interval, a value you can specify in the project.
0.2 is 50 FPS
i understand
So if i had everything of my code
in update() it would make it very unoptimized
inside void update, add Debug.Log(horizontal);
below the line that defines horizontal.
actually, no, inside FixedUpdate()
This is right?
Yes, that's where we would* use other Unity calls and Events to trigger code, instead of polling.
Polling is just best to learn with for starters.
oh so
polling = checking every frame
like
lets say i made some movement scripts
I would put the keybind in the void update so it would be responsive
and the other stuff in the fixed update?
Yes, if you're working with Colliders and Rigidbodies
Game Logic also goes in Fixed Update
not just physics
We always check for input in Update
However, there is actually an option to let input be registered inside FixedUpdate()
Though, I have never tried it myself.
i kinda understand void update is for stuff that can trigger other lines of code?
Yes, if you let me lead the conversation I will get you there soon
ok
Have you added the Debug.Log ?
using UnityEngine;
public class Movement : MonoBehaviour
{
private float horizontal;
private float speed = 8f;
[SerializeField] private Rigidbody2D rb;
[SerializeField] private LayerMask groundLayer;
void Update() Debug.Log(horizontal);
{
horizontal = Input.GetAxisRaw("Horizontal");
}
private void FixedUpdate()
{
rb.velocity = new Vector2(horizontal * speed, rb.velocity.y);
}
}
it needs to be inside the body of the method
and also - FixedUpdate, not Update (I changed my mind earlier)
void Update() is a method
void FixedUpdate() is also a method
private void FixedUpdate(Debug.Log(horizontal))
the body is within the curly brackets { }
oh
private void FixedUpdate()
{
Debug.Log(horizontal)
rb.velocity = new Vector2(horizontal * speed, rb.velocity.y);
}
Yes
Now save the script, press Play in Unity and make sure you see the Console tab in the Editor
Debug.Log() is like Console.WriteLine() or print()
it sends strings of text to be displayed in the console
using UnityEngine;
public class Movement : MonoBehaviour
{
private float horizontal;
private float speed = 8f;
[SerializeField] private Rigidbody2D rb;
[SerializeField] private LayerMask groundLayer;
void Update();
{
horizontal = Input.GetAxisRaw("Horizontal");
}
private void FixedUpdate()
{
Debug.Log(horizontal)
rb.velocity = new Vector2(horizontal * speed, rb.velocity.y);
}
}
Yep
see now it works
but here is the thing i don't understand
why does it say line 21 space 1
when it is not the last bracket that is the faulty code
Errors are usually very smart, if you've only made one error.
You'll learn to understand them soon enough.
(21,1) means Line 21 Character 1
That's where it starts perceiving an error
i understand how the problem thing works
with 21, 1 thing
but that is the last bracket
using UnityEngine;
public class Movement : MonoBehaviour
{
private float horizontal;
private float speed = 8f;
[SerializeField] private Rigidbody2D rb;
[SerializeField] private LayerMask groundLayer;
void Update(); <--
{
horizontal = Input.GetAxisRaw("Horizontal");
}
private void FixedUpdate()
{
Debug.Log(horizontal);
rb.velocity = new Vector2(horizontal * speed, rb.velocity.y);
}
} <--
no it was to indicate
you wonder what the last bracket is for?
to tell the code that that is the end of public class Movement : MonoBehaviour
It's best to make actual script comments.
} // <--
i used to do it on python
so i would understand
what i wrote
like i would write a bunch of statements and then explain what that part of code was used for
that's good practice
or you'll have a hard time coming back to said code in 2 weeks
Script fixed?
yes
Yeah good. And when you move, it shows a number between -1 and 1
which is what horizontal returns
ok so the horizontal
can never be more than -1 to 1
but you can increase the force
Since input is not smoothed, keyboard input will always be either -1, 0 or 1.
The smooth one is GetAxis
i understand that means
Next up is adding more to the debug log, and doing math inside it
0.5f of mouse position x
would be half of my monitor
right?
and that would theoretically scale with any resolution
I'm not sure what you're on about now?
Input.GetAxisRaw("Horizontal") returns -1 when you press to move Left
and 1 if you press to move Right.
If no move is pressed, it returns 0.
It returns an integer, not a float.
so i can make the integer more powerful by increase the float value?
GetAxis returns a float between -1f and 1f
but it will still only be -1 to 1
you can't change the input return value, but you'll work around it to get your logic down
I'll show you in a bit
Now we'll do math in the Debug Log
using UnityEngine;
public class Movement : MonoBehaviour
{
private float horizontal;
private float speed = 8f;
[SerializeField] private Rigidbody2D rb;
[SerializeField] private LayerMask groundLayer;
void Update(); <--
{
horizontal = Input.GetAxisRaw("Horizontal");
}
private void FixedUpdate()
{
Debug.Log(horizontal + " * " + speed + " = " + (horizontal*speed));
rb.velocity = new Vector2(horizontal * speed, rb.velocity.y);
}
}
Replace code?
Nah, just replace the Debug.Log line.
There is also another way to write it, using string interpolation with $
Debug.Log(horizontal + " * " + speed + " = " + (horizontal*speed));
Debug.Log($"{horizontal} * {speed} = {(horizontal*speed)}");
It is showing both
and the result
Yes. And that is possible, but we should do something to make sure it is precise.
If you divide two integers, the result will be rounded down in C#.
If the answer return type is destined to be an integer, you won't get the fractional value
so, we cast them
Debug.Log($"{horizontal} * {speed} = {((float)horizontal*speed)}");
oh actually
you're saving horizontal as a float type
which means inside void Update you are setting an int to a float, which is fine
horizontal = Input.GetAxisRaw
which is a value you cannot change
you can change it after getting it, but every frame it would be reset
no
Yes, but you store its value as a float, which is fine. There is implicit casting between the basic numeric types.
But if you were to say int myInteger = 1.23f it would round that down to 1
I understood it as
GetAxisRaw gives an int value to "Horizontal"
and then it multiplies the "Horizontal" with the float "speed"
and then it multiplies the "Horizontal" with the float "speed"
GetAxisRaw doesn't do that
or were you referring to the code as it ?
Okay, go on
and then the Horizontal multiplied with Speed equals the rb velocity
which is the actual movement?
and Vector3(x,y,z)?
yes
Vector 1 is just x?
I don't think there is a vector1 😆
rb.velocity = new Vector2(horizontal * speed, rb.velocity.y);
What does rb.velocity.y do?
on that line you are recreating the velocity vector, and modifying the X axis, but leaving the Y axis as it was previous.
horizontal = Input.GetAxisRaw("Horizontal");
vertical = Input.GetAxisRaw("Vertical");
// ...
rb.velocity = new Vector2(horizontal * speed, vertical * speed);
That's not the best solution. It would make you go too fast when moving diagonally.
That you can google after this session.
if it's even applicable to you right now
Is Horizontal seen as code?
horizontal = Input.GetAxisRaw("X");
vertical = Input.GetAxisRaw("Y");
It is part of the old input system. Typical error is typing "horizontal" because it wouldn't be recognized without the capital H
it has to be Horizontal or Vertical.
But if i write Horizontal does it just see it as X or is it a name im giving it
Input.GetAxisRaw("Horizontal") returns a very specific variable from the Unity input system
When you do horizontal = that
You're just copying the value (at a point in time) and storing it in a variable.
That is because float is a value type
as opposed to reference type.
Classes are reference types.
When you write: MyClass instance_1 = new MyClass();
And then write: MyClass secondVariable = instance_1;
It doesn't make a copy, but copies the reference (path) to that class instance.
But when you work with value types, it makes copies, at that specific point in time.
string, int, float, double, Vector3 and all that are value types
oh so
//horizontal is now if referenced = Input.GetAxisRaw("Horizontal");
horizontal = Input.GetAxisRaw("Horizontal");
tell me if this is correct, but it sees that line of code and then everytime "horizontal" is used it will actualy use this string of code?
private void Start()
{
horizontal = Input.GetAxisRaw("Horizontal");
// This would give you the value of GetAxisRaw only at the first frame. They would not otherwise be "connected" to the same reference.
}
I'm not sure I comprehend that.
void Update()
{
horizontal = Input.GetAxisRaw("Horizontal");
}
private void FixedUpdate()
{
Debug.Log(horizontal + " * " + speed + " = " + (horizontal*speed));
rb.velocity = new Vector2(horizontal * speed, rb.velocity.y);
}
horizontal does not mean anything
but i gave it a value
it is whatever value it was last given
that it is now using in FixedUpdate
void Update() can run like 300 FPS
FixedUpdate() only runs 50 FPS
So you get whatever value was last inputted.
yes, but it is best to add more variables, so the original value remains unchanged, in case you need it later
void Update()
{
horizontal = Input.GetAxisRaw("Horizontal");
}
private void FixedUpdate()
{
Debug.Log(horizontal + " * " + speed + " = " + (horizontal*speed));
rb.velocity = new Vector2(horizontal * speed, rb.velocity.y);
}
void Update()
{
horizontal = Input.GetAxisRaw("Vertical");
}
private void FixedUpdate()
{
Debug.Log(horizontal + " * " + speed + " = " + (horizontal*speed));
rb.velocity = new Vector2(horizontal * speed, rb.velocity.y);
}
so in this the first FixedUpdate horizontal is equal to the equation in the first void update
the last void update that ran before the current FixedUpdate
yea so the first
but the second fixed update would have the value of the second void update
since it changes it's value?
They don't run in tandem, though there is some internal execution order logic
If void Update runs 300 times per second
and Fixed runs 50 times per second
That means Update will run 6 times before the first Fixed is called.
So whatever Update gave horizontal last, is what Fixed will use.
oh
so if i wanted the horizontal to have different values
i would have to write it in the fixed update
or later in void update
Fixed is better for performance, if the logic permits it
using UnityEngine;
public class VoidVsType : MonoBehaviour
{
private void Start()
{
// Minimum values
Debug.Log(int.MinValue);
Debug.Log(float.MinValue);
// Maximum values
Debug.Log(int.MaxValue);
Debug.Log(float.MaxValue);
}
}
This is the first script example I made
Now I'll show you where it leads
related to void
using UnityEngine;
public class VoidVsType : MonoBehaviour
{
private void Start()
{
MinValues();
MaxValues();
}
private void MinValues()
{
// Minimum values
Debug.Log(int.MinValue);
Debug.Log(float.MinValue);
}
private void MaxValues()
{
// Maximum values
Debug.Log(int.MaxValue);
Debug.Log(float.MaxValue);
}
}
hmm
voids are just pockets of logic
one of the primary principles in electronic data management
when you write
is to never repeat yourself, by storage or by code
private void MaxValues()
is private void the logic of the execution
and MaxValues is just the name of this execution?
So if you need to repeat some line of code, you can call it
private void SomePocketOfCode()
{
// Logic here
}
and repeat that anywhere.
Yeah, you can give it any name you want
there are preferred conventions
It's best to use language that helps the code make sense
call things exactlyWhatTheyAre
Class, Property and Method names usually go with PascalCase
While internal variables, and some public, use camelCasing.
Space isn't valid. Use _
underscore
but will it work?
if i wrote code into that it wouldn't run unless called?
like Void update will update every frame
making a void AnyNamePossible() doesn't make it run unless you call it somewhere
and private void will update every set amount
so a void doesn't run unless it is needed
only void Update is automatically called every frame
Unless you specify it to run.
These are some of your primary options for executing code in MonoBehaviour
thank you
MonoBehaviour is a Unity class, designed to work with the engine.
MonoBehaviour scripts need to be attached to an instance of a GameObject
For background systems, there are other options, like MonoBehaviour singletons (static instance) or regular C# classes and statics.
ah
statics can be accessed from anywhere, without needing a reference
Yes, exactly
that is why i was so confused when i opened visual studios
open new c# files
the stuff i need for unity is not there
yes
ok good
but
the colour is kinda annoying
because the values i preset are not white all the time
Never heard that one before.
If it really is a problem, perhaps try lowering the brightness of your monitor.
What do you mean by that?
for me to understand the code i have to in my head try to interpret it as a number
but it is difficult when it doesn't stay consistent
What i assign i want in white text
Add this anywhere inside Update()
float test = 1f;
Debug.Log(test);
No need to run it.
screenshot how it looks
is that Visual Studio Code?
Yes
Community is objectively better from a beginner perspective, as far as I have understood.
not about coloring
The code I assign which is of the class, is white.
But local variables, that only exist inside their respective method, are tinted blue.
Being?
let's say
private. something
when i type the .
it automatically picks something else
I am not a user of Visual Studio Code, and cannot relate.
Also, it is beside the point of this thread*, and beyond the scope of the channel code-beginner.
General questions go in #💻┃unity-talk or any other specific channel that covers them.
Let me be frank: I am trying to help* you understand code before I have you run some very specific lines of code, which I believe will help you understand some basics of Unity, while it covers the significance of voids and data types.
This derailing is costing a lot of time.
I can help you make an FPS counter that displays with text you can stylize
in the game
Which version of Unity is your project running?
2019, 2020, 2021 or beyond?
@primal walrus FYI, I am not frustrated, just getting hungry.
This will take just 5-10 minutes, and you'll have a working example with void, int, float and string.
2021
Alright. If I recall correctly, that means it ships default with TextMeshPro.
We're going to create a UI element, that is to be rendered by the camera.
Can you see the Text - TextMeshPro option?
when right-clicking in the Hierarchy
yes
Create one
It will automatically also make a Canvas and an EventSystem
There needs to be at least one EventSystem for buttons etc to work.
Every UI element needs to be inside a Canvas.
You can't see the text easily in Scene View. Go to Game* view, and edit the text inside the Text component of the object.
Great. Now, we're going to access that text by code.
in your script, on the top, add using TMPro;
🤨
?
just create a new script?
Great
Add using TMPro;
and make a private TMP_Text uiText;
~~rename Start() to Awake() ~~
actually
no
Add using TMPro; where i put this
Awake vs Start
When accessing a different object, it has to be done in Start, because Start runs after all other scripts have run Awake (or they won't be found anyway)
top of the script, next to the other using statements
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
Add using TMPro;
public class FPSCounter : MonoBehaviour
{
void Start()
{
}
void Update()
{
}
private TMP_Text uiText;
}
I think that 4th line is causing an error
it is
The reason should be obvious 🤔
But I could point it out
using TMPro;
Alright.
Btw, it is usually preferred to have the variables, like uiText, above the methods.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
public class FPSCounter : MonoBehaviour
{
private TMP_Text uiText;
void Start()
{
}
void Update()
{
}
}
Next up - in the editor, select the text object in the hierarchy, scroll down in inspector, and choose Add Component - type 'FPSCounter'
Then add this line in Start()
uiText = GetComponent<TMP_Text>();
Now you can change its text by uiText.text = "my own string of characters"
that's in the script
oh
you have attached the MonoBehaviour to a GameObject, which means that game object will have its own instance of the script
If this weren't for UI, but enemies, each enemy could have its own instance of that same script
btw it's taking a few more min here because I have to write a new FPSCounter from scratch
add these variables
private float timer;
private int frames;
private float framesPerSecond;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
public class FPSCounter : MonoBehaviour
{
private float timer;
private int frames;
private float framesPerSecond;
private TMP_Text uiText;
void Start()
{
uiText = GetComponent<TMP_Text>();
}
void Update()
{
}
}
in the simplest form, an FPS counter is
void Update()
{
uiText.text = 1f/Time.deltaTime;
}
But it would change every single frame, which isn't very nice.
You can try it out. I'm typing out how to only update it every 1 second
Time.deltaTime is the time in seconds since the last frame was called.
it is a float
I realize now, this is missing from your movement script.
When you set speed to be 8f, you mean to say 8f per second.
In order to make that distribute across the frames during that second, we multiply 8f by Time.deltaTime
Cannot implicitly convert "float" to "string."
Ah, that is true.
Two ways to fix this:
void Update()
{
uiText.text = (string)(1f/Time.deltaTime);
// or
uiText.text = (1f/Time.deltaTime).ToString();
}
I suggest ToString() because you can do ToString("F2") and get only 2 decimals
That is a project setting.
okay no problem
From my personal FPS Counter
if (setCustomFrameRate)
{
customFrameRateWasTrue = true;
// Save original settings
originalTargetFrameRate = Application.targetFrameRate;
originalVSyncCount = QualitySettings.vSyncCount;
// 0 for no sync, 1 for panel refresh rate, 2 for 1/2 panel rate
QualitySettings.vSyncCount = 0;
// vSyncCount must be zero
Application.targetFrameRate = targetFrameRate;
}
Application.targetFrameRate and QualitySettings.vSyncCount
I actually don't know where else in the editor it is changed.
Anyway
This code I just posted was not inside Update, but OnEnable()
only runs every time the object is Enabled
using UnityEngine;
using TMPro;
public class FPSCounter : MonoBehaviour
{
private TMP_Text uiText;
private float timeCount;
private int frameCount;
private float framesPerSecond;
private float pollingRate = 1f; // Update interval in seconds
void Start()
{
uiText = GetComponent<TMP_Text>();
}
void Update()
{
timeCount += Time.deltaTime;
frameCount++;
if (timeCount >= pollingRate)
{
framesPerSecond = frameCount / timeCount;
uiText.text = framesPerSecond.ToString("F2");
timeCount = 0;
frameCount = 0;
}
}
}
There you go.
If pollingRate is 10f, the result will be the average FPS over 10 seconds
Any questions?
Forgot to explain earlier: TMP - TextMeshPro is the fully adopted successor to Unity's default UI (which looks horrible)
In older versions it has to be imported as a Package
default UI text is pixelated etc
@primal walrus
To explain the void - you could split up the code inside update, into several individual methods,
and then simply call those methods in the correct order, inside Update, and the functionality would be identical.
To explain return types - void is just a set of code to run
Methods can also return types that have been computed inside said methods.
private void MyMethod()
{
Debug.Log(MyText());
Debug.Log(MyNumber())
Debug.Log(MyNumber() / 2)
}
private string MyText()
{
return "Some random text";
}
private int MyNumber()
{
return 4;
}
There are multiple ways to reach the same results in C#.
private int myNumber = 4;
private int MyNumber()
{
return 4;
}
These are identical, and there is also Properties (with custom get and set), but those aren't really important right now.
Methods can also take arguments, so you can pass along external values.
private void MyMethod()
{
Debug.Log(MyNumberMultiplied(6))
}
private int MyNumberMultiplied(int multiplier)
{
return 4 * multiplier;
}
Well, it's been 3 hours. Good luck 👋