找回密码
 立即注册
查看: 261|回复: 0

unity基础案例讲解:创建旋转的魔方

[复制链接]
发表于 2022-12-20 10:44 | 显示全部楼层 |阅读模式
笼中窥梦

最近,我在玩一款游戏——笼中窥梦,对其中的正方体不同面显示不同场景的功能非常感兴趣。我特地研究了一下,最终做出了这个魔方案例。

如果你想要实现这个功能,首先要了解Unity中的渲染流程。在渲染过程中,有一个模板测试的流程,利用模板测试原理可以剔除不想显示的部分。

首先,你需要一个魔方模型


这个魔方必须每个面的材质都不一样,这样才能使用不同的材质球去控制显示不同的画面。
完成这个需求,你需要创建6个不一样的场景,每个场景对应魔方的一个面


正常情况下六个不一样的场景是会直接重合在一起显示的,这时候我们创建Shader来控制他们的渲染这里用的工具是AmplifyShaderEditor一个Unity的可视化Shader编辑器。
在AmplifyShader中创建1个Shader,然后创建Texture Sample作为场景的颜色贴图,之后依次设置图片中这些选项


场景AmplifyShaderEditor设置图
然后把他赋值给场景的材质球
对这个项目感兴趣的小伙伴可以直接加到我微信拿到资料, 还有针对不同游戏的免费5天训练营可以参加,提高自己的项目实操经验
然后创建把这个Shader复制5分份,修改Reference值为2-6










之后把这些shader分别赋值给6个场景的材质球。
这时候所有的场景都会消失不见,然后我们开始处理魔方的材质。
同样的在AmplifyShader中创建1个Shader,以此设置图标中的这些选项


魔方AmplifyShaderEditor设置图
一样的分别复制5份分别修改Reference值为2-5,分别拖拽赋值给魔方的6个面材质球。
这时候就已经成功实现了魔方六个面显示不同场景的效果。
是不是感觉很神奇,其实利用到的原理很简单,这里主要用到的就是StencilBuffer(模板缓冲)的原理,


首先我们在场景AmplifyShaderEditor设置图可以看到5个设置,设置1和设置2就是关于模板测试的设置,我们给场景设置的是条件是只有模板缓冲区中的值等于Reference的值才能通过模板测试,那为什么把Shader赋值给场景的材质球之后场景整个就消失掉了呢?
原因很简单因为模板缓冲区中的值默认是0的而我们给场景设置的条件值为1-6所以正常情况下场景是无法通过模板测试的。然后我们再看魔方AmplifyShaderEditor设置图中的的1-3设置选项,2设置通过模板测试的条件我们选的是Always此选项的是必定通过模板测试,1设置为通过模板测试的行为,我们选的是Replace此选项会用自身的Reference替换掉蒙缓冲区中的值,这样魔方区域中模板缓冲区的值就被替换成了魔方六个面中对应的Replace值,魔方的六个面就能显示出对应的场景了。
但是现在还有一个问题怎样保证魔方先被渲染呢?其实也很间的,我们可以直接通过设置RenderQueue和QueueIndex来控制渲染顺序。分别是场景AmplifyShaderEditor设置图中的3、4设置和魔方AmplifyShaderEditor设置图中的5、6设置。
魔方6个面显示不同的场景实现了,接下来就是实现魔方的转动功能。
我这里是根据鼠标点击的位置和滑动的方向来判断魔方旋转的区域和方向,这里是利用射线检测获取点击到的小正方体,计算鼠标滑动的方向与小正方体的法线的夹角来判断魔方旋转的方向,然后根据被点击的小正方体的坐标获取需要旋转的魔方,代码如下
/// <summary>
/// 判断鼠标滑动
/// </summary>
private void RoateRubikCubeChild()
{
if (Input.GetMouseButtonDown(0))
{
//从鼠标点击的位置发射一根射线
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
//获取射线目标点物体
RaycastHit hit;
//从屏幕点击的位置发射一根射线
if (Physics.Raycast(ray.origin, ray.direction, out hit, 100f, 1 << layerID))
{
//被点击的物体
cubeObject = hit.transform.gameObject;
//获得点击物体的法线
normal = hit.normal;
//获取射线击中物体的点
mouseStart = hit.point;
}
}
//如果鼠标左键按下,并且鼠标点击到魔方上的物体
if (Input.GetMouseButton(0) && cubeObject != null)
{
//从鼠标点击的位置发射一根射线
Ray rayRun = Camera.main.ScreenPointToRay(Input.mousePosition);
//获取射线目标点物体
RaycastHit hitRun;
//从屏幕点击的位置发射一根射线
if (Physics.Raycast(rayRun.origin, rayRun.direction, out hitRun, 100f, 1 << layerID))
{
//获取鼠标拖动的方向,获取的方法当前就是鼠标点击到的点减去最初点击的点
mouseRun = hitRun.point - mouseStart;
//通过判断滑动的长度来确定是点击还是滑动
if (mouseRun.sqrMagnitude > 0.3f)
{
//鼠标点击到的物体的法线与鼠标拖动的方向来判断旋转的轴向
mouseCross = Vector3.Cross(normal, mouseRun).normalized;
//调用旋转函数
Rotate(mouseCross);
cubeObject = null;
}
}
}
}
private void Rotate(Vector3 mouseCross)
{
axis = Axis.None;
//计算鼠标滑动的方向和魔方之间的夹角,判断夹角的大小来决定旋转的方向
float angleX = Vector3.Angle(mouseCross, transform.right);
float angleY = Vector3.Angle(mouseCross, transform.up);
float angleZ = Vector3.Angle(mouseCross, -transform.forward);
float angle = 0;
if (angleX < 30 || angleX > 150)
{
axis = Axis.X;
angle = angleX;
dir = transform.right;
}
else if (angleY < 30 || angleY > 150)
{
axis = Axis.Y;
angle = angleY;
dir = transform.up;
}
else if (angleZ < 30 || angleZ > 150) {
axis = Axis.Z;
angle = angleZ;
dir = -transform.forward;
}
cw = angle < 30;
//点击到的方块上挂载的脚本
RubikCubeChild child = cubeObject.GetComponent<RubikCubeChild>();
if (child != null && axis != Axis.None)
{
//旋转的信息
RoateRecord record = new RoateRecord(axis, cw);  
switch (axis)
{
case Axis.X:
foreach (var item in cubes)
{
//遍历魔方的27个小正方形,判断坐标位置
if (item.Pos.x == child.Pos.x)
{
item.gameObject.transform.SetParent(center.transform);
RotateList.Add(item);
}
}
record.val = child.Pos.x;
break;
case Axis.Y:
foreach (var item in cubes)
{
if (item.Pos.y == child.Pos.y)
{
item.gameObject.transform.SetParent(center.transform);
RotateList.Add(item);
}
}
record.val = child.Pos.y;
break;
case Axis.Z:
foreach (var item in cubes)
{
if (item.Pos.z == child.Pos.z)
{
item.gameObject.transform.SetParent(center.transform);
RotateList.Add(item);
}
}
record.val = child.Pos.z;
break;
}
finish = false;
//记录旋转的记录
records.Push(record);
}
}
通过这个案例,我们可以看到Unity的强大功能。它不仅可以用于创建游戏,还可以用于开发各种交互式应用程序。

使用Unity创建魔方游戏,除了需要理解渲染流程和模板测试原理之外,还需要掌握一些其他技术。比如,你需要熟悉3D模型的创建和导入,了解如何在Unity中设置场景和相机,以及如何在Unity中使用材质球和Shader来控制物体的外观。

除了上述技术之外,使用Unity创建魔方游戏还需要掌握一些其他技术。

比如,你需要熟悉Unity中的物理系统,以便让魔方能够进行真实的旋转。这样,玩家扭动魔方时,它就会有真实的物理反馈,更加逼真。

此外,你还需要了解如何在Unity中使用脚本来控制游戏流程。通过脚本,你可以设定游戏的规则,比如定义魔方完成的条件,或者判断玩家的行为是否合法等。

另外,如果你想要让你的游戏更加美观,可以使用Unity中的后期处理效果。例如,你可以使用辉光效果,让魔方在旋转时产生漂亮的光芒;或者使用阴影效果,让魔方和场景产生真实的阴影。这些效果能够大大提高游戏的视觉效果,增加玩家的体验。

如果你对游戏开发感兴趣,并且想要学习如何使用Unity创建游戏,可以点击这里领取免费的制作游戏素材包。这个素材包包含了所有你需要的资源,包括此处魔方案例的源文件

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-4-28 02:00 , Processed in 0.115333 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表