这个魔方游戏的前期的实现参考了许多教程,但全部代码逻辑都是本人写的(借鉴了的都会给出原贴链接),只讲实现的思路。

已完成:

魔方的转动和魔方的动画效果,支持魔方的cfop全部公式,按按钮可转动魔方

按键盘上的alt键可用移动鼠标360无死角观察魔方

魔方中心块加了转动提示符,提示魔方是须时针转还是逆时针旋转,双击转动提示符可快速将其设为F面

魔方默认为须时针转动,按键盘上的ctrl键,可切换魔方的转动类型和提示符类型为逆时针旋转

一建打乱,魔方状态保存和复原、已支持了检测魔方的还原情况,分为魔方已还原、白色底部两层和黄色顶层翻色已完成(还有类似5种)、白色底部两层(类似5种)、白色底部十字架(类似5种)

魔方cfop公式检测与还原算法已完成(原创的),实现恩路已完成,详情请看:(14条消息) 魔方CFOP公式匹配算法_qq_39858654的博客-CSDN博客

测试图:

魔方游戏转动思路最初来源于b站的一个视频:萌新学unity可以做一个魔方玩吗?

给我提供了一个很好的思路,我要做的是一个三阶魔方,魔方的转动就是最大的问题,视频中大佬思路是:

1.先摆放27个方块形成一个魔方,然后用6个较薄的正方体作为魔方的控制器,分别置于魔方的六个面,每一个魔方控制器都与9个方块进行触碰。

2.当魔方某个面要进行旋转的时候,相当于选择了某个魔方控制器,然后被选中的魔方控制器去检测与自己产生触碰的物体,将其变成自己的子物体,控制器再去旋转,就完成对魔方某个面的旋转。

3.若选择了某一个魔方控制器,那么剩余的5个魔方控制器都不能有子物体,若有则要将之前的子物体释放,从而避免所形成的魔方控制器得到的方块面不完整。

虽然这种思路可行,但是有个很大缺点,只能对魔方的某个面进行旋转,当我想对魔方的中间进行(E、M、S)旋转时,它做不到,这个就涉及到unity触碰的判断机制:

当A物体与B物体相互触碰,若C物体去触碰A物体,unity会认为C物体触碰到了A物体和B物体。

打一个比较恰当的比喻,就是两个人触电了,你不管摸哪一个都会触电。

如果我用上述的思路,对魔方进行E、M、S的任意一个中间旋转,旋转的都是整个魔方,而不是中间块!

所以想让27个小方块形成的魔方可以随意的转动,第一个要解决的问题是:如何生成控制器?

我想出的方式是用三维坐标来判断,事实证明这种方法很有效果,感觉不但可以用于三阶,还可以用于4阶、5阶等魔方游戏的控制器判断。

首先我让三阶魔方的轴心置于(0,0,0),白色为底面,则会发现一个这样一个规律:

(a,a,-1)F         (1,a,a)R        (a,1,a)U

(a,a,1)B          (-1,a,a)L        (a,-1,a)D

若要判断F面的方块,只需让27个方块分别一下判断三维坐标的z轴是否等于-1,得到是9个符合条件的方块。

(a,0,a) E        (0,a,a) M        (a,0,a) S

若要判断E面的方块,只需让27个方块分别一下判断三维坐标的y轴是否等于0,得到是9个符合条件的中间方块。

f=S(条件)+ F(条件)        r=M(条件)+R(条件)       u=E(条件)+U(条件)

b=S(条件)+ B(条件)       l=M(条件)+L(条件)        d=E(条件)+D(条件)

若要判断f面的方块,只需让27个方块分别一下判断三维坐标的y轴是否等于0或z轴是否等于-1,得到是18个符合条件的方块。

实现后发现了一个小问题,就是旋转后魔方的坐标会有一点小误差,不会是刚等于1或0,有可能是1.001或0.0082等,所以判断前要用Mathf.Round()进行误差的去除,才能得到正确的方块数量,不然转着转着,魔方就会出现方块丢失的情况。

魔方转动是整个游戏的最核心部分,实现步骤:

1、27个魔方方块的创建,主要参考的是:Unity教程 | 手把手教你拼一个3D“魔方”,生成的只是一个模型并不能动。

2、12个魔方控制器创建,有6个面控制器和6个中心块控制器,用于控制27个方块。

3、定义了18个按钮,用一个脚本初始化了,主要参考的是:Unity:使用数组管理多个Button

4、魔方旋转动画的实现:

  1.用的是四元数插值实现的魔方动画,避免了万向锁问题,但四元数转动只转一次就没了,那就需要保存转动数值且要保持角度的连贯性,完美解决的方法是角度叠加法(我原创的)。

角度叠加法:先定义一个旋转的初始方向,顺时针转则加90,逆时针转减90,角度限制在-360度至360度之间,可以这样理解这旋转原理,记录下了上一次的角度,顺时针转加上90就得到顺时针转的目标值,逆时针转减去90就得到逆时针转的目标值。

2.魔方控制器的值不能相互影响,经过我的探索,12个魔方控制器刚好动画能互相不受影响。

3.魔方旋转动画要按时完成且还要保证转到位,用协程能很好解决这问题。

魔方动画效果代码是:

private IEnumerator RotateOverTime(Transform transformToRotate, Quaternion targetRotation, float duration)
    {
        var timePassed = 0f;
        while (timePassed < duration)
        {
            var factor = timePassed / duration;

            transformToRotate.rotation = Quaternion.Slerp(transformToRotate.rotation, targetRotation, factor);
            // 增加自上一帧起经过的时间
            timePassed += Time.deltaTime;

            // 重要的这告诉Unity在这里中断,渲染这个帧
            // 在下一帧中从这里继续
            yield return null;
        }
        // 要确保以精确值结束,请在完成时设置目标旋转修复
        transformToRotate.rotation = targetRotation;
    }

调用动画协程的方法:

StartCoroutine(RotateOverTime(mofanControlList[mofanConNum].transform,Quaternion.Euler(mofan_rotate * n1), 0.3f));

自由观察魔方实现:

在主摄像机上绑了一个脚本,让摄像机绕着魔方转,实现一种可随意观察的效果,但这也导致了一个问题,用按钮操控魔方的各个面,但分不清哪面跟哪面,于是我在魔方的中心块上加了魔方转动标示符。

魔方状态保存和复原:

用结构体定义了两个Vector3,用来保存27个魔方块的坐标和欧拉角,将魔方的对应坐标和欧拉角保存好,就可以保存好魔方的状态,后面发现用魔方块的坐标和欧拉角可以反推魔方的颜色,具体看:魔方状态检测2_qq_39858654的博客-CSDN博客

这个我列了480记录,用了一个星期左右的时间发现的。

魔方的还原情况检测:

1、先判断27个魔方块是否被还原:

当要检测某个魔方块是否被还原,也就是检测魔方块的坐标和旋转角度是否正确。

棱块坐标还原检测:

如:要检测红白棱块,可以将红色魔方块的中心块的坐标加上白色魔方块的中心块的坐标,得到红白棱块坐标。

角块坐标还原检测:

如:要检测红白绿棱块,可以将红色魔方块的中心块的坐标加上白色魔方块的中心块的坐标加上绿色魔方块的中心块的坐标,得到红白绿棱块坐标。

棱块、角块旋转角度还原检测:

只要棱块或角块的旋转角度跟魔方最中心的魔方块旋转角度一样即为已还原。

当上述两个检测通过则表示某个魔方块成功被还原,那样能实时检测20个魔方块的实时还原情况。
 

2、然后判断魔方块的还原个数,分为4、8、12、20,对不同的还原阶段,黄色顶层是否翻色成功是用黄色中心块与其它块是否在同一面

游戏的完整的代码已经在gitee上传,地址为:

智能魔方

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐