Unity入门(一)

news2024/11/24 5:41:25

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 update
    void Start()
    {
        
    }

    // Update is called once per frame
    void 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 update
    void 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 frame
    void Update()
    {
        
    }
}

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

常用方法

public class RotateTest : MonoBehaviour
{
    // Start is called before the first frame update
    void 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 frame
    void Update()
    {
        
    }
}

Debug

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

public class DebugTest : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        Debug.Log("test");
        Debug.LogWarning("test2");
        Debug.LogError("test3");

    }

    // Update is called once per frame
    void 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 update
    void 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 frame
    void 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 update
    void Start()
    {
        // 使用预设体动态生成物体,会返回一个GameObject对象
        Instantiate(Prefab);

    }

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

游戏时间的使用

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

public class TimeTest : MonoBehaviour
{
    // Start is called before the first frame update
    float timer = 0;
    void Start()
    {
        // 游戏开始到现在所花的时间
        Debug.Log(Time.time);
        // 时间缩放值(时间倍速)
        Debug.Log(Time.timeScale);
        // 固定时间间隔(每一帧之间的间隔时间数)
        Debug.Log(Time.fixedDeltaTime);

    }

    // Update is called once per frame
    void 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 update
    void 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);

        // 用浏览器打开一个URL
        Application.OpenURL("www.baidu.com");

        // 退出游戏
        Application.Quit();
        
    }

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

在这里插入图片描述

切换场景

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

在这里插入图片描述

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

在这里插入图片描述

在SampleScene场景中跳转到MyScene中

using UnityEngine.SceneManagement;

public class SceneTest : MonoBehaviour
{
    // Start is called before the first frame update
    void 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 frame
    void Update()
    {
        
    }
}

异步加载场景获取进度

using UnityEngine.SceneManagement;

public class SceneTest : MonoBehaviour
{

    AsyncOperation operation;
    // Start is called before the first frame update
    void Start()
    {
        StartCoroutine(loadScene());

    }

    // 协程方法用来异步加载场景
    IEnumerator loadScene() {
        operation = SceneManager.LoadSceneAsync(1);
        // 让用户手动跳转场景
        operation.allowSceneActivation = false;
        yield return operation;
    }
    float timer = 0;

    // Update is called once per frame
    void Update()
    {
        // 每一帧都记录 加载的进度 值范围 0-0.9
        Debug.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.coloradmin.cn/o/461739.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Maven 如何下载依赖包的源码包

使用Maven下载依赖包的时候&#xff0c; 默认是不会下载源码包的&#xff0c;但是有时候&#xff0c; 需要Debug代码&#xff0c;或是看看依赖项的源码的写法&#xff0c; 就需要下载源码包了。 这里以 Apache 的 commons-text 为例&#xff0c; 在Maven中添加如下依赖配置&am…

pwlink用作USB转TTL,进入HC-05的AT模式

不说废话的文章概括&#xff1a; 直接连接PWLINK与HC-05&#xff0c;无法进入AT模式&#xff0c;因为蓝牙模块的VCC只能接5V&#xff0c;不能接3.3V&#xff0c;而且PWLINK有两个VDD引脚&#xff0c;且两个VDD引脚初始默认输出电压都是3.3V&#xff0c;所以需要将3.3V改为5V的…

【JavaEE】网络通信中的一些基本概念及协议分层

博主简介&#xff1a;想进大厂的打工人博主主页&#xff1a;xyk:所属专栏: JavaEE初阶 互联网是怎么来的&#xff1f;很多先进技术&#xff0c;都是先军用&#xff0c;用了之后太香了才逐渐民用~~ 互联网也是如此&#xff0c;互联网之前&#xff0c;可以通过有线/无线&#xf…

单链表——“数据结构与算法”

各位CSDN的uu们你们好呀&#xff0c;今天&#xff0c;小雅兰的内容终于是我们心心念念的单链表啦&#xff0c;这一块呢&#xff0c;是一个很重要的部分&#xff0c;也是一个对目前的我来说&#xff0c;比较困难的部分&#xff0c;下面&#xff0c;就让我们进入单链表的世界吧 之…

【unity项目实战】3DRPG游戏开发04——导航、人物移动和鼠标指针图片替换

AI导航烘培 还不清楚怎么用的可以看我另一篇文章 零基础带你从小白到超神29——导航系统 将地形调成静态导航的 选中地形,设置为可行区域 点击烘培 可爬坡改为30度,就会发现坑就变为不可行区域了 选择所有的树,为不可行区域,点击烘培 给主角人物添加导航组件

Kafka3.0.0版本——生产者数据可靠性

目录 一、ACK应答原理1.1、应答级别1.1.1、acks 01.1.2、acks 11.1.3、acks -1&#xff08;all&#xff09; 1.2、问题思考 二、数据可靠性2.1、数据可靠性分析2.2、 数据完全可靠条件2.3、ACK应答级别可靠性总结 三、数据可靠性代码示例 一、ACK应答原理 1.1、应答级别 1…

一日一题:第十二题---模拟散列表(三种方法!!)

​作者&#xff1a;小妮无语 专栏&#xff1a;一日一题 &#x1f6b6;‍♀️✌️道阻且长&#xff0c;不要放弃✌️&#x1f3c3;‍♀️ 今天来给大家介绍的是简单的Hash表的应用 目录 关于哈希的知识点 题目描述&#xff08;模拟散列表&#xff09; 代码 1&#xff08;拉链…

基于GPT-4的神仙插件Bito,亲测好用

基于GPT-4的神仙插件&#xff0c;无需魔法,目前免费 一、Bito 简介 最近发现一个可以有效提升coding效率的插件神器&#xff0c;截止当前(20230425)已有65k的下载量了&#xff01; 类似与Cursor一样&#xff0c;可以使用AI辅助写代码&#xff0c;但是又解决Cursor没有语法提…

力扣刷题day35|416分割等和子集

416. 分割等和子集 力扣题目链接 给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集&#xff0c;使得两个子集的元素和相等。 示例 1&#xff1a; 输入&#xff1a;nums [1,5,11,5] 输出&#xff1a;true 解释&#xff1a;数组可以分割…

keil设置程序起始地址及生成bin文件的方法

一.keil设置程序起始地址 1.1FLASH APP 的起始地址设置 随便打开一个之前的实例工程&#xff0c;点击 Options for Target→Target 选项卡 默认的条件下&#xff0c;图中 IROM1 的起始地址&#xff08;Start&#xff09;一般为 0X08000000&#xff0c;大小&#xff08;Size&a…

通用el-table 修改样式

通用el-table 修改样式 el-table实现下图效果: <template><div class"contentbox"><el-table:data"tableData"height"310"style"width: 40%"highlight-current-rowcurrent-change"handleCurrentChange"&g…

利用Floodlight进行DDOS攻击防御实验笔记

Floodlight Floodlight是Apache授权并基于JAVA开发的企业级OpenFlow控制器&#xff0c;当前最新版本是1.2。 Floodlight OpenFlow Controller -ProjectFloodlight&#xff1a;http://www.projectfloodlight.org/floodlight/ 流表 把同一时间&#xff0c;经过同一网络中具有某种…

线程同步方式之二条件变量

Linux线程同步方法之二 条件变量 饥饿状态&#xff1a;由于线程A频繁地申请/释放锁&#xff0c;而导致其他线程无法访问临界资源的情况。 同步synchronized&#xff1a;在保证数据安全的前提下&#xff0c;让线程能够按照某种特定的顺序访问临界资源&#xff0c;从而有效避免…

Spring Security实战(九)—— 使用Spring Security OAuth实现OAuth对接

一、OAuth2.0介绍 OAuth2.0是一种授权协议&#xff0c;允许用户授权第三方应用程序代表他们获取受保护的资源&#xff0c;如个人信息或照片等。它允许用户授权访问他们存储在另一个服务提供商上的资源&#xff0c;而无需将其凭据共享给第三方应用程序。OAuth2.0协议建立在OAuth…

直升机空气动力学基础--004翼型的阻力

来源 1. 空气的粘性 2.阻力的产生 3.形成因素 4.阻力系数曲线

LeetCode-242. 有效的字母异位词

题目链接 LeetCode-242. 有效的字母异位词 题目描述 题解 题解一&#xff08;Java&#xff09; 作者&#xff1a;仲景 首先&#xff0c;满足条件的情况下&#xff0c;两个字符串的长度一定是相等的&#xff0c;不相等一定不满足条件 使用Hash表来存储字符串s中各个字符出现的…

回溯算法——我欲修仙(功法篇)

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【❤️我欲修仙】 系列文章目录 第一章 ❤️ 学习前的必知知识 第二章 ❤️ 二分查找 文章目录 系列文章目录回溯算法&#x1f914;&#x1f914;&#x1f914;回溯算法一般可以解决的问题回溯算法的实现回…

Python语言简介

B站讲解视频&#xff1a;https://www.bilibili.com/video/BV1Mv4y1n7n8/?vd_source515e6808c21c69114a4fae34589dfb0e Python是什么 Python是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。具有很强的可读性&#xff0c;相比其他语言经常使用英文关键字&a…

为什么有时候磁珠会使电源的纹波变大

电路设计时&#xff0c;我们常常在芯片电源的输入放一个磁珠和电容&#xff0c;用以滤除电源上的高频噪声。 但是有时候会发现&#xff0c;加了磁珠后&#xff0c;芯片电源输入处纹波竟然变大了&#xff0c;超出了电源纹波范围&#xff0c;导致芯片工作异常。 把磁珠换成0R电阻…

论文阅读:Heterogeneous Graph Contrastive Learning for Recommendation(WSDM ’23)

论文链接 Motivation&#xff1a; 在推荐系统中&#xff0c;图神经网络在建模图结构数据上已经变成一个强有力的工具。但是现实生活的推荐语义通常涉及异质关系&#xff08;像用户的社交关系&#xff0c;物品知识关系的依赖&#xff09;&#xff0c;这些都包含丰富的语义信息…