Unity入门(一)

news/2024/3/29 21:08:30/文章来源:https://blog.csdn.net/weixin_45248492/article/details/130373222

Unity

Unity是一套完善体系与编辑器的跨平台游戏开发工具,也可以称之为游戏引擎。游戏引擎是指一些编写好的可以重复利用的代码与开发游戏所用的各功能编辑器。

  • 基于C#编程,易上手,高安全性
  • 独特的面向组件游戏开发思想让游戏开发更加简单易复用
  • 十分成熟的所见即所得开发编辑器
  • 良好的生态圈
  • 强大的跨平台,可以制作PC、主机、手机、AR、VR等多平台游戏

下载安装

在中文网站中https://unity.cn/releases

下载Unity Hub即可。

在这里插入图片描述

下载好之后,点击进入软件,然后选择Unity Editor的安装地址等待下载安装。

在这里插入图片描述

可以选择使用中文语言。上图中的设置按钮,点击后

在这里插入图片描述

完成后,还需要记得要申请一个许可证,才可以使用,个人版的即可。

安装一个LTS版本的编辑器

在这里插入图片描述

勾选上visual studio的开发工具,如果有,可以不用再去安装了

在这里插入图片描述

整完后,创建一个项目,然后摸索下它里面的功能菜单。。

模型商店

在这里插入图片描述

在页面中找子集需要的素材即可

在这里插入图片描述

脚本声明周期

在unity中创建一个C#脚本

在这里插入图片描述

进入vs编辑器

public class Test : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){}// Update is called once per framevoid Update(){}
}

包含两个方法,start()和Update(),而其他的生命周期方法

  • Awake():最早调用,一般在此实现单例模式
  • OnEnable():组件激活后会被调用,在Awake()后会调用一次
  • Start():在Update()前调用一次,在OnEnable()后调用,可以在这里设置一些初始值
  • FixedUpdate():固定频率调用方法,每次调用与上次调用的时间间隔相同
  • Update():帧率调用方法,每一帧调用一次,每次调用与上次调用的时间间隔不相同
  • LateUpdate():在Update()每调用一次后,紧跟着调用一次
  • OnDisable():与OnEnable()相反,组件未激活时调用
  • OnDestory():被销毁后调用一次

OnEnable和OnDisable()的触发

在这里插入图片描述

Update()和LateUpdate()

当程序开始执行时,每走一帧都会调一次Update()方法,而Update()执行完毕后,LateUpdate()跟着执行一次

在这里插入图片描述

FixedUpdate()

每秒走多少帧,此方法就调用多少次

OnDestory()

当对象的组件被移除或者程序结束时,会调用OnDestory()。

脚本执行顺序

在这里插入图片描述

当一个对象加上了两个脚本后,他们的执行顺序是从下向上运行的,并且它会先执行全部脚本Awake()、OnEnable()、Start()...

那么,我们可以将先执行的脚本方法实现,放入到生命周期最优先的方法中即可。

或者,我们可以给脚本设置执行的顺序:

在这里插入图片描述

在这里插入图片描述

设置后,它的执行顺序是:先执行Test1的Awake(),再执行Test2的Awake(),然后执行Test1的Start(),执行Test2的Start();

物体做标记

给物体打个Tag,以便分类,方便查找。

在这里插入图片描述

当找不到想要的tag标签是,可以自定义创建一些标签进行使用。

还有Layer图层, 可以更大方面作区分,比如区分是人物、场景等,可以用Layer图层作区分。

而像人物又可以分为玩家和敌人,再细分至Tag标签。

在这里插入图片描述

在摄像机对象中,可以设置要拍摄的图层。

在这里插入图片描述

勾掉后的图层,在实际相机拍摄中就不会再显示出来了。

向量

标量:只有大小的量

向量:既有大小,又有方向。

向量的摸:就是向量的大小

单位向量:大小为1的向量

单位化,归一化:把向量转为单位向量的过程。

点乘:得到两个向量之间的夹角:A向量*B向量=x1*x2+y1*y2=cosθ,而这个θ就是点乘的值(度数)

预制体与变体

在这里插入图片描述

当给预设体中增加组件时,场景中的物体也会自动增加上,但是当场景中的物体增加组件时,它是场景中物体独有的组件,可以添加至预设体中。

在这里插入图片描述

在场景物体属性栏中,新增的组件时呈蓝色边。

从场景物体中,添加至预设体中

在这里插入图片描述

完成后,蓝边会消失。

注意后缀是prefab的文件是预制体,可以导出给别人使用,也可以导入到自己的项目中使用。

如果预制体需要再次呈现出不同的预制体,那么可以使用在原始预制体的基础上进行叠加,那么当原始预制体改变时,新的预制体跟着变更

在这里插入图片描述

Vector3的使用

创建一个C#脚本,在start()方法中

public class VectorTest : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){// 向量Vector3 v = Vector3.right;Vector3 v2 = Vector3.forward;// 计算两点之间的角度Debug.Log(Vector3.Angle(v, v2));// 计算两点之间的距离Debug.Log(Vector3.Distance(v, v2));// 点乘Debug.Log(Vector3.Dot(v, v2));// 叉乘Debug.Log(Vector3.Cross(v, v2));}// Update is called once per framevoid Update(){}
}

方向描述,欧拉角与四元数

常用方法

public class RotateTest : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){// 旋转:欧拉角,四元数Vector3 rotate = new Vector3(0, 30, 0);// 方法一:无旋转的四元数Quaternion quaternion = Quaternion.identity;// 方法二:通过欧拉角创建的四元数quaternion = Quaternion.Euler(rotate);// 看向一个物体quaternion = Quaternion.LookRotation(new Vector3(0,0,0))// 通过四元素转为欧拉角rotate = quaternion.eulerAngles;}// Update is called once per framevoid Update(){}
}

Debug

开发中,可能会遇到需要调试的情况。

public class DebugTest : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){Debug.Log("test");Debug.LogWarning("test2");Debug.LogError("test3");}// Update is called once per framevoid Update(){// 画一条直线,起点和终点Debug.DrawLine(new Vector3(1,0,0), new Vector3(1,1,0), Color.blue);// 画一条射线  起点,射线Debug.DrawRay(new Vector3(1,0,0), new Vector3(1,1,0), Color.red);}
}

在这里插入图片描述

动态修改物体属性,物体类的使用

我们需要获取当前脚本所挂载的游戏物体。

给物体绑定脚本后,脚本内部自动会获取到物体实例并且放入到 gameObject对象中。

// 此脚本会自动获取到游戏物体
// GameObject go = this.gameObject;
// 游戏物体的名称
Debug.Log(gameObject.name);
// 游戏标签
Debug.Log(gameObject.tag);
// 图层 , 注意这里返回的是索引值 0是default层
Debug.Log(gameObject.layer);

当物体中有子物体时,需要在脚本中声明子物体变量,然后再父物体中设置子物体的游戏变量。

public class EmptyTest : MonoBehaviour
{public GameObject cube;// Start is called before the first frame updatevoid Start(){// 此脚本会自动获取到游戏物体// GameObject go = this.gameObject;// 游戏物体的名称Debug.Log(gameObject.name);// 游戏标签Debug.Log(gameObject.tag);// 图层 , 注意这里返回的是索引值 0是default层Debug.Log(gameObject.layer);// 立方体名称Debug.Log(cube.name);}// Update is called once per framevoid Update(){}
}

上面创建了一个cube的GameObject对象。然后给设置上值。

在这里插入图片描述

获取对象的激活状态

// 当前真正的激活状态(跟父物体的状态有关系)
Debug.Log(cube.activeInHierarchy);
// 当前自身物体的激活状态
Debug.Log(cube.activeSelf);

获取对象的组件

同对象一样,当脚本和对象(物体)绑定后,它会自动获取到对象的各种组成,直接this.调用即可。

// 获取物体的transform组件
Debug.Log(transform.position);// 获取其他的组件
BoxCollider bc = GetComponent<BoxCollider>();
// 获取当前物体的子物体身上的某个组件
// GetComponentInChildren<CapsuleCollider>(bc);
// 获取当前物体的父物体身上的某个组件
// GetComponentInParent<BoxCollider>();// 手动代码添加组件
gameObject.AddComponent<AudioSource>();

通过其他方式获取物体

// 通过游戏物体的名称获取游戏物体
GameObject test = GameObject.Find("Test");
Debug.Log(test.name);// 通过标签获取物体
test = GameObject.FindWithTag("Enemy");
// 设置游戏物体不可用
test.setActive(false);

预设体动态生成实体

先给脚本中设置一个预设体的变量,然后在物体中绑定好预设体对象。

在这里插入图片描述

public class EmptyTest : MonoBehaviour
{public GameObject cube;public GameObject Prefab;// Start is called before the first frame updatevoid Start(){// 使用预设体动态生成物体,会返回一个GameObject对象Instantiate(Prefab);}// Update is called once per framevoid Update(){}
}

游戏时间的使用

创建一个物体,绑定上脚本,在脚本中使用游戏时间的计数

public class TimeTest : MonoBehaviour
{// Start is called before the first frame updatefloat timer = 0;void Start(){// 游戏开始到现在所花的时间Debug.Log(Time.time);// 时间缩放值(时间倍速)Debug.Log(Time.timeScale);// 固定时间间隔(每一帧之间的间隔时间数)Debug.Log(Time.fixedDeltaTime);}// Update is called once per framevoid Update(){// timer可以用来计数游戏总时间timer += Time.deltaTime;// 上一帧到这一帧所用的游戏时间Debug.Log(Time.deltaTime);// 如果总时间 > 3s,我可以做一些事情if (timer > 3){}}
}

路径权限要理清,Application很重要

假如在Project中新建了一个a.txt文件,在代码中如何读取呢

在这里插入图片描述

public class ApplicationTest : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){// s游戏数据文件夹路径(只读的,打包后加密压缩,所以看不到)Debug.Log(Application.dataPath +"/a.txt");// 持久化文件夹路径(可写的)Debug.Log(Application.persistentDataPath);// StreamingAssets文件夹路径(只读,打包后不会加密压缩,这些文件可以放入此目录下,可以自己创建一个StreamingAssets的目录)Debug.Log(Application.streamingAssetsPath);// 临时文件夹,可以将临时数据写入Debug.Log(Application.temporaryCachePath);// 控制是否在后台运行Debug.Log(Application.runInBackground);// 用浏览器打开一个URLApplication.OpenURL("www.baidu.com");// 退出游戏Application.Quit();}// Update is called once per framevoid Update(){}
}

在这里插入图片描述

切换场景

在Assets的scenes中创建一个新的场景

在这里插入图片描述

然后将这两个场景,放入到打包的场景中,并且会带有索引

在这里插入图片描述

在SampleScene场景中跳转到MyScene中

using UnityEngine.SceneManagement;public class SceneTest : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){// 场景跳转,可以根据名称或索引进行跳转// SceneManager.LoadScene(1);// Additive:多场景叠加// Single:单场景SceneManager.LoadScene("MyScene", LoadSceneMode.Additive);// 获取当前场景Scene scene = SceneManager.GetActiveScene();// 场景名Debug.Log(scene.name);// 场景路径Debug.Log(scene.path);// 场景是否已经被加载Debug.Log(scene.isLoaded);// 场景索引Debug.Log(scene.buildIndex);// 获取场景中的所有游戏对象(根级别的)GameObject[] gos = scene.GetRootGameObjects();Debug.Log(gos.Length);// 场景管理类// 创建新场景Scene newScene = SceneManager.CreateScene("newScene");// 已加载场景的数量Debug.Log(SceneManager.sceneCount);// 卸载场景SceneManager.UnloadSceneAsync(newScene);}// Update is called once per framevoid Update(){}
}

异步加载场景获取进度

using UnityEngine.SceneManagement;public class SceneTest : MonoBehaviour
{AsyncOperation operation;// Start is called before the first frame updatevoid Start(){StartCoroutine(loadScene());}// 协程方法用来异步加载场景IEnumerator loadScene() {operation = SceneManager.LoadSceneAsync(1);// 让用户手动跳转场景operation.allowSceneActivation = false;yield return operation;}float timer = 0;// Update is called once per framevoid Update(){// 每一帧都记录 加载的进度 值范围 0-0.9Debug.Log(operation.progress);timer += Time.deltaTime;// 5s后跳转if (timer > 5){operation.allowSceneActivation = true;}}
}

了解transform

游戏物体的父子集关系,是由transform控制的。

创建一个三层关系的几个物体,然后在中间层绑定上脚本代码

在这里插入图片描述

常用属性:

// 获取世界位置
Debug.Log(transform.position);
// 获取相对位置(相对于父物体)
Debug.Log(transform.localPosition);// 获取世界旋转、
Debug.Log(transform.rotation);
// 获取相对旋转
Debug.Log(transform.localRotation);// 获取世界欧拉角
Debug.Log(transform.eulerAngles);
// 获取相对欧拉角
Debug.Log(transform.localEulerAngles);// 获取相对缩放
Debug.Log(transform.localScale);// 获取向量
Debug.Log(transform.forward);
Debug.Log(transform.right);
Debug.Log(transform.up);

常用方法:

移动、角度类

// 时刻看向 000点
transform.LookAt(Vector3.zero);// 旋转 相对于local旋转
transform.Rotate(Vector3.up, 1);// 绕物体旋转  绕着(0,0,0)的up轴,每一帧转5度
transform.RotateAround(Vector3.zero, Vector3.up, 5);// 移动 每一帧移动0.1
transform.Translate(Vector3.forward * 0.1f);

父子关系:

// 获取父物体
transform.parent.gameObject;// 获取子物体的数量
transform.childCount;// 解除与子物体的父子关系
transform.DetachChildren();// 获取子物体
// 方式一 通过子物体的名称获取子物体的transform
Transform trans = transform.Find("Child")
// 方式二 通过子物体的索引获取子物体的transform
trans = transform.GetChild(0);// 判断物体是不是另一个物体的子物体
bool res = trans.IsChildOf(transform);
Debug.Log(res);// 设置为父物体
trans.SetParent(transform);

基本键鼠操作

键鼠操作,要在Update()中做监测,每一帧都要检测到。

void Update()
{// 鼠标操作// 按下鼠标 0:左键 1:右键 2:滚轮if (Input.GetMouseButtonDown(0)){Debug.Log("按下了鼠标左键");}// 持续按下鼠标左键if (Input.GetMouseButton(0)){Debug.Log("持续按下鼠标左键");}// 抬起鼠标左键if (Input.GetMouseButtonUp(0)){Debug.Log("抬起鼠标左键");}// 按下键盘按键if (Input.GetKeyDown(KeyCode.A)) {Debug.Log("按下了A");}// 持续按下键盘按键if (Input.GetKey(KeyCode.A)) {Debug.Log("持续按下了A");}// 抬起键盘按键if (Input.GetKeyUp(KeyCode.A)) {Debug.Log("抬起按键A");}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_103621.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【神经网络】tensorflow实验7--回归问题

1. 实验目的 ①掌握一元线性回归模型的实现方法 ②掌握多元线性回归模型的实现方法 ③掌握三维数据可视化方法 2. 实验内容 ①使用TensorFlow建立一元线性回归模型&#xff0c;使用商品房销售数据训练模型&#xff0c;并使用训练好的模型预测房价 ②使用TensorFlow建立多元线…

十、ElasticSearch 实战 - 源码运行

一、概述 想深入理解 Elasticsearch&#xff0c;了解其报错机制&#xff0c;并有针对性的调整参数&#xff0c;阅读其源码是很有必要的。此外&#xff0c;了解优秀开源项目的代码架构&#xff0c;能够提高个人的代码架构能力 阅读 Elasticsearch 源码的第一步是搭建调试环境&…

思维导图从入门到大神

思维导图怎么做&#xff1f;思维导图是一种发散性思维的图。在我们生活的方方面面都有运用。无论是工作、学习、还是生活&#xff0c;我们都可以用到它。那思维导图是怎么绘制的呢&#xff1f;其实非常简单&#xff0c;只要这简单的几步 1、首先在绘制思维导图前&#xff0c;我…

【网络】-- UDP协议

目录 传输层 再谈端口号 端口号范围划分 认识知名端口号&#xff08;Well-Know Port Number&#xff09; 两个问题 netstat pidof UDP协议 UDP的特点 UDP的缓冲区 UDP使用注意事项 基于UDP的应用层协议 传输层 负责数据能够从发送端传输接收端。 再谈端口号 端…

Codeforces Round 861 (Div. 2)(A~D)

A. Lucky Numbers 给出边界l和r&#xff0c;在区间[l, r]之间找到幸运值最大的数字。一个数字的幸运值被定义为数位差的最大值&#xff0c;即数字中最大的数位和最小的数位的差。 思路&#xff1a;因为涉及到至少两位&#xff0c;即个位和十位变化最快&#xff0c;最容易得到相…

07 - 进程创建大盘点

---- 整理自狄泰软件唐佐林老师课程 查看所有文章链接&#xff1a;&#xff08;更新中&#xff09;Linux系统编程训练营 - 目录 文章目录 1. 进程创建回顾2. 再论进程创建2.1 思考2.2 vfork()深度分析2.3 vfork()要点分析2.4 fork()的现代优化2.5 编程实验&#xff1a;fork() &…

被遗忘的Java关键字:transient

前言 今天在看项目代码时候&#xff0c;看到了下面这样一行代码&#xff0c;用transient修饰了一个变量&#xff0c;主要作用是做一个全局开关。说实话我是第一次看到这个关键字。激发了我的好奇心&#xff0c;所以就了解一下这是何方神圣。 /*** 全局开关*/public static tran…

最新研究:可审计的具有拜占庭鲁棒的联邦学习方案

本人新论文&#xff0c;可免费下载&#xff1a;https://download.csdn.net/download/liangyihuai/87727720 Y. Liang, Y. Li and B. -S. Shin, “Auditable Federated Learning With Byzantine Robustness,” in IEEE Transactions on Computational Social Systems, doi: 10.…

浅谈拉格朗日插值法

浅谈拉格朗日插值法 好像FFT要用到&#xff0c;所以就学习一手 文章目录 浅谈拉格朗日插值法什么是插值拉格朗日插值法 什么是插值 在离散数据的基础上补插连续的函数&#xff0c;使得这条连续函数经过所有离散数据点&#xff0c;这个过程就叫插值。其意义在于&#xff1a; …

论文阅读:DLME = Deep Local-flatness Manifold Embedding

Author: Zelin Zang, Siyuan Li, Di Wu and Stan Z Li. 1-4: Westlake University 摘要 流形学习&#xff08;ML, Manifold learning&#xff09;旨在从高维数据中识别低维结构和嵌入&#xff0c;然而我们发现现有工作在采样不足的现实数据集上效果不佳。一般的ML方法对数据结…

LNMP网站框架搭建

1. Nginx的工作原理 php-fpm.conf 是控制php-fpm守护进程的 php.ini是php解析器 工作进程&#xff1a; 1.客户端通过域名进行请求访问时&#xff0c;会找Nginx对应的虚拟主机 2. Nginx对该请求进行判断&#xff0c;如果是静态请求,Nginx会自行处理&#xff0c;并将处理结果返…

【C++】了解设计模式、 stackqueue的使用与模拟实现

文章目录 1.设计模式2.stack1.stack的使用1.stack的结构2.stack的接口 2.stack的模拟实现1.stack的结构2.接口实现 3.queue1.queue的使用1.queue的结构3.queue的接口 2.queue的模拟实现1.queue的结构2.接口实现 4.了解deque1.deque的原理介绍2.deque的底层结构3.deque的迭代器设…

【Android入门到项目实战-- 7.1】—— 如何使用通知?

目录 一、创建通知的步骤 1、创建一个NotificationManager实例 2、使用一个Builder构造器来创建Notification对象 3、设置标题、文字、时间和图标等信息 4、显示通知 二、通知实例演示 三、实现通知的点击效果 1、PendingIntent 什么是PendingIntent&#xff1f; 如何使…

Linux下实现C语言程序

一.情况说明 写这篇博客的情况比较复杂&#xff0c;首先我本来是参加新星计划按照规划现在去学习shell脚本语言的&#xff0c;但是博主现在由于其他原因需要了解makefile&#xff0c;makefile是Linux系统下的一种工具&#xff0c;makefile的一些背景要涉及链接库的知识&#xf…

HTB-DevOops

HTB-DevOops 信息收集5000端口 立足python反序列化攻击XEE读取SSH root 信息收集 5000端口 根据文字所述&#xff0c;下面的图片是feed.py。 目录扫描 /upload如下&#xff1a; 上传测试xml文件。 得到反馈 怀疑是标签不匹配&#xff0c;尝试寻找匹配的标签。前面首页有提…

【算法】【算法杂谈】判断点是否在三角形内部(面积法和向量法)

目录 前言问题介绍解决方案代码编写java语言版本c语言版本c语言版本 思考感悟写在最后 前言 当前所有算法都使用测试用例运行过&#xff0c;但是不保证100%的测试用例&#xff0c;如果存在问题务必联系批评指正~ 在此感谢左大神让我对算法有了新的感悟认识&#xff01; 问题介…

Java企业电子招标采购系统源码Spring Boot + Mybatis + 前后端分离 构建企业电子招采平台之立项流程图

项目说明 随着公司的快速发展&#xff0c;企业人员和经营规模不断壮大&#xff0c;公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境&#xff0c;最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范&#xff0c;以及…

HTB靶机-Lame-WP

Lame 简介&#xff1a; Lame is a beginner level machine, requiring only one exploit to obtain root access. It was the first machine published on Hack The Box and was often the first machine for new users prior to its retirement Tags&#xff1a; Injection, C…

OSCP-XPosedAPI(本地文件包含、查看源码、os.system、命令盲注)

目录 扫描 Web API枚举 命令盲注 提权 扫描 发现了两个开放的端口:端口22上的SSH和端口13337上的未知服务。 用netcat手动探测端口13337,但是运行几个常见的TCP/UDP服务初始化命令没有输出。 尝试了一个完整的脚本和版本nmap扫描的开放端口࿰

Vue+Echarts 项目演练(下)收尾工作图表绘制

设置销售总量图表 中心容器地图设置 产品库存统计图 产品类别图表 项目可视化完结-整体展示 设置销售总量图表 在第一个容器中进行图表设置 <template><div><h2>A</h2><div class"chart" id"oneChart">容纳后期的图表…