引言:人生无处不代码,无代码处不人生。今天给大家分享双人打乒乓游戏的主要开发流程。
开发版本:unity 5.3.5f
适合人群:初学Unity者
源文件链接请见文末!
开启学习之旅吧!
游戏效果预览:
玩法:两人使用W/S键,上下键来分别控制左右的挡板,当一方没有接到球时,另一方加一分
01 场景搭建
创建2D工程PingPong,并创建新场景MainScene,导入素材,完成初始场景搭建
注意工程路径最好不要有中文
注意Order in Layer可以控制sprite渲染先后顺序,数值越大,后渲染,显示在其他sprite的上面
例如:上图中间线数值为0,显示在背景数值为-1的上面
02 开发围墙
新建四个空对象,分别添加BoxCollider2D组件,并设置父对象WallGroup
使用代码控制Collider的大小和位置,新建脚本GameManager.cs
将GameManager设置为单例模式
在我们的整个游戏生命周期当中,有很多对象从始至终有且只有一个。这个唯一的实例只需要生成一次,并且直到游戏结束才需要销毁。
单例模式一般应用于管理器类,或者是一些需要持久化存在的对象。
private static GameManager _instance;
public static GameManager Instance
{
get
{
return _instance;
}
}
private void Awake()
{
_instance = this;
}
a点为世界坐标中心点,A点为屏幕坐标中心点
新建方法ResetWallPos(),在Start()里调用一次即可
void ResetWallPos()
{
//分别获取各个墙的collider组件
_upWallBoxCollider2D = _upWall.GetComponent<BoxCollider2D>();
_downWallBoxCollider2D = _downWall.GetComponent<BoxCollider2D>();
_rightWallBoxCollider2D = _rightWall.GetComponent<BoxCollider2D>();
_leftWallBoxCollider2D = _leftWall.GetComponent<BoxCollider2D>();
//new Vector2(Screen.width, Screen.height) 该点是屏幕的右上角
//Camera.main.ScreenToWorldPoint将屏幕坐标点转化为世界坐标点
//_screenToWorldPointPos就是图中的(x,y)
Vector3 _screenToWorldPointPos = Camera.main.ScreenToWorldPoint(new Vector2(Screen.width, Screen.height));
//_screenToWorldPointPos.y + 0.5f的偏差是为了让上面的墙向上偏移0.5m,以下同理
_upWall.transform.position = new Vector3(0, _screenToWorldPointPos.y + 0.5f, 0);
//设置Collider的Size属性,长度为_screenToWorldPointPos.x * 2
_upWallBoxCollider2D.size = new Vector2(_screenToWorldPointPos.x * 2, 1);
_downWall.transform.position = new Vector3(0, -_screenToWorldPointPos.y - 0.5f, 0);
_downWallBoxCollider2D.size = new Vector2(_screenToWorldPointPos.x * 2, 1);
_rightWall.transform.position = new Vector3(_screenToWorldPointPos.x + 0.5f, 0, 0);
_rightWallBoxCollider2D.size = new Vector2(1, _screenToWorldPointPos.y * 2);
_leftWall.transform.position = new Vector3(-_screenToWorldPointPos.x - 0.5f, 0, 0);
_leftWallBoxCollider2D.size = new Vector2(1, _screenToWorldPointPos.y * 2);
}
03 开发Player
新建一个2D精灵对象,标签设置为Player,设置为预制体,然后创建两个Player,即Player_Left和Player_Right
挂载Rigidbody2D和Box Collider2D组件,设置Gravity Scale为0,冻结Z轴旋转,X轴位移
Collision Detection也可以设置为continuous,防止因为速度过快而穿越player的现象
添加PlayerController.cs脚本
首先利用添加刚体速度控制挡板的上下移动
//Public 用于外部设置控制键
public KeyCode _upKey;
public KeyCode _downKey;
public float speed = 10;
private void Update()
{
//Input.GetKey()当按键不放时,一直返回true
//通过if else if来判断按键情况,并设置player运动状态
if (Input.GetKey(_upKey))
{
//通过修改Rigidbody2D.velocity刚体速度,来模拟逐渐加速的过程,可以理解为加速度
//该命令会使物体向Y轴上方移动
_rigidbody2D.velocity = new Vector2(0, speed);
}
else if (Input.GetKey(_downKey))
{
//该命令会使物体向Y轴下方移动
_rigidbody2D.velocity = new Vector2(0, -speed);
}
else
{
//不按上下键时,刚体速度设为0
_rigidbody2D.velocity = new Vector2(0, 0);
}
}
Player上下移动地按键可以在Inspector面板设置
左边的Player设置为W/S键,右边的设置为S上下键
代码控制Player的位置,使得挡板分别位于左右两边的中间,距离边缘10像素距离
在GameManager.cs中添加ResetPlayer()方法,在Start()方法中调用一次
private void ResetPlayer()
{
rightPlayerPos = Camera.main.ScreenToWorldPoint(new Vector2(Screen.width - 10, Screen.height / 2));
_rightPlayer.position = rightPlayerPos;
leftPlayerPos = Camera.main.ScreenToWorldPoint(new Vector2(10, Screen.height / 2));
_leftPlayer.position = leftPlayerPos;
}
04 开发Ball
制作小球Ball,可以将其位置放在画面中点,并设置其标签为Ball
右键Creat一个Physics2D material ,弹性设置为1
Ball上挂载脚本Wall.cs
首先实现Ball随机左右发球,InitForce()在Start()中只调用一次
private void InitForce()
{
//Random.Range随机取整值,但取不到右边的值2,可以取值0,1
int number = Random.Range(0, 2);
if (number == 1)
{
//AddForce对刚体添加一个方向的力
//Vector2.right等于new Vector2(1,0)
_rigidbody2D.AddForce(Vector2.right * 100);
}
else
{
_rigidbody2D.AddForce(-Vector2.right * 100);
}
}
当小球碰撞到挡板后,获取上下移动的速度
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.collider.CompareTag("Player"))
{
//获取Ball的Rigidbody2D组件的速度
Vector2 velocity = _rigidbody2D.velocity;
//给Ball添加一个y轴方向的刚体速度
//为了防止Ball速度,无限增加,减半增加
velocity.y = velocity.y / 2f + collision.rigidbody.velocity.y /2f;
_rigidbody2D.velocity = velocity;
}
}
控制小球运动速度,防止其速度过低,影响游戏体验
private void Update()
{
Vector2 velocity = _rigidbody2D.velocity;
if (velocity.x < 10 && velocity.x > -10 && velocity.x != 0)
{
if (velocity.x > 0)
{
velocity.x = 10;
}
else
{
velocity.x = -10;
}
_rigidbody2D.velocity = velocity;
}
}
05 设计分数
用UGUI创建两个Text用来计分,需要引入命名空间using UnityEngine.UI;
在GameManager中添加以下代码
public Text leftText;
public Text rightText;
private int leftScore;
private int rightScore;
public void ChangeScore(string name)
{
if (name == "leftWall")
{
rightScore++;
}
else if (name == "rightWall")
{
leftScore++;
}
//分数更改后,更新Text
leftText.text = leftScore.ToString();
rightText.text = rightScore.ToString();
}
在Ball.cs中调用ChangeScore方法
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.collider.CompareTag("Player"))
{
Vector2 velocity = _rigidbody2D.velocity;
velocity.y = velocity.y / 2f + collision.rigidbody.velocity.y /2f;
_rigidbody2D.velocity = velocity;
}
//当小球碰撞到左右两边的墙时,进行加分
if (collision.collider.name == "rightWall" || collision.collider.name == "leftWall")
{
//GameManager.Instance调用Gamemanager的唯一实例
GameManager.Instance.ChangeScore(collision.collider.name);
}
}
06 添加音效
在MainCamera上添加组件AudioSource,audioclip设置背景音乐ChillMusic,勾选play on awake,loop选项
为四面墙添加AudioSource组件,并为AudioClip添加Click音效,挂载Wall.cs脚本
public class Wall : MonoBehaviour
{
private AudioSource _audio;
、
private void Start()
{
_audio = GetComponent<AudioSource>();
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.collider.CompareTag("Ball"))
{
//修改音量
_audio.volume = 0.6f;
//获取随机播放音效的音调
_audio.pitch = Random.Range(0.8f, 1.2f);
_audio.Play();
}
}
}
同理为PlayerController.cs 添加如下方法 并添加hit音效
//OnCollisionEnter2D方法用于碰撞检测,is trigger不能勾选
//当发生碰撞时,将碰撞到的物体Collider信息存储在Collision中
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.collider.CompareTag("Ball"))
{
_audio.pitch = Random.Range(0.8f, 1.2f);
_audio.Play();
}
}
07 发布PC端
File-BuildSettings 点击Build完成打包,注意打包出的文件要放在同一个文件夹内
做完后,叫上你的小伙伴一起来玩吧!喜欢我的分享就关注我吧!以后会陆续分享案例教程的!
素材及工程文件百度云链接:链接:https://pan.baidu.com/s/1eT5iCcM 密码:s5w5