转载请注明出处:https://blog.csdn.net/weixin_44013533/article/details/130233098
视频参考 极客学院Unity3D视频精讲课程
可以看到MonoBehaviour继承自Component,Component继承自Object
MonoBehaviour官网API
之前学的start awake等都是Message事件响应函数,它们都是我们在脚本中直接使用的回调函数
比较好懂
// 删除gameObject
Destroy(gameObject);
// Removes this script instance from the game object
Destroy(this);
// Removes the rigidbody from the game object
Destroy(GetComponent<Rigidbody>());
// Kills the game object in 5 seconds after loading the object 延迟删除)
Destroy(gameObject, 5);
注意:
public static void DestroyImmediate (Object obj, bool allowDestroyingAssets= false);
Object.Destroy
。Destroy 始终延迟进行 (但在同一帧内执行)。 使用该函数时要务必小心,因为它可以永久销毁资源! 另请注意,切勿循环访问数组并销毁正在迭代的元素。这会导致严重的问题(这是一条通用的编程实践,而不仅仅是在 Unity 中)。public static void DontDestroyOnLoad (Object target);
在加载新的 Scene 时,请勿销毁 Object。(scene切换时会释放老场景内存,如果想不释放某个对象,就可以用这个方法)
void Start()
{
DontDestroyOnLoad(gameObject);
}
// Update is called once per frame
[System.Obsolete]
void Update()
{
if(Input.GetKey(KeyCode.Space)){
//Application.LoadLevel("emp");
Application.LoadLevel(1);
}
}
可以用场景名称,也可以用scenes in build中scene的index
如图,实现点击空格切换场景,但脚本所绑定的cube未被释放内存(这个方法可以用在比如切换场景但背景音乐丝滑过渡的场合)
注意:
void Start()
{
DontDestroyOnLoad(GetComponent<Rigidbody>());
}
脚本绑定到cube
但如果但将脚本挂cube(1)或者cube(2)上,则DontDestroyOnLoad对这三个cube都不产生效果,所以要求不释放内存的对象没有父对象
public static Object Instantiate (Object original);
public static Object Instantiate (Object original, Transform parent);
public static Object Instantiate (Object original, Transform parent, bool instantiateInWorldSpace);
public static Object Instantiate (Object original, Vector3 position, Quaternion rotation);
public static Object Instantiate (Object original, Vector3 position, Quaternion rotation, Transform parent);
参数
描述
克隆 original 对象并返回克隆对象。
此函数会通过与编辑器中的复制命令类似的方式创建对象的副本。如果要克隆 GameObject,则可以指定其位置和旋转(否则,这些默认为原始 GameObject 的位置和旋转)。如果要克隆 Component,则也会克隆它附加到的 GameObject(同样可指定可选的位置和旋转)。
克隆 GameObject 或 Component 时,也将克隆所有子对象和组件,它们的属性设置与原始对象相同。
注意
public Object obj;
void Update()
{
if(Input.GetKeyDown(KeyCode.Space)){
//Quaternion.identity:旋转角默认0
Object.Instantiate(obj,new Vector3(0,5,0),Quaternion.identity);
}
}
添加物体自销毁、施加一个脉冲力
public float survivalTime = 3;
void Start()
{
Destroy(gameObject,survivalTime);
}
public Rigidbody rig;
void Update()
{
if(Input.GetKeyDown(KeyCode.Space)){
//Quaternion.identity:旋转角默认0
// 声明为Rigidbody,注意这里输入的是Rigibody,返回的也是Rigibody,如果输入GameObject输出Rigibody,会报NullReferenceException异常
Rigidbody copyRig = Object.Instantiate(rig,new Vector3(0,5,0),Quaternion.identity) as Rigidbody;
copyRig.AddForce(Vector3.forward*5,ForceMode.Impulse);
}
}
Component.tag和GameObject.tag都表示此游戏对象的标签。
public bool CompareTag (string tag);
Checks the GameObject’s tag against the defined tag.
注意比较tag有两种方法
使用场景:只要我们得到了一个类的引用,便可以向它的子类/类本身/父类传递某些消息,最终达到直接执行某个函数的目的,这样非常方便实现一个引用,简化开发复杂程度。
public void SendMessage (string methodName);
public void SendMessage (string methodName, object value);
public void SendMessage (string methodName, object value, SendMessageOptions options);
public void SendMessage (string methodName, SendMessageOptions options);
参数
描述
调用此游戏对象中的每个 MonoBehaviour 上名为 methodName 的方法。
通过具有零参数,该接收方法可选择忽略此参数。 如果选项设置为 SendMessageOptions.RequireReceiver,则在任何组件均未拾取此消息时输出错误。
注意,不会将消息发送到非活动对象(即,在 Editor 中或使用 GameObject.SetActive 函数已停用的对象)。
public void SendMessageUpwards (string methodName, SendMessageOptions options);
public void SendMessageUpwards (string methodName, object value= null, SendMessageOptions options= SendMessageOptions.RequireReceiver);
调用此游戏对象中的每个 MonoBehaviour 上或此行为的每个父级上名为 methodName 的方法。
public void BroadcastMessage (string methodName, object parameter= null, SendMessageOptions options= SendMessageOptions.RequireReceiver);
public void BroadcastMessage (string methodName, SendMessageOptions options);
调用此游戏对象或其任何子项中的每个 MonoBehaviour 上名为 methodName 的方法。
up说比如足球踢到某个物体,那么就可以用这个方法触发被状物体的某个函数。
这几个方法使用的是反射方式,类似监听者模式,是官方提供的方法,后续应该会有自己实现的更高效的使用监听者模式实现的方法(delegate +event方式)。
这个sendMessage看起来非常重要,后续花个时间做个专题,这里就简单过一下。
public void Invoke (string methodName, float time);
在 time 秒后调用 methodName 方法。
注意:
public GameObject obj;
public GameObject obj2;
public float timeDelay = 2;
public float myTimeScale = 1;
// Update is called once per frame
void Update()
{
Time.timeScale = myTimeScale;
if(Input.GetKeyDown(KeyCode.Space)){
Object.Instantiate(obj2,new Vector3(0,5,0),Quaternion.identity);
Invoke("spawnCube",timeDelay);
}
}
void spawnCube(){
GameObject copyObj = Object.Instantiate(obj,new Vector3(0,5,0),Quaternion.identity);
Rigidbody rig = copyObj.GetComponent<Rigidbody>();
rig.AddForce(Vector3.forward*5,ForceMode.Impulse);
}
private void OnGUI() {
GUILayout.TextArea("gameTime:" + Time.time.ToString());
GUILayout.TextArea("realTime:" + Time.realtimeSinceStartup.ToString());
}
public void InvokeRepeating (string methodName, float time, float repeatRate);
在 time
秒后调用 methodName
方法,然后每repeatRate
秒调用一次。
*注意:*如果将时间刻度设置为 0,该函数不起作用。
public void CancelInvoke ();
取消该 MonoBehaviour 上的所有 Invoke 调用。
public bool IsInvoking (string methodName);
是否有任何待处理的 methodName
调用?
Coroutine协同执行程序
参数IEnumerator对象,通常有三种方式获得。
public Coroutine StartCoroutine (IEnumerator routine);
启动协程。
public float step = 0.01f;
private void OnMouseDown() {
StartCoroutine(Move(step));
}
IEnumerator Move(float step){
for(int i=0;i<500;i++){
this.transform.Translate(step,0,0);
yield return null;
}
this.transform.position = new Vector3(0,1,0);
Debug.Log(this.name +"移动结束");
}
public void StopAllCoroutines ();
停止在该行为上运行的所有协同程序。
public void StopCoroutine (string methodName);
public void StopCoroutine (IEnumerator routine);
public void StopCoroutine (Coroutine routine);
停止在该行为上运行的第一个名为 methodName 的协同程序或存储在 routine 中的协同程序。
这里message传递,协程和方法延迟调用这三个还有待继续深入