问题表现
问题表现
当旋转角度超过±90度时,欧拉角angle会发生突变(镜像)。
关键日志
我对2D俯视角游戏做了一段测试,一直向右旋转,以下是日志。检查存在的问题,以及可能的原因
[890] [log] [TankController] onKeyDown: 启动向右旋转
[890] 角度: 0,角度: (0, 0, 0),四元数: (0, 0, 0, 1)
[891] 角度: -1.852567240440002,角度: (0, 0, -1.852567240440002),四元数: (0, 0, -0.016165994762118024, 0.9998693217682755)
[892] 角度: -3.151274175755274,角度: (0, 0, -3.151274175755274),四元数: (0, 0, -0.027496588964432335, 0.999621897316841)
[893] 角度: -4.82240442047398,角度: (0, 0, -4.82240442047398),四元数: (0, 0, -0.04207099687944587, 0.9991146236651577)
[894] 角度: -6.369393554469093,角度: (0, 0, -6.369393554469093),四元数: (0, 0, -0.055554827840641655, 0.9984556380248432)
[895] 角度: -7.973678596229254,角度: (0, 0, -7.973678596229254),四元数: (0, 0, -0.06952733385791691, 0.9975800468366485)
[896] 角度: -9.520667730224368,角度: (0, 0, -9.520667730224368),四元数: (0, 0, -0.08298794668916183, 0.9965505510029669)
[897] 角度: -11.182248668365904,角度: (0, 0, -11.182248668365904),四元数: (0, 0, -0.09742872831862506, 0.9952425045677137)
[898] 角度: -12.710139177823004,角度: (0, 0, -12.710139177823004),四元数: (0, 0, -0.11068960150049388, 0.9938550257052896)
[899] 角度: -14.314424208199496,角度: (0, 0, -14.314424208199496),四元数: (0, 0, -0.12459229768041723, 0.9922080222204991)
[900] 角度: -15.947357192458508,角度: (0, 0, -15.947357192458508),四元数: (0, 0, -0.1387181619328161, 0.9903318996932196)
[901] 角度: -17.532543598296986,角度: (0, 0, -17.532543598296986),四元数: (0, 0, -0.15240407123188104, 0.9883182681059517)
[902] 角度: -19.13682862867347,角度: (0, 0, -19.13682862867347),四元数: (0, 0, -0.1662251672151471, 0.9860878225514684)
[903] 角度: -20.884353394311567,角度: (0, 0, -20.884353394311567),四元数: (0, 0, -0.18124312510307772, 0.9834383201822421)
[904] 角度: -22.383595961269823,角度: (0, 0, -22.383595961269823),四元数: (0, 0, -0.19409392329927222, 0.9809829503810432)
[905] 角度: -23.921035788687764,角度: (0, 0, -23.921035788687764),四元数: (0, 0, -0.20723760709814806, 0.9782906389229294)
[906] 角度: -25.47757424064372,角度: (0, 0, -25.47757424064372),四元数: (0, 0, -0.22050655467647512, 0.9753854926872302)
[907] 角度: -27.09140858898105,角度: (0, 0, -27.09140858898105),四元数: (0, 0, -0.23422093967316576, 0.9721833939224734)
[908] 角度: -28.896229262384185,角度: (0, 0, -28.896229262384185),四元数: (0, 0, -0.24950317554975224, 0.9683739801288496)
[909] 角度: -30.280880036579692,角度: (0, 0, -30.280880036579692),四元数: (0, 0, -0.26118588535394294, 0.9652885233399789)
[910] 角度: -31.875615748995326,角度: (0, 0, -31.875615748995326),四元数: (0, 0, -0.27459378505988924, 0.9615603221881004)
[911] 角度: -33.46080215483382,角度: (0, 0, -33.46080215483382),四元数: (0, 0, -0.2878686989341789, 0.9576698868472074)
[912] 角度: -35.05553787863313,角度: (0, 0, -35.05553787863313),四元数: (0, 0, -0.3011679920740851, 0.9535710988437431)
[913] 角度: -36.65027359104877,角度: (0, 0, -36.65027359104877),四元数: (0, 0, -0.3144089575348543, 0.9492876315542335)
[914] 角度: -38.25455863280894,角度: (0, 0, -38.25455863280894),四元数: (0, 0, -0.3276677651759322, 0.9447930120743961)
[915] 角度: -39.839745027263746,角度: (0, 0, -39.839745027263746),四元数: (0, 0, -0.34070566001304387, 0.9401700129418488)
[916] 角度: -41.58726980428551,角度: (0, 0, -41.58726980428551),四元数: (0, 0, -0.3550031086426755, 0.9348651201398183)
[917] 角度: -43.03876578143956,角度: (0, 0, -43.03876578143956),四元数: (0, 0, -0.3668159616009896, 0.9302935291158062)
[918] 角度: -44.63350150523887,角度: (0, 0, -44.63350150523887),四元数: (0, 0, -0.3797266337226064, 0.9250987426441015)
[919] 角度: -46.209138593116506,角度: (0, 0, -46.209138593116506),四元数: (0, 0, -0.3924104704482903, 0.9197902057983394)
[920] 角度: -47.822972941453834,角度: (0, 0, -47.822972941453834),四元数: (0, 0, -0.40532486528377143, 0.9141727154004831)
[921] 角度: -49.40815934729231,角度: (0, 0, -49.40815934729231),四元数: (0, 0, -0.4179317619195534, 0.908478421526245)
[922] 角度: -50.9933457531308,角度: (0, 0, -50.9933457531308),四元数: (0, 0, -0.4304586836242305, 0.9026102822882612)
[923] 角度: -52.79816641515027,角度: (0, 0, -52.79816641515027),四元数: (0, 0, -0.44462084680259645, 0.8957188747528669)
[924] 角度: -54.182817189345755,角度: (0, 0, -54.182817189345755),四元数: (0, 0, -0.45541141620678, 0.8902811027919973)
[925] 角度: -55.78710221972225,角度: (0, 0, -55.78710221972225),四元数: (0, 0, -0.4678303396165951, 0.8838182920341835)
[926] 角度: -57.3627393075999,角度: (0, 0, -57.3627393075999),四元数: (0, 0, -0.4799382584410825, 0.8773022672286563)
[927] 角度: -59.12936270915966,角度: (0, 0, -59.12936270915966),四元数: (0, 0, -0.4934057929271914, 0.8697992432198878)
[928] 角度: -60.54266143723767,角度: (0, 0, -60.54266143723767),四元数: (0, 0, -0.5040955405451472, 0.8636478946900153)
[929] 角度: -62.31883415675831,角度: (0, 0, -62.31883415675831),四元数: (0, 0, -0.5174210201800096, 0.8557309669959818)
[930] 角度: -63.85627397279259,角度: (0, 0, -63.85627397279259),四元数: (0, 0, -0.5288551865951123, 0.8487120781581048)
[931] 角度: -65.31731927929114,角度: (0, 0, -65.31731927929114),四元数: (0, 0, -0.5396330085007303, 0.8419003599811861)
[932] 角度: -67.02664678446955,角度: (0, 0, -67.02664678446955),四元数: (0, 0, -0.5521308797468656, 0.8337574537177778)
[933] 角度: -68.57363592984832,角度: (0, 0, -68.57363592984832),四元数: (0, 0, -0.5633359736611967, 0.8262279230207555)
[934] 角度: -70.09197712134457,角度: (0, 0, -70.09197712134457),四元数: (0, 0, -0.5742337453816203, 0.8186913983089088)
[935] 角度: -71.69626215172106,角度: (0, 0, -71.69626215172106),四元数: (0, 0, -0.5856387992226624, 0.8105721416660198)
[936] 角度: -73.24325129709986,角度: (0, 0, -73.24325129709986),四元数: (0, 0, -0.5965278469297476, 0.8025923796282641)
[937] 角度: -74.82843770293834,角度: (0, 0, -74.82843770293834),四元数: (0, 0, -0.607572967537436, 0.7942638661790891)
[938] 角度: -76.45182136923647,角度: (0, 0, -76.45182136923647),四元数: (0, 0, -0.6187637176254677, 0.785577152003742)
[939] 角度: -78.02745845711414,角度: (0, 0, -78.02745845711414),四元数: (0, 0, -0.6295065928843558, 0.7769951412429359)
[940] 角度: -79.65084212341233,角度: (0, 0, -79.65084212341233),四元数: (0, 0, -0.6404505094457654, 0.7679994433270506)
[941] 角度: -81.25512715378875,角度: (0, 0, -81.25512715378875),四元数: (0, 0, -0.6511394085199261, 0.7589581481691337)
[942] 角度: -83.18408892653184,角度: (0, 0, -83.18408892653184),四元数: (0, 0, -0.6638223742560095, 0.7478902696499764)
[943] 角度: -84.41595064750491,角度: (0, 0, -84.41595064750491),四元数: (0, 0, -0.6718236995987397, 0.7407110885206609)
[944] 角度: -86.04888363176384,角度: (0, 0, -86.04888363176384),四元数: (0, 0, -0.6823102862925674, 0.7310627012913151)
[945] 角度: -87.65316866214063,角度: (0, 0, -87.65316866214063),四元数: (0, 0, -0.6924779846302928, 0.7214390069869858)
[946] 角度: -89.24790438593982,角度: (0, 0, -89.24790438593982),四元数: (0, 0, -0.702450650297128, 0.7117324524687222)
[947] 角度: -89.10961332322378,角度: (180, 180, -89.10961332322378),四元数: (0, 0, -0.712579663493251, 0.7015912080234794)
[948] 角度: -87.54352555330738,角度: (180, 180, -87.54352555330738),四元数: (0, 0, -0.7221012510964865, 0.6917873829182555)
[949] 角度: -86.03473366838816,角度: (180, 180, -86.03473366838816),四元数: (0, 0, -0.7311469485686924, 0.6822200082075355)
[950] 角度: -84.44954726254979,角度: (180, 180, -84.44954726254979),四元数: (0, 0, -0.7405140875364491, 0.6720408366759123)
[951] 角度: -82.86436086809492,角度: (180, 180, -82.86436086809492),四元数: (0, 0, -0.7497395225324027, 0.661733064273567)
[952] 角度: -81.13593472699482,角度: (180, 180, -81.13593472699482),四元数: (0, 0, -0.7596350202344682, 0.6503496259961861)
[953] 角度: -79.55074832115638,角度: (180, 180, -79.55074832115638),四元数: (0, 0, -0.7685585730382474, 0.6397794305926168)
[954] 角度: -78.03240712966011,角度: (180, 180, -78.03240712966011),四元数: (0, 0, -0.776967955078047, 0.6295401470770852)
[955] 角度: -76.44722072382166,角度: (180, 180, -76.44722072382166),四元数: (0, 0, -0.7856019936232534, 0.6187321776141674)
[956] 角度: -74.8620343179832,角度: (180, 180, -74.8620343179832),四元数: (0, 0, -0.7940857002936408, 0.6078058082884353)
大致就是四元数正常,但欧拉角不正常。
直接怀疑引擎为了解决万向锁,内部使用了四元数,在欧拉角超过±90度时,因为四元数转换算法不同。
将(0,0,z)转换为等价的(180,180,f(z))(没算,反正就是和z有关的一个函数,单纯意思意思)这样的形式。
但对于2D游戏而言这就是极大的缺陷,明明只旋转的z轴的angle却导致了xy轴角度的修改(虽然总体等价),但这直接导致了BUG。
问题代码
代码仓库:https://cnb.cool/158com_code/tank_war_cocos
提交分支:feature-cocos
提交哈希:5896dcb249485f193c8e574ad82aecf39979679d
提交信息:chore(TankController): 添加坦克控制器旋转调试日志
提交时间:25.08.18.17:21:16 GMT+0800
问题原因
引擎使用了四元数作为游戏的底层角度。在第三四象限时,四元数解算的结果未保持xy轴旋转角度,从而导致z轴旋转角异常。
问题建议
使用四元数解决万向节锁是不错,但请不要忘了2D游戏中只有z轴,请保持z轴的旋转角度不会发生突变。
即使这可能是四元数本身的特性,但我相信改变他并不难,为了2D游戏着想,给2D游戏额外增加一个转换函数。
最起码也要给开发者提个醒,让我们知道有这么回事。

