Unity3D基础案例-双人乒乓

引言:人生无处不代码,无代码处不人生。今天给大家分享双人打乒乓游戏的主要开发流程。

开发版本: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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值