碰撞器及触发器的优化用法

发表于2017-09-30
评论0 1.8k浏览

在游戏项目中,我们经常会用到 碰撞器检测或者触发器检测。而我们在做检测的时候都要在物体上挂载脚本,然后添加OnTriggerEnter\OnCollisionExit等函数

而有些物体,比如英雄身上的武器、技能上的特效,需要在物体上挂载脚本 再在脚本里去做碰撞检测后的逻辑。

这样的操作维护成本太高 而且耦合性也会增加。

介于所述缺点,可以使用今天教给大家的方式试下~~

上代码:

using UnityEngine;
using System.Collections;
using System;
public class ColliderDetect : MonoBehaviour
{
    #region 事件
    public Action<GameObject> onTriggerEnterEvent;
    public Action<GameObject> onTriggerStayEvent;
    public Action<GameObject> onTriggerExitEvent;
    public Action<GameObject> onCollisionEnterEvent;
    public Action<GameObject> onCollisionStayEvent;
    public Action<GameObject> onCollisionExitEvent;
    #endregion
    /// <summary>
    /// 给物体添加BoxCollider
    /// </summary>
    public void AddBoxCollider(bool isTrigger, Vector3 center = default(Vector3), Vector3 size = default(Vector3), PhysicMaterial material = null)
    {
        Rigidbody rigidBody = GetComponent<Rigidbody>();
        if (rigidBody == null)
            rigidBody = gameObject.AddComponent<Rigidbody>();
        rigidBody.useGravity = false;
        BoxCollider collider = GetComponent<BoxCollider>();
        if (collider == null)
            collider = gameObject.AddComponent<BoxCollider>();
        collider.isTrigger = isTrigger;
        collider.center = center;
        collider.size = size;
        collider.material = material;
    }
    /// <summary>
    /// 给物体添加SphereCollider
    /// </summary>
    public void AddSphereCollider(bool isTrigger, Vector3 center = default(Vector3), float radius = default(float), PhysicMaterial material = null)
    {
        Rigidbody rigidBody = GetComponent<Rigidbody>();
        if (rigidBody == null)
            rigidBody = gameObject.AddComponent<Rigidbody>();
        rigidBody.useGravity = false;
        SphereCollider collider = GetComponent<SphereCollider>();
        if (collider == null)
            collider = gameObject.AddComponent<SphereCollider>();
        collider.isTrigger = isTrigger;
        collider.center = center;
        collider.radius = radius;
        collider.material = material;
    }
    #region 检测
    private void OnTriggerEnter(Collider other)
    {
        if (onTriggerEnterEvent != null)
            onTriggerEnterEvent(other.gameObject);
    }
    private void OnTriggerStay(Collider other)
    {
        if (onTriggerStayEvent != null)
            onTriggerStayEvent(other.gameObject);
    }
    private void OnTriggerExit(Collider other)
    {
        if (onTriggerExitEvent != null)
            onTriggerExitEvent(other.gameObject);
    }
    private void OnCollisionEnter(Collision collision)
    {
        if (onCollisionEnterEvent != null)
            onCollisionEnterEvent(collision.gameObject);
    }
    private void OnCollisionStay(Collision collision)
    {
        if (onCollisionStayEvent != null)
            onCollisionStayEvent(collision.gameObject);
    }
    private void OnCollisionExit(Collision collision)
    {
        if (onCollisionExitEvent != null)
            onCollisionExitEvent(collision.gameObject);
    }
    #endregion
}

测试脚本:

public class Test : MonoBehaviour {
    public GameObject cube;     // 需要做碰撞或触发检测的物体
    void Start()
    {
        ColliderDetect detect = cube.AddComponent<ColliderDetect>();    
        detect.AddBoxCollider(true, default(Vector3), Vector3.one);     // 添加Collider及刚体组件
        detect.onTriggerEnterEvent = OnCubeTriggerEnter;            // 监听TriggerEnter事件
    }
    void OnCubeTriggerEnter(GameObject target)
    {
        Debug.Log("OnCubeTriggerEnter "   target.name);
    }
}

测试方法:

一、在空场景里创建一个Cube和Sphere,让它俩分开点距离,我们的目的是给Cube添加触发器检测,检测是否碰撞到Sphere

二、将Test.ts脚本挂载在摄像机,给Test脚本的cube变量复制

三、拖动Sphere到Cube位置,看看是否输出了内容了呢

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引

标签: