03、事件响应函数(一)
一、激活销毁
void OnEnable()//每次激活脚本时调用 { print("OnEnable"); } void OnDisable()//脚本取消激活状态调用 { print("OnDisable"); } void OnDestroy()//被销毁时调用 { print("OnDestroy"); }
二、鼠标事件
/// <summary> /// 代码添加到需要变颜色的物体上 /// </summary> void OnMouseEnter()//鼠标进入游戏对象时 执行 { GetComponent<Renderer>().material.color = Color.red; } void OnMouseExit()//鼠标离开时 { GetComponent<Renderer>().material.color = Color.blue; } void OnMouseDown()//鼠标点击 { GetComponent<Renderer>().material.color = Color.yellow; } void OnMouseUp()//鼠标抬起 { GetComponent<Renderer>().material.color = Color.green; } void OnMouseDrag()//鼠标拖拽 { GetComponent<Renderer>().material.color = Color.black; } //void OnMouseOver()//持续停留在游戏对象上 //{ // GetComponent<Renderer>().material.color = Color.gray; //} //void OnMouseUpAsButton()//当鼠标在同一个GUIElement或Collider按下,在释放时调用 //{ // GetComponent<Renderer>().material.color = Color.yellow; //}
三、触发事件
触发信息检测(需要勾选Is Trigger)
(1)void OnTriggerEnter(Collider other) 当进入触发器
(2)void OnTriggerExit(Collider other) 当退出触发器
(3)void OnTriggerStay(Collider other) 当逗留触发器
例1:
void OnTriggerEnter(Collider other) { Destroy(gameObject);//销毁物体本身 Destroy(other.gameObject);//销毁被碰撞的物体 }
例2:
void OnTriggerEnter(Collider other) { //当进入触发器的时候,打开isKinematic使物体停止运动。重新定位物体的位置。再把isKinematic关闭,使物体自动下落 transform.GetComponent<Rigidbody>().isKinematic = true;//打开isKinematic transform.position = new Vector3(0, 3, 0); transform.GetComponent<Rigidbody>().isKinematic = false; }
四、碰撞器
碰撞信息检测
(1)void OnCollisionEnter(Collision other) 当进入碰撞器
(2)void OnCollisionExit(Collision other)
(3)void OnCollisionStay(Collision other)
例1:
void OnCollisionEnter(Collision other) { Destroy(gameObject);//销毁物体本身 Destroy(other.gameObject);//销毁被碰撞的物体(CollisionInfo) }
例2:
void OnCollisionStay(Collision other) { //当这两个游戏对象名字相同时 if (string.Equals("Cube",other.gameObject.name)) { print("产生火花。。"); } }
五、其他事件函数
1、OnControllerColliderHit
在移动的时,当controller碰撞到collider时OnControllerColliderHit被调用。
/// <summary> /// 这个方法用来推开角色控制器碰到的所有刚体 /// </summary> public float pushPower = 2.0F; void OnControllerColliderHit(ControllerColliderHit hit) { Rigidbody body = hit.collider.attachedRigidbody; //没有刚体,返回0 if (body == null || body.isKinematic) return; //我们不想推动在我们下边的物体。。moveDirection(当碰撞发生时,角色控制器的方向) if (hit.moveDirection.y < -0.3F) return; //根据移动方向计算推的方向 //我们只把物体推向一旁,而不是往上或往下 Vector3 pushDir = new Vector3(hit.moveDirection.x, 0, hit.moveDirection.z); //速度=推动方向*推动速度 body.velocity = pushDir * pushPower; }
2、OnJointBreak
当附在同一对象上的关节被断开时调用。
/// <summary> /// 当一个力大于这个关节的承受力时,关节将被断开。此时OnJointBreak将被调用 /// 应用到关节的力传入到breakForce /// </summary> /// <param name="breakForce"></param> void OnJoinBreak(float breakForce) { Debug.Log("Joint Broke!,force:" + breakForce); }
3、OnParticleCollision
当粒子碰到collider时被调用。这可以应用到游戏对象的伤害上(通过粒子给游戏对象带来的伤害)
这个信息发送到所有附加到 WorldParticleCollider的脚本和被击中的碰撞体上(Collider)
(1)传统粒子系统
/// <summary> /// Legacy Particle System: /// 对所有被粒子碰撞的刚体组件施加一个力。 /// 需要在Particle System的Collision→Type类型设置为World(粒子与世界中的对象相碰) /// 并开启sendCollisionMessage /// </summary> /// <param name="other"></param> void OnParticleCollision(GameObject other) { Rigidbody body = other.GetComponent<Rigidbody>(); if (body) { //受力方向 Vector3 direction = other.transform.position - transform.position; //方向标准化 direction = direction.normalized; body.AddForce(direction * 5); } }
(2)新版本粒子系统(Shuriken Particle System)
与传统粒子系统不同的是,他的信息发送到Particle Systems和Collider。
public ParticleSystem part; public List<ParticleCollisionEvent> collisionEvents; void Start() { //初始化组件(ParticleSystem)和事件 part = GetComponent<ParticleSystem>(); collisionEvents = new List<ParticleCollisionEvent>(); } void OnParticleCollision(GameObject other) { //other碰撞事件的对象,collisionEvents写碰撞事件的数组 ParticlePhysicsExtensions.GetCollisionEvents(part, other, collisionEvents); //对刚体施加力 Rigidbody rb = other.GetComponent<Rigidbody>(); int i = 0; while(i<collisionEvents.Count) { if (rb) { //方向 Vector3 pos = collisionEvents[i].intersection; //力 Vector3 force = collisionEvents[i].velocity * 10; //force相当于向量 rb.AddForce(force); } i++; } }
或者:
public ParticleSystem part; public List<ParticleCollisionEvent> collisionEvents; void Start() { //初始化组件(ParticleSystem)和事件 part = GetComponent<ParticleSystem>(); collisionEvents = new List<ParticleCollisionEvent>(); } void OnParticleCollision(GameObject other) { //定义一个整型变量存储粒子系统的Collision事件 //other碰撞事件的对象,collisionEvents写碰撞事件的数组 int numCollisionEvents = part.GetCollisionEvents(other,collisionEvents); //对刚体施加力 Rigidbody rb = other.GetComponent<Rigidbody>(); for (int i = 0; i < numCollisionEvents; i++) { if (rb) { Vector3 pos = collisionEvents[i].intersection; Vector3 force = collisionEvents[i].velocity * 10; rb.AddForce(force); } } //int i = 0; //while(i<numCollisionEvents) //{ // if (rb) // { // //方向 // Vector3 pos = collisionEvents[i].intersection; // //力 // Vector3 force = collisionEvents[i].velocity * 10; // //force相当于向量 // rb.AddForce(force); // } // i++; //} }
注(两段代码运行时都有错误:参数不能为空)
4、OnBecameVisible
当renderer(渲染器)在任何相机上可见时(在物体进入摄像机时调用)。
5、 OnBecameInvisible
renderer在任何摄像机上都不可见时调用。场景视图也要不可见才行。
6、OnLevelWasloaded
当一个新关卡被载入时此函数被调用。
void OnLevelWasloaded(int level) { if (level == 13) print("hello"); }
7、OnPreCull
相机消隐场景之前调用。
/// <summary> /// 把它赋给摄像机。所有被它渲染的物体都被翻转 /// </summary> Camera cam; void Update() { cam = GetComponent<Camera>(); } void OnPreCull() { //重置世界到相机空间的变换矩阵(世界矩阵到相机矩阵) cam.ResetWorldToCameraMatrix(); //重置投影矩阵 cam.ResetProjectionMatrix(); //Matrix4x4:标准的4x4矩阵 cam.projectionMatrix = cam.projectionMatrix * Matrix4x4.Scale(new Vector3(1, -1, 1)); } //相机渲染场景之前被调用 void OnPreRender() { //设置它为true我们可以看到翻转的物体 GL.invertCulling = true; } //在相机完成场景渲染之后被调用 void OnPostRender() { // 再设置它为false,因为我们不想作用于每个相机 GL.invertCulling = false; }
8、OnPreRender
相机渲染场景之前被调用。脚本附加到摄像机上
/// <summary> /// 这个脚本用于开启和关闭每个相机的雾 /// </summary> private bool reverFogState = false; void OnPreRender() { reverFogState = RenderSettings.fog; RenderSettings.fog = enabled; } void OnPostRender() { RenderSettings.fog = reverFogState; }
9、OnPostRender
相机完成场景渲染之后被调用。
/// <summary> /// 该脚本附加在摄像机上, /// 反转目标颜色,在游戏模式下观察效果 /// </summary> private Material mat; //常规渲染完成之后调用 public void OnPostRender() { if (!mat) { //Unity有一个内置着色器(shader),对绘图很有用 //我们现在想用一个混合模式来反转目标颜色 var shader = Shader.Find("Hidden/Internal-Colored"); mat = new Material(shader); mat.hideFlags = HideFlags.HideAndDontSave; //设置混合模式来反转目标颜色 mat.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusDstColor); mat.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.Zero); //关掉隐面消除 mat.SetInt("_Cull", (int)UnityEngine.Rendering.CullMode.Off); mat.SetInt("_ZWrite", 0); mat.SetInt("_ZTest", (int)UnityEngine.Rendering.CompareFunction.Always); } //PushMatrix方法:将投影和模型视图矩阵都保存到矩阵堆栈中 GL.PushMatrix(); //LoadOrtho方法:帮助函数建立一个正交透视变换 GL.LoadOrtho(); //激活第一个着色器 mat.SetPass(0); //在整个屏幕绘制一个方形(quad) GL.Begin(GL.QUADS); GL.Vertex3(0, 0, 0); GL.Vertex3(1, 0, 0); GL.Vertex3(1,1, 0); GL.Vertex3(0, 1, 0); GL.End(); //把投影视图矩阵和模型视图矩阵弹出堆栈。 GL.PopMatrix(); }