Frist Game:Sunnyland
1、安装软件与导入素材
下载
默认显示方式
window -> layout -> default
SampleScene :
Project -> 文件目录
Scene ->游戏画面
asset store -> 素材商店
在asset store下载素材 sunnyland
shift + sapace 放大窗口
2、编辑素材与Til
1.背景导入
每个格子16像素: Pixels Per Unit 16px
2.绘制瓷砖式地图
新建瓦片图层:左上角/右键 > 2D object>Tilemap
调出画板: window > 2D > Tile palette
建立瓦片文件夹管理素材
编辑素材:素材16像素/格, 编辑 Sprite Editor
切割素材:Slice >automatic自动 (效果不好,无法分出每格)
>Grid By Cell Size自定义
第一行x:16 y: 16
Apply 确认
将素材拖拽进画板Tile palette开始绘制
遇见问题:编辑完地图保存项目后,打开发现素材丢失 (为了找解决方案找了半个小时qaq)
原因:不在一个场景
解决方案:assets > scenes > scene.unity
3、图层(layer)与角
Main camera中的Size可调整视野大小
图层排序:sorting layer
图层名称排序越在下面,越在前面
order in layer 数字越大越在前
右键->2D object -> sprite(精灵)
sprite:表示在 2D 游戏中使用的精灵对象。
精灵
将角色素材拖拽到 sprite中
Add Component:
Rigibody 2D 2D刚体
Box Collider 2D碰撞体(记得Edit Collider去调整人物的绿色框不要太大)
Tilemap Collider 2D 地图碰撞格子
遇到的几个问题
1.狐狸大小-> 设置图片的 unit -> 16
2.无法移动 -> 要点到箭头才能拖动
4、角色移动
在Player中Add Component->New Scripts(脚本),命名为PlayerControler
可以创建专门的Scripts文件夹来放Scripts
打开代码文件创建一个刚体
保存后将Rigidbody 2D拖拽进Rb中绑定player(角色)来实现更改角色
Input.GetAxis 函数:用于确定移动方向
Input.GetAxis("Horizontal")表示在X轴上移动,
Input.GetAxis("Vertical")代表在z轴上移动,
可以从Edit——Project Setting——input中查看相关的设置
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerControler : MonoBehaviour
{
//声明刚体变量
public Rigidbody2D rb;
//声明速度
public float speed;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
//Update函数在游戏运行中时刻调用
void Update()
{
Movement();
}
//角色移动
void Movement()
{
float horizontalmove;
//Horizontal是u3d的水平虚拟轴,即左右,
//GetAxis为得到-1到1的数值
horizontalmove = Input.GetAxis("Horizontal");
if(horizontalmove != 0)
{
//velocity:此属性用于设置或返回刚体的速度值,vector2表示用于2D
rb.velocity = new Vector2(horizontalmove * speed, rb.velocity.y);
}
}
}
注意事项:
1.在游戏过程中更改的变量不会在结束时保存,
若需保存游戏内的更改,可以先在游戏时Copy Component,
在结束后粘贴即可(如下)
2.2D角色需要在刚体中固定Z轴,否则会晕头转向(笑)
5、角色方向与跳跃
角色方向:
Scale是缩放比例:用Transform.localScame调用
//GetAxisRwa可得到-1,0,1三个数值
float facedicretion = Input.GetAxisRaw("Horizontal"); //左右转向
//判断左右转向
if(facedicretion != 0)
{
//localScale是三维的缩放
transform.localScale = new Vector3(facedicretion,1,1);
}
注意事项:
1.人物移动时的卡顿问题:
将TileMap在现有基础上加一个CompositeCollider2D组件,并把原来的TileMapCollider2D的
Used By Composite钩上,这样每一个瓦片的碰撞框会合并到一起,然后将刚体中的Body Type
设置为静态后即可解决。
2.针对不同电脑帧率不同的问题:
将void Updatee() -> void FixedUpdate()
将rb.velocity = new Vector2(horizontalmove * speed, rb.velocity.y);
-> rb.velocity = new Vector2(horizontalmove * speed *Time.deltaTime, rb.velocity.y);
其中Time.deltaTime为百分比时间,可防止跳帧现象
跳跃:通过刚体来更改角色的Y轴
可以在刚体里调整重力
//跳跃
public float jumpforce;
//跳跃功能(Jump)
if(Input.GetButtonDown("Jump")) //如果检测到Jump按键(即空格)被按下
{
rb.velocity = new Vector2(rb.velocity.x,jumpforce * Time.deltaTime);
}
}
}
代码还存在跳跃不灵敏的问题未修改;
手感优化
官方手册里的
有关于按键手感的优化说明
FixedUpdate()每秒固定刷新帧数
6、实现动画效果(Animation与Animator)
<1>添加组件Animator,再创建一个Animator Controller命名为Player
再将Animator Controller拖拽到
在Animation窗口中创建Idle(原地站立)的动画,再从素材包中找到idle的动画全部
(多选的方法:选中一个目标,按下shift再选择最后一个目标,就可以完成多选了)
拖拽到时间轴,可以拉长时间轴或调整samples来改变播放速度。
在
中可点击Player后看见角色添加的动画
,再添加跑动的动画
再让Idle和Run之间建立联系
再给箭头设置条件
声明动画变量Anim,再将Animator拖拽到Anim中
在脚本里添加代码
7、跳跃动画
1、先用跟上节一样的原理给player添加jumping和falling的动画
2、在Animator中设置好触发条件
编写脚本,再在Update中调用即可
//转换动画
void SwitchAnim()
{
anim.SetBool("idle", false);
if (anim.GetBool("jumping") && rb.velocity.y < 0) //检测到jumping为true并且Y轴速度小于0(下落)
{
//触发下落动画
anim.SetBool("jumping" , false);
anim.SetBool("falling", true);
}
else if(coll.IsTouchingLayers(ground)) //如果接触地面
{
//触发站立动画
anim.SetBool("falling", false);
anim.SetBool("idle", true);
}
}
8、修复移动卡顿错误和优化代码
(1)给Player添加圆形碰撞体
调整两个碰撞体的大小
(2)
因为rb与anim的值不需要反复更改,所以不需让他显示在Unity中
实现方法:
9、镜头控制Cinemachine
1、给Main Camera添加脚本
2、
后将Player拖拽进此
即可实现摄像头跟随移动
3、在GameObject中打开Cinemashine创建2D摄像头,然后
调整Dead Zone Width可锁定不跟踪范围
4.锁定移动镜头范围
10、物品收集 & Prefabs
实现收集樱桃和宝石:
1、创建精灵
,给Cherry添加Animator组件,用前面创建角色的方法将樱桃实体化
2、给樱桃添加碰撞体Box,勾选Is Trigger(一个碰撞检测用的开关,不要让它有碰撞效果的意思)
//拾取物品
private void OnTriggerEnter2D(Collider2D collision) //取消碰撞触发OnTrigger事件
{
if(collision.tag == "Collection") //如果碰撞体的标签是Collection
{
Destroy(collision.gameObject); //则销毁此物体
Cherry += 1;
}
}
OnTriggerEnter2D:
- Trigger触发,取消所有的物理碰撞,可以在触发时执行OnTrigger事件。
- 想获得碰撞状态信息,又不想触发物理效果 使用OnTrigger
- 至少一方勾选 Trigger触发器
- 运动一方必须含有刚体
Prefabs预制件:
相当于模板,类与对象的关系
11、物理材质&空中跳跃
移动跳跃完美手感(终极版/可多段跳)
//跳跃
void Jump()
{
if (isGround)
{
jumpCount = 2;
isJump = false;
}
//第一段跳
if (jumpPressed && isGround) //在地面上跳跃
{
isJump = true;
rb.velocity = new Vector2(rb.velocity.x, jumpForce);
jumpCount--;
jumpPressed = false;
jumpAudio.Play(); //播放声音
}
//第二段跳
else if (jumpPressed && jumpCount > 0 && !isGround) //在天上
{
rb.velocity = new Vector2(rb.velocity.x, jumpForce);
jumpCount--;
jumpPressed = false;
jumpAudio.Play(); //播放声音
}
}
12、UI入门
UI ->Canvas :画布
1.添加Canvas ->添加Text->按F聚焦->blod,22,颜色
2.在代码中给Text修改值->赋值用到toString()
3.锁定UI位置->Text里Rect transform->左上角有个图形
13、敌人Enemy
1.添加敌人sprite,添加Enemy标签
2. 通过 private void OnCollisionEnter2D(Collision2D collision) 防范判断踩到敌人
遇到的问题:
添加了敌人未显示:添加层级,分层
14 受伤效果Hurt
1.添加碰撞逻辑 , 根据x的大小判断左右
2.设置弹出 rb.velocity = new Vector2(h, rb.velocity.y);
3.Mathf.Abs(rb.velocity.x) < 0.1 判断弹出是否结束,isHurt变量设置是否受伤状态
4.添加受伤动画 hurting 变量切换动画状态 anim.SetFloat("running", 0); 结束跑动状态
15 AI敌人移动
1.添加敌人控制代码
2.给敌人添加左右两个子object 确定左右节点
3. 代码中根据左右节点决定转向
- 拖到Perfabs 重复
问题: 滚动,原因是没有把Z轴固定
16 Animation Events动画事件
- 创建动画
2. 编写 跳落地逻辑
3. 在Idel结束帧后加入移动代码,保证动画播完
17 类的继承制作更多敌人
public class Enemy : MonoBehaviour
{
//protected仅限父子类间使用
protected Animator anim;
protected AudioSource deathAudio;
//虚方法
protected virtual void Start()
{
anim = GetComponent<Animator>();
deathAudio = GetComponent<AudioSource>();
}
//敌人死亡动画与音效
public void Death()
{
Destroy(gameObject);
}
public void JumpOn()
{
anim.SetTrigger("death");
deathAudio.Play(); //播放
}
}
18 音效Audio
添加AudioSource
Play On Awarke 自动播放
Loop 是否循环
Stereo Pan 左右耳声音量
19 对话框Dialog
添加UI ->Panel
布局
添加 text
字体
围绕中心点拖动大小 option+拖动
触发Dialog
添加boxCollider -> trigger
添加代码
EnterDialog
player添加 tag
public GameObject enterDialog; //门
OnTriggerEnter2D //碰撞事件
OnTriggerExit2D //离开事件
制作动画
add Animation
点击录制按钮,设置不同帧的样式。
FixUpdate fixedDateTime
20 趴下效果Crouch
创建下蹲按钮
edit->project setting
右上角Gimoz 可以显示碰撞体
enabled 控制碰撞体是否启用
判断点周围是否重合
Physics2D.OverlapCircle
头顶添加一个object判断上方是否有碰撞物
21 场景控制SceneManager
1.回到起点
添加一个deadobject
添加deadLine Tag
重置游戏
using UnityEngine.SceneManagement;
//延时执行
Invoke("Restart", 2f);
//重新加载场景
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
//关闭音源
GetComponent ().enabled = false;
index
file -> build Setting
加载到菜单
SceneManager.LoadScene("Menu");
25 主菜单MainMenu
1.新建Scene作为主菜单
2.添加panel作为背景,添加渐变动画
3.添加开始结束按钮,在on click()中选择函数