Unity学习笔记:坦克大战

前言

本学习笔记跟着SiKi学院Trigger老师的Unity公开课进行学习
比较老的教程,适合初出茅庐的小白
B站公开课网址
素材百度云链接 密码:exqi


1.素材导入

在素材中找到这样以.unitypackage后缀命名的文件, 然后将其拖到Unity界面方可导入素材, 其中包含该游戏制作需要使用的音频素材, 图片素材等.
在这里插入图片描述
图片素材有可能是单个素材; 有可能是同一个素材的不同形态的集合; 也有可能是一个素材的动画的不同帧的集合; 也有可能是多个素材的集合.
对于多素材组成的图片, 就需要进行切割后才能使用,
在这里插入图片描述

2.素材切割与预制体

将纹理类型设置为Sprite(2D和UI)
将Sprite模式设置为 多个
点击Sprite Editor

Sprite Editor界面:

在这里插入图片描述
左上角设置栏, 右下角可以设置每张素材的像素点和切割起始点, 注意, 默认起始点在左下角, 即坐标轴的原点. 切割完毕后, 图片被分为多个素材, 打开图片左边的箭头就可以访问任意一个素材.对于不需要任何动画的(静态的)图片素材, 可以直接从项目一栏将需要的素材拖到层级中, 而对于随帧不断变化的图片素材(动态的), 就需要一次选定多个图片素材然后拖动.

素材需要进行备份, 以便多次进行调用的时候可以快速提取(预制体), 在项目一栏新建Scenes(场景)文件夹, 将层级中的素材拖到Scenes文件夹中, 完成预制体后, 素材左边的方块会变成蓝色.
在这里插入图片描述
在这里插入图片描述

3.让坦克动起来

在项目一栏中建立scripts(精灵)文件夹, 用C#设置场景中物件的各种属性, 行为. 右键选择新建-C#脚本, 命名为与物件相同名字, 默认套用了三个命名空间, 上面两个是.NET的接口, 下面的是Unity制作使用的接口.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

另外包含一个与精灵同名的类, 和两个函数, 主要用于编写精灵的行为, Start()函数表示精灵在刚开始被调用时发生的行为, Update()函数表示之后发生的一系列行为和触发器.
在Update()函数下写这些:

//新增属性
private float moveSpeed = 3;

void Update() 
{
   
	float h = Input.GetAxisRaw("Horizontal");
	transform.Translate(Vector3.right * h * moveSpeed * Time.deltaTime, Space.World);

	float v = Input.GetAxisRaw("Vertical");
	transform.Translate(Vector3.up * v * moveSpeed * Time.deltaTime, Space.World);
}

h设置为水平方向输出,当键盘输入→或←的时候h等于1或-1.
v设置为垂直方向输出,当键盘输入↑或↓的时候v等于1或-1.

注: 如果使用GetAxis(), 返回的值就是一个类似加速度的量0->1或0->-1.类似于开车和刹车.
Transform.translate函数为unity三种移动方式之一
参数:

Vector3.right * h * moveSpeed * Time.delteTime 这是一个矢量, 表示物体运动的方向+速度.
Vector3.right 表示水平方向, 如果right改为up就是垂直方向.
moveSpeed 全局变量, 表示移动速度, 其值为3.
Time.deltaTime 时间单位. deltaTime代表一帧.
Space.world 相对坐标系, 如果不填写, 默认为自身坐标系Space.Self.

坦克现在可以移动了, 但是他的方向并不会改变, 原因是我们并没有设置它在不同情况下的朝向.

4.让坦克转弯

控制坦克贴图的组件是SpriteRenderer, 我们已经有了坦克不同方向的贴图, 只需要在按下不同方向键时把坦克改为对应贴图即可, 因此我们需要取得SpriteRenderer组件的使用权. 首先定义私有变量sr用于控制SpriteRenderer, 建立一个数组, 用于存放变换的几张贴图, 也就是坦克的不同朝向的图片, 在程序中定义Awake函数:

//新增属性
private SpriteRenderer sr; 
//新增引用
public Sprite[] tankSprite; //指向坦克四个方向贴图 up right down left 转弯切换图片

private void Awake() 
{
   
	sr = GetComponent<SpriteRenderer>();
}

定义了数组以后就可以看到脚本下多了一项tankSprite组件, 可以用来存放贴图, 将贴图放入.
在这里插入图片描述
这四张图片分别对应 上 右 下 左.
之后将Update函数写成这样:

Update() 
{
   
	float h = Input.GetAxisRaw("Horizontal");//水平方向输入

    transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);//(水平方向 * 左/右 * 速度 * 时间 , 坐标系)

    if (h < 0)
    {
   
        sr.sprite = tankSprite[3];
    }
    if (h > 0)
    {
   
        sr.sprite = tankSprite[1];
    }
    if (h != 0) //这一步的目的是防止坦克同时横向纵向移动造成漂移
    {
   
        return;
    }
        
	float v = Input.GetAxisRaw("Vertical");//垂直方向输入

    transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);//(垂直方向 * 上/下 * 速度 * 时间 , 坐标系)

    if (v < 0)
    {
   
        sr.sprite = tankSprite[2];
    }
    if (v > 0)
    {
   
        sr.sprite = tankSprite[0];
    }
}

意为:
h>0 => 贴图变为向右; h<0 => 贴图变为向左;
v>0 => 贴图变为向上; v<0 => 贴图变为向下;

5.添加碰撞体

实际上, 图片左边的预览栏的实体都不是预设的, 真正预设一栏放在右边的预制体文件夹下(Scenes), 在预制体中做的操作可以实时反应到预览中, 而在预览中做的操作需要事后保存到预制体中. 打开预制体栏, 选择Walls文件夹下的全部预制体, 将Grass留出(Grass为可穿透物体)

添加组件
2D 物理
2D盒状碰撞器(Box Collider 2D)

在这里插入图片描述
打开Tanks文件夹, 选择Player, 重复上述操作. 给我们控制的坦克也加上碰撞体, 毕竟碰撞是两个物体接触才能发生的. 另外, 还需要给我们的坦克加上刚体这一属性

添加组件
2D 物理
2D 刚体(Rigidbody 2D)

修复碰撞bug, 现在的坦克与墙体发生碰撞时会偶尔进入对方, 发生抖动, 这是因为坦克移动的每一帧都是由电脑性能决定的, 电脑性能高, 坦克移动就平稳, 反之颠簸. 但电脑性能在不同时间又是不同的, 为此, 我们需要一个稳定的帧数, 打开Player脚本, 创建这样的函数:

private void FixedUpdate()

这是对Update()函数的修正函数, 我们可以将其中坦克移动的所有代码剪切到此函数里, 并将移动命令行中的Time.DeltaTime 改为 Time.FixedDeltaTime 让坦克移动变成固定帧, 这样问题就解决了.

6.子弹设计

我们有坦克子弹的贴图, 新建一个预制体取名为Bullet,贴图为Bullet_0,也就是子弹朝上的方向,并缩放到合适大小. 然后我们需要让坦克在按下空格的时候生成一枚子弹,打开player脚本,写如下Attack()函数:

//新增属性
private Vector3 BulletEulerAngle; //子弹朝向
private float timeVal; //攻击cd
//新增引用
public GameObject BulletPrefab; //指向Bullet的预制体

    private void Attack()
    {
   
        if (Input.GetKeyDown(KeyCode.Space))
        {
   
            Instantiate(BulletPrefab, transform.position, Quaternion.Euler(transform.eulerAngles+BulletEulerAngles));
            //Instantiate生成函数(生成组件的脚本内名字,生成坐标,生成角度)
            //Quaternion.Euler角度转换函数,欧拉角转换为四元角函数(欧拉角角度)
            timeVal = 0;
        }
    }

给引用赋好预制体
在Update()中加入攻击cd随时间递减的方法,内部引用攻击方法

if(timeVal >= 0.4f)//攻击CD
        {
   
            Attack();
        }
        else 
        {
   
            timeVal += Time.deltaTime;
        }

Input.GetKeyDown()为接受键盘按下函数,当键盘按下时触发,相似的还有Input.GetKeyUp()为接受键盘弹起。Instantiate()为生成函数, Quaternion()函数为角度转换函数,后面加.Euler为将欧拉角转换为四元角
此子弹转弯函数和之前玩家转弯用的方式是不相同的,一个是切换图片,一个是更改朝向,但功能看起来是一样的,做好区分

transform.eulerAngles为当前脚本主体的面向角度,因为坦克的朝向我们依靠的是切换贴图实现的,故这个值恒定为0.
BulletEulerAngles为自己定义的Vector3变量,意为子弹的旋转角度。
此外, BulletEulerAngles的值为(x,y,z)形式,它表示子弹在三个不同轴向的旋转角度。因此我们需要在按下方向键的同时改变z轴的大小就可以完成子弹朝向的改变。
我们首先将移动方式封装成一个方法,然后在里面加入子弹发射方向的改变

private void Move()
    {
   
        float h = Input.GetAxisRaw("Horizontal");//水平方向输入

        transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);//(水平方向 * 左/右 * 速度 * 时间 , 坐标系)

        if (h < 0)
        {
   
            sr.sprite = tankSprite[3];
            BulletEulerAngles = new Vector3(0, 0, 90); //子弹将向左发射
        }
        if (h > 0)
        {
   
            sr.sprite = tankSprite[1];
            BulletEulerAngles = new Vector3(0, 0, -90); //子弹将向右发射
        }

        if (h != 0
  • 3
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值