What is the "Messages" of this page? (Start,Update,Awake...etc)
Is is a something like virtual method or event?
Or "Messages" is one of the C# syntax?
https://docs.unity3d.com/ScriptReference/MonoBehaviour.html
The Unity engine basically calls these methods on MonoBehaviours if they are defined, depending on Engine events.
For example:
Awake is called when the script instance is being loaded.
Start is called in the first frame when the script is being enabled, before every Update method and after Awake
Update is being called in every frame
There are numerous messages as you can see it int the DOCs, and they are being called depending on engine events.
You can not call these events they are being handled by the engine!
Most commons are:
Update
Start
Awake
OnDestroy
OnEnable
But please note that using these methods(messages) while they are empty have a small overhead because the engine will call them, even if they are empty.
Another advanced thing is that some of these messages can be Coroutines. And you can give them some advanced functionality.
IEnumerator Start()
{
Debug.Log("First frame i'm being enabled! yeee");
// After 2 seconds i'm gonna blink
yield return new WaitForSeconds(2.0f);
Debug.Log("I'm going to blink");
Blink();
}
'Message' here is a synonymous for Function/Method, which are just Automatically called functions by unity engine, for any script inheriting from MonoBehaviour and attached to an ACTIVE gameobject in your scene.
Consider an animal script
public class Animal : MonoBehaviour
{
void Awake()
{
Debug.Log("Code here in awake is executed by unity the first time this object is activated, and never again in the lifetime of this object.");
}
void Start()
{
Debug.Log("Start is similar to awake but is executed after 'Awake' is executed on all game objects.");
}
void OnEnable()
{
Debug.Log("Code executed EVERYTIME your object is activated, including the first time you enter playmode, provided this object is active.");
}
void OnDisable()
{
Debug.Log("Code executed EVERYTIME your object is deactivated, does not include the first time you enter playmode if the object was disabled before playing.");
}
}
And so on, every Message/Function/Method has its use case and time, you'll get the hang of it when you start using them, they are the core of the engine.
Related
I have a prefab, which is used multiple times in my game (it will not be instatiated during runtime, I only use the prefab by dragging it into scene view to build my level).
Inside this prefab are many locations, where a specific text is written. This text is unique for every prefab.
So, it is like:
InstanceA
TextA (multiple times inside the instance)
InstanceB
TextB (multiple times inside the instance)
and so on ...
At the moment, I see two options to do it:
I change every text manually in every instance. This would work, but is a little annoying, also I can see me making mistakes (like a misspelling or forget to change one of the texts).
I solve it by a script and change the texts in the Awake or Start method. This would work, but it must be done every time, I start the game.
What I would hope for would be a solution like 2) but not every time (because nothing changes, it es every time the same) but only once - so it is generated by a script but after that, it will be always there. Even when I'm not in runtime and just work in the scene view.
Do you know any approach to get something done like this?
Thank you!
If you wish to run a piece of code outside the run-time, you can use one of the following two options.
OnValidate method
OnValidate is triggered when your MonoBehaviour script is loaded or an inspector value has changed.
using UnityEngine;
public class TestScript : MonoBehaviour
{
private void OnValidate()
{
Debug.Log("test");
}
}
ExecuteInEditMode attribute
Adding ExecuteInEditMode to a MonoBehaviour class will make it function both during and outside the runtime. If you do not wish the script to function during the runtime, feel free to also use Application.isPlaying.
using UnityEngine;
[ExecuteInEditMode]
public class TestScript : MonoBehaviour
{
private void Update()
{
if (!Application.isPlaying)
Debug.Log("test");
}
}
I'm studying C#'s Constructer and destructor with unity component system.
I'm sorry if the English of this question is weird. I used a translator cause I am not good at English.
The log output came out like this.
The Constructor log was displayed without pressing the play button. Why?
When I pressed the play button, I saw a log of something being created and immediately disappearing. I didn't write a code to create an object after the game started, where does this phrase run?
This is my code.
project working structure
Pressing the space bar brings the pre-made pre-fab to the game world,
and Prefab has a component that attached to test the constructor and
destructor.
CubeFactory.cs / when Press the space bar, It creates Prefab.
this component was attached to "GameObject" Gameobject
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CubeFactory : MonoBehaviour
{
public GameObject obj;
private int pos = 1;
void Start()
{
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
Instantiate(obj,new Vector3(pos,0,0),Quaternion.identity);
pos++;
}
}
}
ClassTest.cs / Component for Testing Constructor and Destructor. It attached Cube prefab.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ClassTest : MonoBehaviour
{
public ClassTest(){
Debug.Log("I was born!");
}
~ClassTest(){
Debug.Log("I Died x0x");
}
}
This is my project file. (I'm sorry to compress it up. I haven't learned how to use Git yet.)<
https://github.com/Scincy/UnityStudy
Please change your ClassTest.cs script to use simpler functions. Never use constructors and finalizers in Unity. What I understood from your logic is that when you press Spacebar, an object is instantiated. The ClassTest.cs is attached to this object. Better use:
void Start()
{
Debug.Log("I was born!"); //Will be called when the gameObject is active for the first time
}
Now you also want to know if the gameObject is destroyed, you can do this with another script attached to an always-active gameObject such as:
public GameObject cube;
void Update()
{
cube= GameObject.Find("Cube(Clone)"); //Depending on how your object is called
if(cube == null)
{
Debug.Log("Either not created or is destroyed");
}
}
I have used Update() which is called every frame. You could use a different function that you would like to call from another script only once.
Ye olde wisdom says that you should only use C# finalizers if your class contains a handle (IntPtr) to an object in unmanaged memory. If you're unclear what that means, then you probably don't need to be using finalizers; either way, you should never need to use them in a UnityEngine.Object-derived class.
Instead, prefer either of these Unity messages:
void OnDestroy()
{
// (1) called when the Object is about to be fully destroyed.
}
void OnDisable()
{
// (1) called when the Object is disabled in the Scene hierarchy.
// OR
// (2) called right before OnDestroy() would be called.
}
These Unity messages are of course available on MonoBehaviours, but also on all ScriptableObjects too! (For the latter, OnDisable essentially resolves to the same thing as OnDestroy since they are not Scene-bound Objects.)
Similarly, you should also avoid using C# constructors on MonoBehaviours and ScriptableObjects. The messages to prefer instead are:
void Awake()
void Start()
void OnEnable()
Each has its own quirks, so you may want to familiarize yourself with the differences and write some tests.
You can refer to the relevant documentation here: (see section header "Messages")
MonoBehaviour docs
ScriptableObject docs
This is a very amateur question and I'm not entirely sure how to title it. Essentially I want to use the OnCollisionEnter2D method for multiple (while separate) game objects in the same script, rather than a script for each separate game object.
I've tried the following with no success:
void OnCollisionEnter2D(Collision2D col)
{
if (col.gameObject.name == "Ballone")
{
charge += 1;
}
}
I believe this isn't functioning properly because it's attached to a script for my event system, but I'm not sure how to change the syntax.
OnCollisionEnter2D is an event handler.
During FixedUpdate when Unity performs collision calculations, it notifies colliders about whether they have collided and passes them the relevant Collision2D object. If that collider is attached to an object with a script component that has a OnCollisionEnter2D method, then the Collision2D object is passed into that method and the collision is handled.
In that context, it doesn't make sense for an unrelated object to handle OnCollisionEnter2D events that belong to other objects. However, you can capture the events on each object and then pass those events (or data from those events) to another more "general purpose" method in another script if you want.
E.g
Create a class and method to handle your collisions then attach it to a GameObject in the scene such as an empty GameObject named CollisionManager
class CollisionManagerScr : MonoBehaviour {
public void HandleCollision(GameObject collidingObject, Collision2D col) {
Debug.Log("I've managed this collision with " + collidingObject.name);
Debug.Log(col) // Some info about the Collision2D object
}
}
Then, attach a script to the objects that you want to check for collision on:
public class MyCollisionScript : MonoBehaviour {
private CollisionManagerScr colManager;
void Start() {
colManager = GameObject.Find("CollisionManager").GetComponent<CollisionManagerScr>();
}
void OnCollisionEnter2D(Collision2D col) {
if (col.gameObject.name.equals("Ballone")) {
if (colManager != null) {
colManager.HandleCollision(this, col); // Passes in the object that detected the collision
colManager.HandleCollision(col.gameObject, col) // Passes in the Ballone object
}
}
}
}
Now, whenever OnCollisionEnter2D is triggered for those objects, it calls HandleCollision. HandleCollision can then do whatever you want it to do. There undoubtedly is a use case for something like this but it smells a lot like unnecessary abstraction to me.
Please bear in mind that I wrote this on the fly so there could be problems/typos etc. Also, this is just one potential approach. You could also implement an approach that is effectively the same using EventHandlers etc. but that is just adding an additional event handling layer to the existing event handling layer.
I'm writing a game with some animations, and use those animations when the user clicks on a button. I would like to show the user the animation, and not "just" call a new level with Application.loadLevel. I thought I could use the Time.DeltaTime in the onMouseUp method and add it to a predefined 0f value, then check if it is bigger than (for example) 1f, but it just won't work as the onMouseUp method adds just "it's own time" as the delta time.
My script looks like this now:
public class ClickScriptAnim : MonoBehaviour {
public Sprite pressedBtn;
public Sprite btn;
public GameObject target;
public string message;
public Transform mesh;
private bool inAnim = true;
private Animator animator;
private float inGameTime = 0f;
// Use this for initialization
void Start () {
animator = mesh.GetComponent<Animator>();
}
// Update is called once per frame
void Update () {
}
void OnMouseDown() {
animator.SetBool("callAnim", true);
}
void OnMouseUp() {
animator.SetBool("callAnim", false);
animator.SetBool("callGoAway", true);
float animTime = Time.deltaTime;
Debug.Log(inGameTime.ToString());
// I would like to put here something to wait some seconds
target.SendMessage(message, SendMessageOptions.RequireReceiver);
}
}
}
Im not entirely sure what your trying to do by using Time.deltaTime in onMouseUp. This is just the time in seconds since the last frame was rendered, and should act the same no matter where you try to access it. Normally it is used in a function that is called every frame, not one-off events like onMouseUp.
Despite not being certain what you are trying to achieve, it sounds like you should be using Invoke:
http://docs.unity3d.com/ScriptReference/MonoBehaviour.Invoke.html
Just put the code you wish to be delayed into a separate function, and then invoke that function with a delay in onMouseUp.
EDIT: To backup what some others have said here I would not use Thread.Sleep() in this instance.
You want to do this (and all waiting functions that do not appear to make the game "freeze") by blocking the Update loop by using a Coroutine.
Here is a sample of what you are probably looking for.
void OnMouseUp()
{
animator.SetBool("callAnim", false);
animator.SetBool("callGoAway", true);
//Removed the assignement of Time.deltaTime as it did nothing for you...
StartCoroutine(DelayedCoroutine());
}
IEnumerator DoSomethingAfterDelay()
{
yield return new WaitForSeconds(1f); // The parameter is the number of seconds to wait
target.SendMessage(message, SendMessageOptions.RequireReceiver);
}
Based on your example it is difficult to determine exactly what you want to accomplish but the above example is the "correct" way to do something after a delay in Unity 3D. If you wanted to delay your animation, simply place the calling code in the Coroutine as I did the SendMessage invocation.
The coroutine is launched on it's own special game loop that is somewhat concurrent to your game's Update loop. These are very useful for many different things and offer a type of "threading" (albeit not real threading).
NOTE:
Do NOT use Thread.Sleep() in Unity, it will literally freeze the game loop and could cause a crash if done at a bad time. Unity games run on a single thread that handles all of the lifecycle events (Awake(), Start(), Update(), etc...). Calling Thread.Sleep() will stop the execution of these events until it returns and is most likely NOT what you're looking for as it will appear that the game has frozen and cause a bad user experience.
I'm having a bit of trouble with Unity 3D's Component-based design model.
Here's an example that demonstrates my problem:
class MyComponent : MonoBehaviour
{
MyType entity;
void Start()
{
entity = (MyType)FindObjectsOfType(typeof(MyType)).First();
}
void MyMethod()
{
var x = entity.SomeProperty; // <= NullReference exception
}
}
// ....
var clone = (GameObject)Instantiate(original);
clone.GetComponent<MyComponent>().MyMethod();
Sometimes, not always though, MyMethod executes before Start so what I end up doing is move all the initializations I usually have in Start to MyMethod which is quite an ugly workaround:
void Start() { }
void MyMethod()
{
entity = (MyType)FindObjectsOfType(typeof(MyType)).First();
var x = entity.SomeProperty; // <= now it's fine.
}
My question is, what is the correct way of working with this pattern (without a constructor)?
That probably happens when you call MyMethod from the Awake of another Component, because Awake is called before the game starts. The only solution I see is to make sure that you don't call methods on other components (in this case MyMethod) in the Awake() event, but rather in the Start() event.
The Unity documentation says "Awake is called before the game starts" but this is not precise. A component's Awake method is called when in a scene the gameobject becomes active which carries the component.
Some gameobjects will be active by default when a scene is loaded, but other gameobjects might be activated later. Then there is the possibility of dynamically adding components via AddComponent.
This aspect should be kept in mind when relying on dependencies between Awake and Start methods. Another example for a race condition is to enable a component from the Update method. While enabling a component implies that its Start method will be called, this will not happen in the running update cycle, so that other components cannot rely on the first component's ".enabled" property to determine wheter it has been started or not.