Unity学习笔记(2)- MonoBehaviour类的生命周期及脚本报错收集

       在Unity中,脚本的职责就是做GameObject的逻辑驱动,所有需要挂载到GameObject上面的脚本,都需要继承自MonoBehaviour,MonoBehaviour是Unity中所有脚本驱动的基类(当你使用C#作为脚本语言时)。MonoBehaviour有一些事件函数会在特定的时间被调用,Unity的MonoBehaviour脚本的生命周期示意图如下:

Unity学习笔记(2)- MonoBehaviour类的生命周期及脚本报错收集_第1张图片

        需要说明的是,当脚本被绑定在GameObject上时,可以通过点选前方的复选框来决定这些事件函数是否会被激活调用。

                                  Unity学习笔记(2)- MonoBehaviour类的生命周期及脚本报错收集_第2张图片

        需要特定说明的几个函数调用时间的区分:

        Awake和Start:Awake在每次生命周期开始的时候被调用,之后会调用OnEnable函数,但是在Awake函数中如果调用this.enable=false;直接调用onDisable函数,另外你也可以在其他脚本或者逻辑直接调用this.enable=true;启动脚本,启动脚本后,会检测之前有没有调用过Start函数,如果没有,那么将调用Start函数,所以区别是Start会在Awake之后调用并且它的调用与否取决于this.enable。

       Update,FixedUpdate和LateUpdate:Update函数顾名思义,会在每一贞被调用,我们可以在这个函数中控制物体的位置从而实现物体的移动等等,但是需要注意的是,要尽量避免在Update中调用比较耗费效率的操作,因为它每帧都会被调用,同样的原则适用于FixedUpdate和LateUpdate。FixedUpdate与Update的不同在于,Update在每帧被调用,但是调用时间不确定,所以我们要实现一个物体匀速运动是,是无法通过Update准确实现的,但是我们可以在FixedUpdate中实现,因为它在确定的时间间隔中被调用,LateUpdate如图所示,它会在所有update被调用后调用,这个函数可以在我们编写ai时被使用,因为我们要当所有物体和怪物移动过后再判断物体的一些策略,比如开枪等,这个时候就可以在LateUpdate中编写,因为LateUpdate基本可以保证所有物体在本帧的移动等操作均已经完成。

关于所有事件函数api的参考可以参见:https://docs.unity3d.com/Manual/ExecutionOrder.html

      在我的框架中,为了收集脚本报错的功能,我在MonoBehaviour的基础上扩展了BaseMonoBehaviour,并让其他脚本继承自BaseMonoBehaviour,这个类后续还会扩展一些其他的全局功能。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
/*
 * 所有类的基类,逐步加入全局功能
 * 2017-5-1 收集报错信息
 */
public class BaseMonoBehaviour : MonoBehaviour {

	//输出句柄
	private System.IO.StreamWriter ExceptionStreamWriter;
	//报错文件名
	public string ExceptionFileName = "log.txt";

	void Awake () {
		ExceptionStreamWriter = new System.IO.StreamWriter (Application.persistentDataPath + "/" + ExceptionFileName);
		Debug.Log (Application.persistentDataPath + "/" + ExceptionFileName);
	}

	void Update () {
		
	}

	void OnEnable() {
		//注册报错
		Application.logMessageReceived += LogCallback;
	}

	void OnDisable() {
	}

	void OnDestroy() {
		ExceptionStreamWriter.Close ();
	}

	//收集报错
	void LogCallback(string logString, string stackTrace, LogType type) {
		if (type == LogType.Exception || type == LogType.Error) {
			ExceptionStreamWriter.WriteLine ("Logged at: " + System.DateTime.Now.ToString () + " - Log Des: " + logString + " - Trace:" + stackTrace + " - Type:"
				+ type.ToString());
		}
	}
}
       在OnEnable函数中注册收集报错函数,注意,这是Unity5新修改的注册方式,以前是通过调用函数注册,当LogCallback注册函数被调用的时候,就可以通过输出文件(或者将报错发到服务器)的方式收集报错,方便我们在游戏测试上线的过程中收集查询bug。
      最后,发现知乎上有一个关于是否要继承MonoBehaviour的讨论:https://www.zhihu.com/question/31163311,个人也有一些看法,我觉得这是个伪命题,因为当我们要把一个脚本绑定在GameObject上时,继承MonoBehaviour几乎是必须的,这样我们才能启动我们的脚本,因为Unity不是程序驱动,而是由场景驱动脚本,脚本也是资源的一部分,当我们的类是个纯逻辑类或者工具类全局类时,这时候就不必继承MonoBehaviour,当然就算继承自MonoBehaviour,它的事件函数也会因为没有绑定在GameObject上从而不会被调用,也就不存在性能问题,当然,为了代码整体的整洁和规范,可以规定只有需要绑定在GameObject上的脚本才继承自MonoBehaviour(本框架中采用baseMonoBehaviour)

      能力不足,水平有限,如有问题,欢迎讨论

       

你可能感兴趣的:(unity3d,unity初探学习笔记)