IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> Unity入门 ---- 2D -> 正文阅读

[游戏开发]Unity入门 ---- 2D

DAY 一:

向量Vector

  1. 向量的长度
    Vector2 :长度 = sqrt( x2 + y2 )
    Vector3 :长度 = sqrt( x2 + y2 + z2 )
    可直接使用API求长度:
  float len = v.magnitude;
  1. 向量的标准化Normalize
    将向量的长度缩放成1,即单位向量
    示例: (2,2) --> (0.707,0.707) 、(3,4) --> (0.6,0.8)
    使用API进行标准化,示例:
 Vector3 a = new Vector3(3f,4f,0);
 Vector3 b = a.normalized;
 Debug.log("标准化为: " + b.ToString("F3"));
 //F3表示在打印显示时保留3位小数;
 //注:向量打印默认显示保留一位小数
  1. 几个常用的标准向量(静态向量)
Vector3.right; 	//Vector3(1,0,0)
Vector3.up;		//Vector3(0,1,0)
Vector3.forward;//Vector3(0,0,1)

向量夹角

从a到b的夹角:示例

        Vector3  a = new Vector3(2,2,0);

        Vector3 b = new Vector3(-1,3,0);

        float angle1 = Vector3.SignedAngle(a,b,Vector3.forward);//顺着z轴进行旋转,带符号的,负为逆时针,正为顺时针
        
        float angle2 = Vector3.Angle(a,b);

        Debug.Log("a到b的夹角为:" + angle1); 

物体的指向

示例:让一个飞机指向子弹,然后飞机向子弹移动

   void Start()
    {
        //本物体的现指向:Y轴
        Vector3 face = this.transform.up;
        
        //找到所要指向的物体
        GameObject target  = GameObject.Find("子弹");

        //找到两个物体之间的方向:两物体的空间坐标相减
        Vector3 direction = target.transform.position - this.transform.position;

        //一个是Y轴标准向量,一个两物体之间的向量,得到旋转角度
        float angle = Vector3.SignedAngle(face,direction,Vector3.forward);

        //旋转
        this.transform.Rotate(0,0,angle);
    }

    void Update()
    {
        float step = 1.2f * Time.deltaTime;

        //机头指向沿自己的Y轴指向前进
        transform.Translate(0,step,0,Space.Self);
    }

屏幕坐标

游戏中的物体,有两个坐标:
空间坐标: transform.position
该物体在世界空间中的坐标
屏幕坐标
通过屏幕(摄像头)观察,该物体在屏幕上的位置
屏幕坐标系:

  • y轴向上,x轴向右 ,左下角为(0,0);
  • 宽度Screen.width(像素);高度Screen.height(像素)

获取一个物体的屏幕坐标:

Vector3 pos = transform.position;
Vector3 screenPos = Camera.main.WorldToScreenPoint(worldPos);//单位为像素

注:因为屏幕边界(左右)的不确定,所以去判断小物体是否移动至屏幕边界,得用屏幕坐标。

示例:让一架飞机左右飞行,不能超出屏幕边界

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

public class point : MonoBehaviour
{
    private bool toRight = true; //用于判断是否到达屏幕边界
    // Start is called before the first frame update
    void Start()
    {
        //让机头顺时针旋转90向右
        transform.eulerAngles = new Vector3(0,0,-90);

    }
    // Update is called once per frame
    void Update()
    {
        //得到物体的屏幕坐标
        Vector3 sp = Camera.main.WorldToScreenPoint(transform.position);

        //到达右边界后向左旋转
        if( toRight && sp.x > Screen.width) {
            toRight = false;
            transform.eulerAngles = new Vector3(0,0,90);
        }

        //到达左边界后向右旋转
        if(!toRight && sp.x < 0) {
            toRight = true;
            transform.eulerAngles = new Vector3(0,0,-90);
        }

        float step = 1.8f * Time.deltaTime;

        //机头指向沿自己的Y轴指向前进
        transform.Translate(0,step,0,Space.Self);
    }
}

DAY 二

鼠标事件处理

探测鼠标事件

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

public class Mouse : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        //该方法用来让游戏以指定的帧率执行
        Application.targetFrameRate = 60;
    }
    // Update is called once per frame
    void Update()
    {
        //Input.GetMouseButtonDown( )探测鼠标按下,其中,0 代表左键,1 为右键,2 为 中键(滚轮)
        if (Input.GetMouseButtonDown(0)) {
            Debug.Log("鼠标按下:" + Input.mousePosition);
            //打印此时鼠标的位置(屏幕坐标)
        }

        //Input.GetMouseButtonUp ( )探测鼠标抬起
        if(Input.GetMouseButtonUp (0)) {
            Debug.Log("鼠标抬起");
        }

        //Input.GetMouseButton ( )探测鼠标的状态,若按下,返回true;
        if (Input.GetMouseButton(0)) {
             Debug.Log("鼠标正在被按下");
        }
    }
}

注:屏幕坐标转换为世界坐标时,记得把z坐标置0,放在2D平面上。

鼠标跟随事件

示例:
实现鼠标跟随效果,让飞机自动朝向鼠标飞行
思路:
首先判断鼠标的状态是否为按下,然后获取鼠标位置。
其次,让飞机移动到鼠标移动到的位置

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor.Build.Reporting;
using UnityEngine;
using UnityEngine.UIElements;

public class  point : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        Application.targetFrameRate = 60;
    }

    // Update is called once per frame
    void Update()
    {

        // 检查 ‘当前鼠标左键是否按下’ ,此为状态检查
        if (Input.GetMouseButton(0))
        {
            //把屏幕坐标转换成世界坐标
            Vector3 pos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
            pos.z = 0;    // 把Z坐标置0,放到2D平面上来

            // 控制机头的指向
            SetDirection(pos);
        }

        float step = 1.2f * Time.deltaTime;
        transform.Translate(0, step, 0, Space.Self);
    }

    void SetDirection(Vector3 targetPos)
    {
        Vector3 face = transform.up; // 头部指向
        Vector3 direction = targetPos - transform.position;

        float angle = Vector3.SignedAngle(face, direction, Vector3.forward);
        transform.Rotate(0, 0, angle);
    }

}

鼠标拖拽

示例:
拖拽小飞机,移动它的位置
思路:
首先判断鼠标是否点击到飞机,即鼠标与飞机的位置之间的距离是否足够小,
其次,移动鼠标,将飞机的位置覆盖为鼠标的位置,让飞机移动到鼠标移动到的位置。

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor.Build.Reporting;
using UnityEngine;
using UnityEngine.UIElements;

public class MyJet : MonoBehaviour
{
    private bool drag = false;//用于判断
    private Vector3 lastMousePos;//飞机最终移动到的鼠标位置

    // Start is called before the first frame update
    void Start()
    {
        Application.targetFrameRate = 60;
    }

    // Update is called once per frame
    void Update()
    {
        if ( Input.GetMouseButtonDown(0) )
        {
            Vector3 pos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
            pos.z = 0;    // 把Z坐标置0,放到2D平面上来

            float distance = (pos - transform.position).magnitude;
            if(distance < 1.5f)
            {
            //如果鼠标点击的是飞机,则将飞机位置变为鼠标位置
                drag = true;
                lastMousePos = pos;
            }
        }

//鼠标抬起,将drag初始化
        if( Input.GetMouseButtonUp(0))
        {
            drag = false;
        }


        // 检查 ‘当前鼠标左键是否按下’ ,此为状态检查
        if ( drag )
        {
            Vector3 pos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
            pos.z = 0;    // 把Z坐标置0,放到2D平面上来

            Vector3 delta = pos - lastMousePos;
            transform.position += delta;

            lastMousePos = pos;
        }
    }
}

事件函数 Event Functions

常见几个

  • Awake() --脚本组件实例化时调用
  • OnEnable() – 脚本组建启用时调用
  • Start() – 脚本组件第一次执行之前
  • Update()
  • FixedUpdate()

(1)不以On开头的,由系统调用;
Awake() 、 Start() 、Update()、FixedUpdate()
(2)以On开头的,是相应事件的回调函数;
OnEnable() 、OnDisable()、OnGUI()
(3)当组件被禁用时,Start()不被调用,用于实例化的Awake()会被调用;
(4)无论组件被重新调用几次,Start()只会调用一次;
(5)一般情况下,可以把初始化写在Awake()或Start()中;

脚本的执行顺序

(1)对所有组件进行遍历,调用它们的 Awake() ,而后再依次遍历组件,调用 Start() ,再依次遍历组件执行Update() 。
(2)Exection Order : 脚本的执行顺序,即优先级。脚本的默认顺序都是0,无序。顺序值越小,则越优先。
**执行顺序的是设定:
** Project Settings --> Script Execution Order 或者 点击C#脚本 --> Execution Order
(1)用下面两种方式中任一种打开Project Settings面板 Script Execution Order 项
在这里插入图片描述
(2)点击如下的红框
在这里插入图片描述

(3)点击所要修改优先级的脚本

在这里插入图片描述
(4)如下图所示,改变优先级。Dedault Time 是默认值,也可以直接拖拽脚本放在它上面【优先级增加】或下面【优先级减小】
在这里插入图片描述

脚本的参数

脚本的参数,用于控制脚本的运行。
一个脚本是可以多次使用的,可以同时将脚本挂载在多个游戏对象上
示例:编写Fly.cs,让飞机按照设定的方向进行一定速度的移动。

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

public class Fly : MonoBehaviour
{
    public Vector3 speed ; //速度参数
    // Start is called before the first frame update
    void Start()
    {
        Application.targetFrameRate = 60;
    }

    // Update is called once per frame
    void Update()
    {
        Vector3 step = speed * Time.deltaTime ; //标量乘法
        transform.Translate(step,Space.Self);
    }
}

如下图中,可以设定移动方向,以及移动速度
在这里插入图片描述

引用类型的参数

引用类型: class类型的参数。
在脚本中,可以引用一个游戏对象组件、或资源
示例:点击人物,实现换装功能。【在脚本中指定2张图片,便于动态的切换】
步骤:

  1. 在脚本中添加资源的引用 : public Sprite sprite0 ;
  2. 在Unity中的Inspector 中指定参数:把图片Sprite资源拖到Inspector 相应参数位置
  3. 在代码中切换图片显示。
    注:也可以使用数组来表示多张图片: public Sprite[] sprites ;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ChangeFace : MonoBehaviour
{
    //新建两个Sprite,然后在Unity中指定游戏对象,给其赋值;
    public Sprite sprite0;
    public Sprite sprite1;

    private int index = 0;
    // Start is called before the first frame update
    void Start()
    {
        Debug.Log("Start.....");
    }

    // Update is called once per frame
    void Update()
    {
    //探测到鼠标按下事件
        if(Input.GetMouseButtonDown(0)) {
            DoChange();
        }
    }

    void DoChange() {

        SpriteRenderer renderer = GetComponent<SpriteRenderer>();
        if (index == 0) {
            index = 1;		
            renderer.sprite = this.sprite1;
        } else {
            index = 0;
            renderer.sprite = this.sprite0;
        }
    }
}

预制体

预制体Prefab:预先制作好的物体(模板),是一个资源文件.prefab。
将游戏对象事件制作好,作为资源备用,一般用于游戏对象的动态创建

编辑预制体

打开方法:
1.在Project窗口,双击*.prefab资源;
2.在Inspector 窗口,点Open Prefab;
3.在Hierarchy 窗口,找到预制体的实例【图标为蓝色】,点右侧的小箭头。
注:

  1. 使用预制体,可以快速创建多个相同的实例;修改预制体时,每一个实例都会自动更新。
  2. 对预制体资源【实例】进行修改时,也可以改变预制体,使得其他预制体资源同步更新

(1)随意选中某一预制体资源,Prefab工具,如下图:

  • Open :打开Prefab编辑
  • Select:定位Prefab资源,在Project面板中会定位到Prefab资源
  • Overrides:点击:下拉小箭头:
    - Revert All :取消对Instance所做的修改
    - Apply All: 应用对Instance所做的修改
    在这里插入图片描述

断开Prefab 和 Prefab Instance 联系

在Hierarchy 窗口中,右键点击一个Prefab实例,执行 Unpack Prefab ,
由它成为一个独立的游戏对象,不再和原始Prefab有联系。如下图:
在这里插入图片描述

动态创建实例

在游戏的运行中使用代码来创建游戏对象。
示例: 每点击一次按钮,飞机就会发一枚子弹;
MyJet 挂载至“飞机”上:

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

public class MyJet : MonoBehaviour
{
    public GameObject myPrefab;
    // Start is called before the first frame update
    void Start()
    {
        Application.targetFrameRate = 60;
    }

    // Update is called once per frame
    void Update()
    {
        //当鼠标点击,便创建一个子弹的实例
        if(Input.GetMouseButtonDown(0)) {
            Fire();
        }
    }

    void Fire() {
        //创建了一个子弹的实例:Instantiate(myPrefab)根据一个prefab,来创建一个实例,返回值便是创建出的GameObject
        GameObject bullet = Instantiate(myPrefab);
       
        //创建的实例在Y轴上方的1f处向上移动
        bullet.transform.position = transform.position + new Vector3(0,1f,0);

        //改变新创建的实例的名字
        bullet.name = "my bullet" ;
        
    }
}

MyBullet 挂载在“子弹”上:

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

public class MyBullet : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        float step = 1.5f * Time.deltaTime;

        transform.Translate(0,step,0,Space.Self);
    }
}

实例的销毁

    void Update()
    {
        float step = 1.5f * Time.deltaTime;

        transform.Translate(0,step,0,Space.Self);

        //获取当前实例的位置:转换为屏幕位置
       Vector3 sp = Camera.main.WorldToScreenPoint(transform.position);

        //当超出屏幕上边界后,销毁实例
        if(sp.y  > Screen.height) {
            Destroy(this.gameObject);
        }
    }

注:要把文件存进资源里,然后拖到My Prefab。
否则,预制体会被销毁,也再也不能创建新的预制体实例。
在这里插入图片描述

DAY 三

子弹发射(练习)

游戏对象:飞机,子弹(预制体)

要求:

  1. 定时发送子弹
  2. 通过键盘控制左右移动

定时器 :每0.4s发射一个子弹

  • 定时发射子弹, 通过预制体不断地创建新的“子弹”实例。
  • 子弹发射后,沿着y轴一直移动,超出屏幕边界后销毁。

键盘事件

Input.GetKeyDown(key) //键盘按下事件
Input.GetKeyUp(key) //键盘抬起事件
Input.GetKey(key) //状态检查,某键是否被按下

//检查 左箭头 是否被按下
if(Input.GetKey(KeyCode.LeftArrow)) {
	transform.Translate(-step,0,0);
}

附带有具体的实现代码见链接: https://blog.csdn.net/Mj_yong/article/details/119354146.

物理系统

物理系统Physics,即有物理规律作用的系统。
为物体添加刚体组件(RigidBody 2D)
A
添加刚体组件后,可以设置其质量、材质等属性,拥有质量后,会产生下落的效果。
区分: 2D游戏中是 Physics 2D 。在3D中,选择Physics.

静态刚体

分类:

  1. Dynamic:普通刚体,有质量、有速度
  2. Static: 静态刚体,质量无穷大、无速度 (适用于建筑物、地面等固定不动的物体)
  3. Kinematic:运动学刚体,无质量 (忽略物理规律的刚体,一般用于碰撞检测)
    在这里插入图片描述

刚体的碰撞

添加碰撞体(Collider)组件后,才有碰撞的计算。
在这里插入图片描述
在规定碰撞范围后,两物体碰撞时会根据其范围与形状产生不同的效果。
在这里插入图片描述
注: 一般地,RigidBody 组件和 Collider 组件是同时使用的。

刚体的反弹

  1. 在Project窗口里,创建一个用于表示物体的材质
    在这里插入图片描述
    创建后,在面板右侧出现下图
    在这里插入图片描述
    Friction: 摩擦系数
    Bounciness :弹性系数,设为1.
  2. 选择物体的 Rigidboby 2D组件
    Material : 选择上述材质
    在这里插入图片描述
    在物理系统下,运动,碰撞,反弹都是有系统自动计算的。

DAY 四

延时调用

//延长一点时间(IntervalTime)后调用。
//在每一帧Update之后系统会检查待执行的Invoke;
//逻辑上也可以自己计时,然后执行
Invoke("methodName",IntervalTime);
//注:方法名是一个字符串。

在这里插入图片描述

消息调用

例子:若是得分,便调用方法AddScore(int value);

//找到节点
GameObject main = GameObject.Find("游戏主控");
//第一种方法:
//调用方法
MyGame myGame = main.GetComponent<MyGame>();
myGame.AddScore(1);

//第二种方法:
main.SendMessage("AddScore",1);

SendMessage():查找目标方法并立即执行;是同步调用

  • 遍历该对象上的所有c#脚本组件,检查该组件上有没有对应的方法;
  • 若有此方法,则执行该方法;反正目标方法未找到,则提示SendMessage XXX has no receiver;
  • 注:若没有找到,便检查自己是否单词拼写错误等。

交互界面UI

UI :User Interface用户交互界面。
Unity游戏中的UI,称为UGUI。
UI层不属于游戏空间,而是附在屏幕之上。

添加Canvas及其控件

  • 所有的UI元素,都应该放在Canvas节点下面;
  • 添加Canvas时,同时添加了EventSystem事件系统,它们是配合使用。
  • 添加Canvas流程:
  1. 添加 Canvas
    在 Hierarchy窗口,右键 GameObject —> UI —> Canvas
    同时添加一个 Canvas ,和一个 EventSystem 事件系统管理器
    在这里插入图片描述
  2. 指定 Canvas 的显式方式
    选中 Canvas 节点,
    Render Mode : 设为 Screen Space – Camera
    Render Camera : 指向 Main Camera
    Plane Distance :显示平面与摄像机的距离 ,设为 5 .
    在这里插入图片描述
  3. 添加 Text 文件控件
    注意:所有 UGUI元素,都应该放在 Canvas 节点下面

右键选中 Canvas ,添加一个 Text 子节点 :
在这里插入图片描述
设置一下 Text 的属性,
Font :字体样式,可以自己下载字体样式文件,然后拖至该框。
Best Fit :自动调整字体大小,适应 Rect矩形框
Color : 文本的颜色
在这里插入图片描述

  1. 添加Image控件
    和添加Text文件控件相同,在Canvas节点下,添加一个Image;
    指定图片资源;
    设置填充类型Image Type:
    Simple 拉伸,
    Sliced 九宫格,
    Tiled 平铺,
    Filed充满
    在这里插入图片描述
    注:Sliced ,九宫格方式填充,适用于带边框的图片(四个角不变,中央区域拉伸)
    在添加图片资源之前需要对其进行九宫格切割:
    选中图片,打开其Sprite Editor 面板,然后拖拉图片边框绿线节点,调整其位置如下图所示。
    在这里插入图片描述
    而后操作 Image Type设为Sliced。改变Image元素的矩形框大小,观察是否有畸形。

  2. 设置Button
    可以设置按钮的背景图片、以及不同状态下按钮的颜色或高亮或变大【鼠标是否移动到按钮上】、设置按钮上的文本。

UI事件处理

UI事件一般处理的是鼠标点击事件。
(1)在“游戏主控”下挂载脚本,添加好一个Button,在Button组件下的On Click 点击 “ + ” ,然后将游戏主控拖至此处,继续选择游戏主控下的MyGame的Login() 。这样就指定了事件响应的处理。
在这里插入图片描述

(2)也可以采用自定义Button的方式,需要自己编写脚本,实现IPointerDownHandler接口。

UI界面布局

(1) Rect Transform【矩形变换组件】的定位:
默认是居中定位。改变Game窗口大小,Text与Canvas中心的距离是不变的
Pos X/ Y. Width/Height的单位是像素。

如下图,点击center下的方框,可以选择改变Canvas控件的布局。
选择了某种布局后,无论Game窗口的大小和比例多少,它总是会在那个方位。
在这里插入图片描述
(2)UI布局Anchors
在这里插入图片描述
(3) UI布局Panel
实质上就是一个Image控件,但是自带一个背景图片。可用于界面布局,和其他控件形成一个父子关系。

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2021-08-11 12:46:26  更:2021-08-11 12:46:53 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/1 17:20:28-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码