概述
前言
最近在一家公司实习,公司用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),所以互相冲突的可能性很小,现在还没遇到过,不过一般可以用优先级和权重的方案解决,遇到了再细细研究。
最后
以上就是真实大船为你收集整理的Unity中的trigger的全部内容,希望文章能够帮你解决Unity中的trigger所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复