Unity中的trigger

来源:互联网 发布:淘宝助理无法图片搬家 编辑:程序博客网 时间:2024/05/17 01:33

前言

最近在一家公司实习,公司用unity做项目,所以开始抛弃cocos,步入unity的深坑,笔主在研究unity时,发现网上很少有人会去分析引擎内部的实现,更加偏向于“是什么”而不是“为什么”,笔主接下来的一段时间可能都会写一些关于unity的个人理解,由于看不到源码,笔主只能通过类比cocos和UE来猜想unity的实现。

trigger的概念

trigger被称之为触发器,但其实这个翻译不太准确,trigger是一种tick方法,它会在每一帧被检测,触发在程序里的概念更合适于消息传递这种场景,比如win32底层的信号量机制。

trigger的表现

在学习了unity官方的几个教程之后,我总结了一下各种类所带有的trigger方法中,基本符合如下的情况:

  • 在满足一定条件时指定函数被调用
  • 在一个周期(此处不是指update)中只会被调用一次,在进入下一次周期时标志被重置

trigger的实现

此处我会贴上我写的一小段代码,来讲述一下我对trigger的理解(由于底层代码都是由c++实现的,此处也是c++代码):

class Trigger{public:    Trigger():        _name = "",        _last = false,        _current = false    {    }    ~Trigger() = default;    void tick()    {        if(!_last)            return;        if(_current)        {            if(onTrigged != nullptr)                onTrigged();        }        _last = _current;    }    void set()    {        this->_current = true;    }    void reset()    {        this->_current = false;    }    void onTimeLineEnd()    {        reset();    }    static Trigger* create();//此处实现很多,省略private:    string _name;    bool _current;    bool _last;public:    function<void()> onTrigged;}class  TriggerMgr{public:     TriggerMgr();    ~ TriggerMgr();    void SetTrigger(const string& triggerName)    {        _triggers[triggerName]->set();    }    virtual void add(const string& triggerName,const function<void()>& func)    {        auto ret = Trigger::create();        ret->onTrigged = func;        _triggers.insert(make_pair<string,Trigger*>(triggerName,ret));    }private:    unordered_map<string,Trigger*> _triggers;};

我的理解是,unity中凡是有trigger的类,一定是实现了对底层trigger类的继承,然后能调用trigger的类,比如Collider,Animator等,内部都有一个hash表(c#中的Dictionary)来管理这些trigger,我们在添加trigger时,就是在表中加元素,然后通过多个标记来达到每个周期只执行一次的效果。

关于周期

此处的周期指的是完成一个事件的时间,比如在Collider中,这个周期指从“和碰撞体相交”到“不想交”的这段时间,我们可以在离开时这样调用:

virtual void onColliderOut(){    ...    this->TriggerMgr[triggerName]->onTimeLineEnd();    ...}

当然,主流的做法是把此处代码放到事件的回调中,在结束时调用。

关于set true

在trigger中,我们被允许使用set方法将trigger显式调用,但是却不允许将trigger取消,set false被禁用了(或许可以实现,但是没看到这样的用法),这样可能是为了有更好的封装性,trigger这样就变成了一个具有自我恢复周期,而非外部控制的bool量。

关于冲突

据我观察,unity中的trigger应该是互相独立的(一个trigger周期内可触发多个其他trigger),所以互相冲突的可能性很小,现在还没遇到过,不过一般可以用优先级和权重的方案解决,遇到了再细细研究。

0 0