游戏好像因为instance_deactivate_object(id)卡住了
gamemaker吧
全部回复
仅看楼主
level 8
anheimfb 楼主
下面是简化之后的代码,一共3个对象,就是发子弹打移动的怪的,打到怪子弹消失,
(触发子弹消失的条件已经简化成y轴位置的判定了)
o_renwu(人物)
beginstep:
if keyboard_check_pressed(ord(*F*))
{
instance_create(x+60*image_xscale,y,o_zidan)
}
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
o_guai(怪)
create:
y1=y
beginstep:
if y>=y1
vspeed=-40
if y<=y1-200
vspeed=40
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
o_zidan(子弹)
create:
hspeed=20
y=o_renwu.y-110
beginstep:
if o_guai.y>y-50
{
instance_deactivate_object(id)
}
if x>room_width
instance_destroy()
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
问题是:如果连续快速按space,就有可能出现游戏卡主无法执行的情况。
经过我反复试验,好像是出现两个子弹同时满足销毁的情况就会卡住
但是不知道为什么,是不是instance_deactivate_object(id)的用法不对
2014年10月10日 05点10分 1
level 8
anheimfb 楼主
说错一句话 是连续按f键 不是space
2014年10月10日 05点10分 2
被deactivate的实例无法被摧毁
2014年10月10日 06点10分
回复 yiwei138 :。。不太懂,你说的意思是不是子弹被解散之后又执行了解散所以游戏卡主了吗
2014年10月10日 06点10分
回复 anheimfb :再次解散已被解散的实例没有问题,可能是因为子弹最后数量太多了。由于一些子弹被解散,所以其不会执行摧毁事件。你需要重新激活它们才能摧毁,可以试试在instance_destroy()前面加上instance_activate_object(id)。 总之我也不是很清楚,你先试试把
2014年10月10日 06点10分
回复 yiwei138 :刚才试了下instance_destroy()换成instance_activate_object(id),不行。我又把instance_destroy()去掉之后试了下,还是一样[抓墙]
2014年10月10日 06点10分
level 8
anheimfb 楼主
改成这样是可以的,但是我很想知道出bug的原因,
而且在我原来的游戏里解散子弹是要用with的,也就是相当于在其他实例里解散子弹,那好像就不能用 instance_destroy() @yiwei138
if o_guai.y>y-50
{
instance_destroy()
}
if x>room_width
instance_destroy()
2014年10月10日 06点10分 3
无语中。。。本来在好奇你为什么不直接用instance_destroy,还以为你故意用deactivate有什么深意。。。
2014年10月10日 06点10分
无语中。。。你直接用instance_destroy就好了嘛,还以为你故意用deactivate有什么深意。。。
2014年10月10日 06点10分
回复 yiwei138 :主要是想知道出bug的原因啊,总不能一直不用instance_deactivate_object吧,而且子弹消失的判定肯定是要用with的(要攻击判定的不只一个怪),也就是说不能用instance destroy [汗]至于无语吗
2014年10月10日 06点10分
吧务
level 13
这段代码,意义不明啊= =强烈怀疑LZ为了简化问题,删除了部分不该删除的。
好吧,那么
1、按LZ文字说明的逻辑,进行Y判断应该是判断“打到怪”虽说只要站在怪物上方攻击就会判断成立,因为没有加入X判断嘛。
2、让子弹deactivate自己,意义不明。如果真的攻击到的话,这个时候子弹应该完全消失掉,用instance_destory()就可以了。没有activate的配合,deactivate和destroy感觉相似但会吃掉你很多系统资源。
3、嗯嗯,LZ的代码在房间里存在多个o_guai的时候,估计会出问题嗯嗯
综上,LZ提出的“卡住”完全意义不明嘛,如果LZ那么想保护其他代码的话,也至少先测试到简化后的代码能正常运行并且和原始程序出现相同问题。最好还是直接发源(不管是原始的还是精简后的),这样也好测试和排查问题,贴代码出来有点……
2014年10月10日 06点10分 4
回复 anheimfb :文件名是zhuangtai_test3.gmk。
2014年10月10日 07点10分
http[汗]://pan.baidu.co[汗]m/s/1sj4oLhN 我去 刚才发链接 被删了- - 这个简化代码之后的代码就是和原代码出异样问题的代码。卡主的意思是游戏定住了,点关闭关不了,只能任务管理器关掉。求帮忙
2014年10月10日 07点10分
用deactivate的原因就是想讨论下为什么不行,这样以后游戏做大点也会避免很多麻烦。把链接里的程序打开,连续快速按f,就会出我说的情况了。真的很想知道原因,花了一上午把出bug的范围缩到这几行代码里
2014年10月10日 07点10分
回复 anheimfb :顺便,我测试时直接把keyboard_check_pressed改成keyboard_check了,这样按住F就能直接看结果。
2014年10月10日 07点10分
吧务
level 13
Please be aware that deactivating and activating instances can sometimes lead to unexpected problems. So you are strongly advised not to use this feature except for very simple situation like the ones described below.
请注意,deactivate和activatate有时会导致意想不到的问题。因此强烈建议您不要除了如下所述的这些非常简单的情况下使用此功能。
以上摘自F1帮助,及用百度翻译以后再次润色的结果。
经过测试,有以下几个解决方案,个人建议使用1,很难想象LZ会再次activate这些o_zidan:
1、将instance_deactivate_object(id)直接改为instance_destroy()。LZ现在的写法完全没有必要。
2、讲o_renwu的Begin Step事件改为常规Step事件,虽然不知道为什么,但隔一步的结果就是没有再次发生卡机。
2014年10月10日 07点10分 5
level 10
原因很简单,把o_renwu的begin step事件换成按下F键事件,就可以解决卡住现象了。
你还有一个错误:
需要加上instance_activate_object(id)
只要记得每次destroy被deactivate的实例前都要先激活它们
2014年10月10日 07点10分 6
以后尽量少用deactivate,可以的话直接用instance_destroy就够了。如果你忘记重新激活它们的话,会再游戏运行后期出现很大的麻烦
2014年10月10日 07点10分
如果没弄错的话……那个IF的永远不会成立啊,因为一个已经解散的实力是根本不会移动的;另外IF判断后的运行代码应该只有一个指令(除非大括号),也就是说销毁事件是不经判断直接执行的……以上是猜测,测试去。
2014年10月10日 08点10分
回复 q糖豆p :不过游戏中途突然重新激活这些实例的话,加上那两句还是可以保险的,不然内存又要溺出了。。。
2014年10月10日 08点10分
回复 yiwei138 :建议呢,有些格式还是保留比较好,比如句尾的分号,比如if后边是小括号和大括号……IF判断以后若果需要执行两行指令,用大括号就好了嘛
2014年10月10日 08点10分
吧务
level 13
解散实例时,它们会被判断为从游戏中移除。他们不再可见也不会执行任何事件。所以对大部分动作库和函数来说,它们不再存在。这样节省了大量的时间,但使用时要非常小心。举例来说,当你删除了某特别类型的所有实例,已解散实例没有被删除(因为它们不存在)。所以不要认为一串角色捡到的钥匙可以用来打开一个已解散的门。
以上摘自某中文版的GML
根据咱的理解,解散(Deactivate)的实例会临时消失,但没有真正消失。它不是简单的隐藏,而是运动、碰撞等大部分事件都不会再执行。但它也不是删除,因为可以通过激活(Activate)让实例重现。再考虑到连帮助里都提到这个功能仍然“有问题”的话……
建议该删除的东西就删除吧。除非是那些临时消失但以后还要冒出来的。
2014年10月10日 07点10分 7
而且解散后的保持实例,并不会移至其它房间,所以很蛋疼。。。
2014年10月10日 07点10分
吧务
level 13
另外@yiwei138 的按键F事件和咱设计的Begin Step→Step貌似都是要解决这样一个问题。不同事件的执行顺序。GM内置的执行顺序是
Begin step events 初始步
Alarm events 计时器
Keyboard, Key press, and Key release events 键盘事件
Mouse events 鼠标事件
Normal step events 标准步事件
(now all instances are set to their new positions) (各实例的位置、速度、加速度计算)
Collision events 碰撞事件
End step events 结束步
Draw events 绘制
测试到现在,暂时将结果定义在:如果生成子弹和子弹解散自己在同一步,且发生在位置计算之前,就会出现问题。将生成事件推后(即子弹在下一步才有机会解散自己),或将解散事件放在位置计算之后,测试时均为出现卡死。
2014年10月10日 08点10分 8
有道理,看来卡死是这个原因了
2014年10月10日 08点10分
回头再看这段话, 感觉算是对(Deactivate)更了解了。心里也踏实些了。还有顺便吐槽一下“测试时均为出现卡死”的为应该改成未。。。
2014年10月10日 10点10分
level 10
@q糖豆p
不过我发现如果把o_zidan的begin step换成step,也就是将解散延迟,可还是会出现卡死现象啊[疑问]
2014年10月10日 08点10分 9
level 10
2014年10月10日 08点10分 10
level 10
@q糖豆p
恩,这个我知道。一般情况下后面不加分号没什么影响的,只有在某些特殊语句比如var xxx后面我才会加分号。大括号载平时我还是会加的,不过有些情况不需要,比如:
if x=y XXXX 或者
if x=y XXXX
else XXXX
反正只需要1行指令的话就不需要使用大括号了。平常看情况省略掉这些符号可以节省不少时间呢
2014年10月10日 08点10分 11
2014年10月10日 08点10分
吧务
level 13
对啊,因为在同一步里,Begin Step创建,Step解散,到坐标计算还是会出问题。我说的是创建(o_renwu)里改Step。以下三种情况会出问题
Begin Step创建 + Begin Step解散
Begin Step创建 + Step解散
Step创建 + Step解散
其实这样推测,大概键盘创建,标准步解散也会出问题吧
2014年10月10日 08点10分 12
原来如此。。。
2014年10月10日 09点10分
level 8
anheimfb 楼主
谢谢大家积极的讨论,很喜欢这种讨论气氛@yiwei138 @q糖豆p
也找到些自己找不到的答案
改成step之后至少我确实没发现问题了。
我感觉以后都不会再用(Deactivate)了,这个函数连说明都说不好用了[汗]
现在有个新问题,
比如我要在子弹里写碰到怪就消失的代码
因为怪不只一个,我肯定要在子弹里用到with
用了with之后问题就来了,
不用instance_deactivate_object(id)的话要如何在with里撤销自己的代码?
instance_destroy应该不行吧 只能撤销自己
2014年10月10日 09点10分 13
level 10
有点不明白你在讲什么。。
如果要碰撞后消失的话直接在子弹与怪物的碰撞事件里写入instance_destroy()
如果要用代码检测碰撞的话,可以这样写:
step:
if place_meeting(x, y, o_guaiwu) instance_destroy()
2014年10月10日 09点10分 14
另外,“撤销自己的代码”是什么意思???
2014年10月10日 09点10分
回复 yiwei138 :[汗]打错2字,应该是:不用instance_deactivate_object(id)的话要如何在with里撤销自己的代码
2014年10月10日 09点10分
回复 anheimfb ::[汗]打错2字,应该是:不用instance_deactivate_object(id)的话要如何在with里撤销自己的实例
2014年10月10日 09点10分
回复 anheimfb :用with(id) instance_destroy()
2014年10月10日 09点10分
level 10
在碰撞事件里销毁怪物的话,你可以这样:
与怪物碰撞事件:
if !instance_exists(other) exit
with(other) instance_destroy()
这样可以做到在step里直接用代码检测一样的效果,也是将碰撞到的怪物销毁
@anheimfb
2014年10月10日 09点10分 15
哦 也可以,不过我很少用拖拽按钮,都是直接写代码,有利于代码封装归类
2014年10月10日 09点10分
level 10
不知不觉居然有47个评论了,平常真是难得啊。不过都只是我们3个在说话。。。我也鼓励多问问题,像这种值得讨论的问题真是很喜欢呢。。。[哈哈]
2014年10月10日 10点10分 16
恩恩
2014年10月10日 10点10分
level 9
I think you can use parent instead of with 0 0
2014年10月10日 12点10分 17
但是只有一种怪物类型的话用with可以,检测多种的话用必须用parent
2014年10月10日 13点10分
回复 yiwei138 :嗯嗯,其实是我不怎么会用with Orz。。。
2014年10月10日 13点10分
吧务
level 13
关于“子弹碰到怪物后应该消失”的问题,目前咱的参考意见是:
1;咱能遇到的情况通常是都是子弹数远多于怪物数,考虑运行效率应该让怪物来执行判断条件而不是子弹。
2;一旦检测到碰撞,怪物可以根据子弹类型完成扣血动作等,并销毁子弹
那么,在怪物上“与子弹碰撞”这个事件里,就可以直接处理成
hp=hp-other.power; //碰撞事件里的的other是直接指代碰撞到的实例,与o_zidan.power的效果是不同的
with(other){instance_destroy();} //销毁子弹实例
2014年10月10日 13点10分 18
第一点,我觉得不管碰撞事件写在实例多的还是少的都不会影响运行效率,但会影响制作效率。。。
2014年10月10日 13点10分
回复 yiwei138 :感觉好像改变碰撞源游戏速度没什么变化。。。
2014年10月10日 13点10分
回复 yiwei138 :因为你没做散弹或者弹幕……等房间里是8只怪、100发己方散弹和100发敌弹的时候就能感觉到了,如果子弹设置了Step简直卡死人。
2014年10月10日 13点10分
回复 q糖豆p :哦。。弹幕类的游戏我的确没做过。不过听说若有100个子弹与1个怪物,碰撞事件不管在子弹还是怪物其实不会有运行效率的不同。就是100个子弹同时检测1个怪物或者是1个检测100个听说没什么两样
2014年10月10日 14点10分
level 9
(插上一句)我都是在子弹与怪碰撞事件里加个destroy,不是很简单么,内些代码都是什么意思?看不懂。。。
2014年10月10日 13点10分 19
那是当你想摧毁子弹时,若想摧毁怪物就得用other,如果怪物还有很多种比如小怪,精英和boss那么还得在碰撞里检测父物件
2014年10月10日 14点10分
那是当你想摧毁子弹时,若想摧毁怪物就得用other,如果怪物还有很多种比如小怪,精英和boss那么还得在碰撞里检测父物件
2014年10月10日 14点10分
1