菜单搭建

搭建一个简单的菜单界面,添加了下雨的特效

主相机配置

在主相机创建两个文本,Text。在其中设置锚点处为界面顶,如图所示:

当然,锚点也可以设置为以父节点为基准,也就是说父结点运动我们的子节点会跟着运动,关于父结点和子节点的关系:

Canvas下的都是子节点,Canvas是父结点。将物件和按钮调整到合适的位置我们加一些组件。

shadow给字体添加阴影,阴影的原理是和字体不太同一个平面内就形成了阴影,在2d中,我们的光源不可能在z轴中出现,所以说就用不同平面表示阴影。x,y表示阴影平面的偏移。

我们还需要对摄像机画面进行修改,让它可以根据我们屏幕大小缩放我们的界面,这里设置的Scale With Screen Size设置缩放。将显示设置为1k,这里Reference Resolution用于适配分辨率。Match选择用那个参考缩放,这里设置为0.5就是两者(高度和宽度)都参考缩放。

添加特效,我们需要的是下雨的特效,但是初始的时候添加发射的是框框:

这是因为我们没有设置样式,我们需要调整这个特效的样式,先看看我们的需求:

  • 需要添加下雨的样式
  • 方向改为向下
  • 雨滴需要有碰撞效果

将发射的物体形状改为Box这样就会集中向一个方向发射,然后将位置改为90度,记得重新设置一下物体的位置,按reset

调整完特效的位置之后,我们需要装上我们的样式

这里采用函数的形式循环播放我们的动画,可以理解为我们插入的都是一帧一帧的图片,然后调整函数的转化时间就可以做一个动画了:

然后设置我们的雨滴大小start size,调整完雨滴的颜色,这里需要设置一下雨滴的重力来模仿我们的现实世界。然后取消我们雨滴的反弹效果,也就是Flip Rotation修改为0.

然后设置碰撞器,让雨滴和地面有碰撞效果

然后就有动画效果了:

然后我们需要对水滴进行增光处理,建一个材质:Material

然后调整颜色和Alpha Clipping这个是不会更改原先样式,将这个材质插入到我们的组件当中:

然后建一个:Global Volume控制我们界面的光效,然后配置:

具体的功能如这个博客,然后我们就实现了功能了。

创建画画机制

在新建一个页面作为我们的选择关卡界面(但是目前关卡只有一个)。在Scence中创建一个

然后得到和我们主相机一样的界面,我们需要对其进行一些配置,首先将我们的相机背景颜色调成暗色。

我们在这个界面建立一个线条特效,名称是Line,这个特效的功能是在我们的界面上绘制线条,在对应的仪表盘可以设置线条的样式。

size是分为几个段,然后下面的Width是调整线段的宽度,然后记得点开世界坐标向量,这个的意思是依据我们摄像机的坐标来绘制我们的线条,也就是这个:

然后我们需要在我们的主界面,按住鼠标左键绘制图形。我们插入一个c#文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LineManager : MonoBehaviour
{
//获取Line
private LineRenderer lineRenderer;
//存储我们绘制的点
private List<Vector2> pointList = new List<Vector2>();

private void Start()
{
lineRenderer = GetComponent<LineRenderer>();
}


private void Update()
{
if (Input.GetMouseButton(0))
{
//获取主界面的坐标
Vector2 position = Camera.main.ScreenToWorldPoint(Input.mousePosition);
//如果当前的坐标没绘制,就绘制
if (!pointList.Contains(position))
{
pointList.Add(position);
lineRenderer.positionCount++;
lineRenderer.SetPosition(lineRenderer.positionCount - 1, position);
}
}


#region 检测按下
if (Input.GetMouseButton(0))
{
Debug.Log("按下");
}
if (Input.GetMouseButton(1))
{
Debug.Log("抬起");
}
#endregion
}
}

逻辑就是,设置一个数组它的值全为0,只要检测到我们绘制的坐标就依据我们的数组来检测它是否绘制即可。然后给我们的线加材质,新建一个材质:

补充材质的选择:Universal Render Pipeline - > Particles -> unit

然后拖入我们线中的材质选项:

然后画画

光效是由这个来判断的:Bloom 这个暂时不清楚

创建人物行走

人物是在我们划线结束的时候,前进到目标点的。所以说我们需要界定我们划线的状态:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LineManager : MonoBehaviour
{
//获取Line
private LineRenderer lineRenderer;
//存储我们绘制的点
private List<Vector2> pointList = new List<Vector2>();

//声明的默认值是什么 - 这里判断我们画完了没 刚开始错误是因为一直判断我们画完了,然后检索数组发现啥都没有
private bool isRun;

//获取玩家坐标
private Transform playerPos;

//索引
private int currentIndex = 0;

[SerializeField]
private float speed;

private void Start()
{
lineRenderer = GetComponent<LineRenderer>();

playerPos = GameObject.Find("Player").transform;
Debug.Log("Player");
}


private void Update()
{
if (Input.GetMouseButton(0))
{
//获取主界面的坐标
Vector2 position = Camera.main.ScreenToWorldPoint(Input.mousePosition);
//如果当前的坐标没绘制,就绘制
if (!pointList.Contains(position))
{
pointList.Add(position);
lineRenderer.positionCount++;
lineRenderer.SetPosition(lineRenderer.positionCount - 1, position);
}
}


#region 鼠标抬起
if (Input.GetMouseButton(0))
{
isRun = true;
}
#endregion

if (isRun)
{
//这个是移动? - 不懂这个函数
playerPos.position = Vector3.MoveTowards(playerPos.position, pointList[currentIndex], speed * Time.deltaTime);
if(Vector3.Distance(playerPos.position, pointList[currentIndex]) < 0.1f)
{
currentIndex++;
if(currentIndex >= pointList.Count)
{
//数组索引是从0开始 所以说最后一个位置是长度-1
currentIndex = pointList.Count - 1;
}
}
}

}
}

这里的执行逻辑是用isRun判断我们画完没,画完了就根据我们的playerPos.position位置和数组的位置来移动我们的player。实现完的画面:

绘制地图

创建一个Tilemap,这个是我们画布的基准,可以理解为在白色的纸上添加格子。

创建完成也就是这个样子:

然后添加我们的sprite,这里就要新建一个画布,开启位置在window处创建.

然后把精灵拖入进去,就可以对这些素材进行绘制了:

简单绘制一下我们的地图,如下:

我们多制作一个绘制表格的物件,将它作为我们的陷阱:Firmap

一个是正常的地图制件,一个是我们预备的陷阱组件,然后对它们增加一个刚体属性,让它有一定的物理属性(这里最主要的作用是让它可以给我们的脚本操控):

补充:这个组件是给物体指定的物理属性

Drag : 这个的意思是阻力,可以赋予它线性的阻力和角阻力

Mass:表示的是我们物体的质量

Gravity:物体的重力

Collision 碰撞

将刚体组件的重力表示为0,或者将之设置为静态状态:

这三个属性:动态,运动,静态。不懂?

然后设置瓦片地图碰撞器

设置 :Delaunay Mesh 这里只会在显示的范围内附加物体这些属性,可以节省性能。然后做完就是这样的效果:

制作人物动画

将我们之前创建的正方形改为我们的动画人物:

animation处制作我们的人物动画(小人移动),使用快捷键ctrl 6 打开对应的组件,然后将精灵拖入到这里面形成逐帧动画:

注意,在我们的对应的组件按ctrl 6才有这个效果,然后拖入我们两帧的图片,记得把时间间隔调为6这样就不会很快了(切换频率)

然后创建Run,原理是一样的拖入我们的组件就行。

然后配置我们的状态机,状态机是用于切换我们动画的状态。我们这里设置了三种状态,待机RunJump。下面的Has Exit Time是过度状态,

在代码中,我们将控制角色行动的操作封装为一个函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private void SetPlayerState()
{
switch (state)
{
//静止逻辑
case PlayerState.Idle:
animator.SetBool(PlayAnimStateTag.IsRun, false);
break;
//运动逻辑
case PlayerState.Run:
animator.SetBool(PlayAnimStateTag.IsRun, true);
break;
//攻击逻辑
case PlayerState.Attack:
break;
}
}

制作金币动画

同样的在Animation处我们创建关于金币的动画,老样子做三个:待机,触发,消失。

制作的流程就是:拉入精灵 - > ctrl 6 -> 拖入需要的动画图片

然后给予我们金币碰撞器,让这个金币可以被我们的小人吃掉。顺便将小人也赋予碰撞器和刚体(记得把重力关掉):

这里还要设置一下Edit Collider,就是将碰撞体调整到我们需要的大小。然后我们配置一下金币。

把金币的选项,isTrigger点起来,这里是忽略一些物理的属性。(不太懂)

我们使用标签Tag来对物品进行标识,给金币一个coin.

在玩家处,我们新建一个c#脚本对于碰撞效果编程:

1