-
Notifications
You must be signed in to change notification settings - Fork 8
Mod Creation_C# Programming_Unity and MonoBehaviour
Every Unity game is running a scene that is composed of GameObject's which have a collection of components attached to them.
Components are the main source of game logic.
A MonoBehaviour is the main class you want to derive from to create your own GameObject component.
Generally when people say "component" they are talking about classes derived from MonoBehaviour, and visa versa.
Every instance of MonoBehaviour has some special functions that are called by the engine at specific events. Here is the game loop: https://docs.unity3d.com/uploads/Main/monobehaviour_flowchart.svg
All MonoBehaviour callbacks are described in unity documentation: Check under "Messages" header But down below we'll talk about some of them.
Generally, you shouldn't use constructors in classes derived from MonoBehaviour. If you need to initialize something, do it in Awake. https://ilkinulas.github.io/development/unity/2016/05/30/monobehaviour-constructor.html
Awake is the first thing that is called when a GameObject with this MonoBehaviour attached is created. Awake also runs in your main plugin class, and occurs prior to all catalog init, so it should be used for any hooks or catalog events.
Start is basically a second awake, for when you need things to happen right after the first initialization. In your main plugin class, this happens after all plugin mods are loaded in the appdomain and their metadata available through the BepInEx Chainloader
The update is called every frame if the MonoBehaviour is enabled.
This is usually the most commonly used function of scripts in Unity games, however, RoR2 does most of its logic in FixedUpdate.
Usually, if you want to do something every frame, like making sure visuals line up, you should do this here.
FixedUpdate has the frequency of the physics system; it is called every fixed frame-rate time.
This means that depending on framerate it can skip frames, or be called multiple times in one frame.
The majority of game logic runs in this update, so that it is independent of framerate.
FixedUpdate in RoR2 updates 50 times per second, or every 0.02 seconds
Same as Update but gets called after coroutines and animations. Less commonly used
Happens after component or its game object is destroyed.
You can destroy any component/game object with Object.Destroy
Happens every time your MonoBehaviour is enabled, or more likely, the GameObject is attached to is set active.
This is different from Awake or Start in that those functions only happen once
Happens every time your MonoBehaviour is disabled, or more likely, the GameObject is attached to is set inactive.
These functions are generally called from within MonoBehaviour components and are in some way related to the gameobject
Calls a function after a specified amount of time. It is for the best to avoid this method. If you want to invoke something with a delay use coroutine instead.
Calls a function after a specified amount of time and then continues to call that function with a given time interval between calls. Avoid, same as Invoke.
Starts an asynchronous process similar to a thread. Use this to repeat a function a specific number of times or Lerp a value without slowdown.
interesting article about coroutine vs threading: https://gamedev.stackexchange.com/questions/143454/unity-coroutine-vs-threads
These functions are used to add, reference, and remove components of GameObjects. If your mod is done through code, you will likely have to wrangle with these a lot.
Adds a component to an object. This also returns the component that was just added.
This can be used to add extra functionality to a game object by making it run a script that it does not currently run.
When a component is passed in, it will remove the component from the GameObject. Of course, if a GameObject is passed in, it will destroy the whole GameObject.
Get component returns a script / component that is attached to an object. This will return null if it is trying to access a component that an object does not have, and you will run into a NullReferenceException if you try to do anything with that null component.
Can be used to get other scripts on an object and access their variables and functions.
A warning, GetComponent can be a bit cpu intensive especially on objects like Characters which have a lot of components.
It is best to avoid this at runtime, and most importantly, in functions like Update or FixedUpdate.
If you want to use it, especially multiple times, generally call it once at the beginning of your code and store it in a variable.
Returns an array of all the components of the desired type attached to a GameObject.
This is guaranteed to iterate through all components of the GameObject, and should avoided even more than GetComponent
As the name implies, it iterates through all children of the GameObject and returns the first component of the desired type.
Should be avoided even more than GetComponent
Do not ever use this The power to find any object in a scene with a desired component sounds appealing, but it will iterate through every single object in the scene, searching through their components. It is a terrible p erformance killer and if you are caught using this you will be publicly shamed.
While you are free to manipulate them as much as you want through code, MonoBehaviour components were intended to use in editor. Refer to this article on how to do as such: https://risk-of-thunder.github.io/R2Wiki/Mod-Creation/C%23-Programming/Using-MonoBehaviour-Scripts-in-Editor/