#Notes on Notes
1 messages · Page 1 of 1 (latest)
yes please ❤️ ❤️ ❤️ ❤️
//I dont understand whats going on in this
this?.Invoke("SpawnThis",0);
?. is the "null condition operator" - it acts like the normal "member access operator" . except if the thing on the left is null then the part on the right won't be evaluated, and the expression as a whole will evaluate to null. This is a super convenient short-hand if you only want to run some method or access some field on an object, but only if that object reference is not null.
I'm not sure if it really makes sense in the quoted code, because I don't think this can ever be null inside of a class instance method - that is, if you're running code within a method on a class instance, then that class instance has to exist, so this should never really be null (I think? I might be wrong about that). But in any scenario, the net effect of that code would be that if this is not null, then it will execute the Invoke() method on it. If this is null, then C# will skip the bit on the right - so it won't try to call Invoke() (and thus avoiding a Null Reference Exception!)
In short,
foobar = someObj?.someField;
is equivalent to
if (someObj == null)
foobar = null;
else
foobar = someObj.someField;
and
someObj?.SomeMethod();
to
if (someObj != null)
someObj.SomeMethod();
But it's important to note that Unity overrides equality comparison checks for things inheriting from UnityEngine.Object (that is, Unity changes how == works for them, and does somewhat confusing things like make them == null even though they still exist). So you should generally avoid using ?. on most every object that comes from Unity (GameObjects, MonoBehaviours, components, vectors, etc) to avoid all sorts of confusion down the road.
//I dont understand whats going on in this
void SpawnThis() => Debug.log("something");
I think this is an "expression body member" https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/expression-bodied-members. It's another neat shorthand to create little methods which can do everything they need to with a single statement or expression.
class FooBar {
int a = 4;
void SpawnThis() => Debug.Log("something");
int GetA() => a;
}
Is the same as writing out
class FooBar {
private int a;
void SpawnThis()
{
Debug.Log("something");
}
int GetA()
{
return a;
}
}
//you can add if statements to just about anything for just about any reason
#if ENABLE_INPUT_SYSTEM
using UnityEngine.InputSystem;
#endif
These bits of code which start with a # are "preprocessor directives", which is sort of a super-basic language which will be executed before the code is actually compiled. This one here's for "conditional compilation," and if the ENABLE_INPUT_SYSTEM symbol isn't defined (which is defined when the Input System package is loaded), then the using UnityEngine.InputSystem; won't even be processed when the code is built. #if UNITY_EDITOR is an especially useful one for omitting your development and debugging code from a build intended for players
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/preprocessor-directives#conditional-compilation
I think that's all I had for the moment. Good on you for taking notes though 👍 😁
Another thing that confuses me is
‘NetworkManager.OnClientConnectedCallback += NetworkManager_OnClientConnectedCallback;’
Events are super awesome. There, NetworkManager.OnClientConnectedCallback is likely a "delegate" type like Action or EventHandler (or something similar), and those types' addition + operator is overridden such that when you add + a method to it, it adds that method to an internal list of methods which will be called when the event is triggered/invoked (generally referred to as "subscribing to the event").
So they're a convenient way to execute one or more methods when something specific happens. In this case the subscription means "When NetworkManager.OnClientConnectedCallback happens, call the method NetworkManager_OnClientConnectedCallback()."
class Foo {
// Declare an event delegate for when a sandwich has prepared. It will pass one argument of type Sandwich to it's subscribers.
public static event Action<Sandwich> OnSandwichPrepared;
public void PrepareSandwich() {
Sandwich sandwich = new();
// ...
// If the event is null, it has no subscribers. If it's not null, invoke it, and pass along the newly prepared sandwich.
if (OnSandwichPrepared != null)
OnSandwichPrepared( sandwich );
// Or, using the null conditional operator from earlier, we could also rewrite the above as:
OnSandwichPrepared?.Invoke( sandwich );
}
}
class Bar : MonoBehaviour {
void Awake() {
// Whenever Foo prepares a sandwich, serve it!
Foo.OnSandwichPrepared += ServeSandwich;
}
void OnDestroy() {
// If this object is destroyed, unsubscribe from the event to prevent memory leaks.
Foo.OnSandwichPrepared -= ServeSandwich;
}
void ServeSandwich( Sandwich sandwich ) {
Debug.Log( "Order up! Serving " + sandwich );
}
}
https://learn.microsoft.com/en-us/dotnet/standard/events/
https://learn.microsoft.com/en-us/dotnet/standard/events/how-to-raise-and-consume-events